zoukankan      html  css  js  c++  java
  • OpenGL三维镂垫

    2015-12-12帮舍友尝试这个代码的时候发现舍友的会出现No GLSL support 后来发现舍友的版本2.0、2.1才能用
    舍友的是glutInitContextVersion(3, 1);改为glutInitContextVersion(2, 1);.所以用的话,如果闪退,可以尝试修改一下版本号
    【关于版本的更多知识http://blog.csdn.net/ym19860303/article/details/44115135】
    整个代码资源:http://download.csdn.net/detail/u014646950/9350045
    代码有书上的+网上的+我自己码的
    用vs2013社区英语版可以得结果,但是有一点小故障,如下。
    代码批注部分贡献者http://www.mamicode.com/info-detail-504374.html
     

     

     
    首先要会创建consoleApplication,会3个新建文本并重命名,下载配置头文件
    相关经验http://jingyan.baidu.com/article/3c48dd34873509e10be35880.html
    或者

     http://xujiayu317.blog.163.com/blog/static/25475209201591393731494/?newFollowBlog

     
    在文件名字为  fshader3.glsl里面填上如下(图代码)
    in vec4 color;
    out vec4 YanColor;
    void main()
    {
       YanColor =color;
    }
    /*@注释上下代码功能等价
    in vec4 color; 
    void main()
    {
       gl_FragColor =color;
    }*/
    在文件名字为  vshader3.glsl里面填上如下(图代码)
    in vec4 vPosition;
    in vec4 vColor;
    out vec4 color;
    void main()
    {      
        gl_Position = vPosition; 
    color=vColor;
    }
     
     

     在文件名字为  ogl3.cpp里面填上如下(图代码)

     
     
    #include <iostream>
    #include<glew.h> 
    #include<freeglut.h>   
    #include<gl.h> 
    #pragma comment(lib,"glew32.lib")
    #pragma comment(lib,"freeglut.lib")
    #pragma comment(lib,"glut32.lib")
    //#pragma comment(lib,"opengl.lib")
     
    /*/#define BUFFER_OFFSET(offset)((GLint *)NULL+offset)用这一个会变成奇怪的颜色*/
    #define BUFFER_OFFSET(bytes)((GLvoid *)(bytes))/*/这个是在书上的,这种竟然没有在附录的代码里面*/
    const int NumTimesToSubdivide = 5;/*/这里是递归的次数*/
    const int NumTetrahedrons = 1024;            /*4^5 tetrahedrons;根据上面递归五次,所以就是4的五次方个四面体*/
    const int NumTriangles = 4 * NumTetrahedrons;  /*/ 4 triangles / tetrahedron每个四面体有4各面*/
    const int NumVertices = 3 * NumTriangles;      /*/ 3 vertices / triangle 每个面有3个顶点*/
     /*@注释 *这个看书上说是在vec.h的头文件里面,可是我电脑上没有,
     *我只知道,书上是说vec是甚么向量,
     *vec2是连续两个float,
     *vec3是连续三个float,
     *vec4是连续四个float,
     *我尝试自己弄这个结构体,并有构造函数初始化。
     */
    struct vec3
    {
    GLfloat x, y, z;
        vec3(){}
    vec3(GLfloat hong, GLfloat lv, GLfloat lan)
    :x(hong), y(lv), z(lan) {}
    vec3 operator +(vec3 other)const
    {
    vec3 temp(x + other.x,y + other.y,z + other.z); 
    return temp;
    }
    vec3 operator/(GLint t)
       {
    vec3 temp(x/t, y/t, z/t);
    return temp; 
        }
    }; 
    typedef ::vec3 point3;  
    typedef ::vec3 color3;/*书上说甚么opengl习惯性这样,对于我来说,觉得这样很啰嗦,明明都是同一个类型*/
    point3 points[NumVertices]; 
    color3 YanSe[NumVertices];
    color3 vertex_Yase[4] =
    {
    color3(0.6f, 0.7f, 0.0f),
    color3(0.0f, 1.0f, 0.0f),
    color3(0.0f, 0.5f, 0.2f),
        color3(0.4f, 0.0f, 0.0f) 
    /*四面体有四个三角面,所以就设置了四种颜色*/
    };
    int  Index = 0; 
    //----------------------------------------------------------------------------
     
    int colorIndex;
     
    /*@注释*对于由a、b、c确定的一个三角面,三个点设置同一个颜色才会是纯色的,否则是渐变的代码
    */
    void
    triangle(const vec3& a, const vec3& b, const vec3& c)
     
    {
    YanSe[Index] = vertex_Yase[colorIndex];
    points[Index++] = a; 
    YanSe[Index] = vertex_Yase[colorIndex];
    points[Index++] = b;
    YanSe[Index] = vertex_Yase[colorIndex];
    points[Index++] = c;
    /*@注释*下面是渐变代码
    YanSe[Index] = vertex_Yase[0];
    points[Index++] = a;
    YanSe[Index] = vertex_Yase[1];
    points[Index++] = b;
    YanSe[Index] = vertex_Yase[2];
    points[Index++] = c;
    */
     
    }
     
    //----------------------------------------------------------------------------
    /*@说明*下面的colorIndex用于给
    *最终的每一个四面体的
    *四个三角面triangle涂上不同的纯色,
    *如果要用渐变,可以去掉colorIndex
    */
    void
    tetra(const vec3& a, const vec3& b, const vec3& c, const vec3& d)
    {
    colorIndex = 0;
    triangle(a, b, c);
    colorIndex = 1;
    triangle(a, c, d);
    colorIndex = 2;
    triangle(a, d, b);
    colorIndex = 3;
    triangle(b, d, c);
    }
     
    //----------------------------------------------------------------------------
     
    /*@注释*递归划分*/
    void
    divide_tetra(const vec3& a, const vec3& b,
    const vec3& c, const vec3& d, int count)
    {
    if (count > 0) {
    vec3 v0 =(a + b) / 2;
    vec3 v1 = (a + c) / 2;
    vec3 v2 = (a + d) / 2;
    vec3 v3 = (b + c) / 2;
    vec3 v4 = (c + d) / 2;
    vec3 v5 = (b + d) / 2;
    divide_tetra(a, v0, v1, v2, count - 1);
    divide_tetra(v0, b, v3, v5, count - 1);
    divide_tetra(v1, v3, c, v4, count - 1);
    divide_tetra(v2, v5, v4,d , count - 1);
    }
    else {
    tetra(a, b, c, d);    // draw tetrahedron at end of recursion
    }
    }
     
    //----------------------------------------------------------------------------
    /*@注释*读取文件,以字符串的形式返回*/
    static char*  readShaderSource(const char *file)
    {
    FILE *fp;   
    if (file == NULL)
    return NULL;
    fopen_s(&fp,file, "rb"); /*@注释,我这里是用的vs2013,vs2013不让用fp=fopen(file, "rb");*/
    if (fp == NULL)return NULL;
    fseek(fp, 0, SEEK_END);/*@注释:将fp所指向的文件位置指针移到以SEEK_END的基准位置,以0为位移量位置*/
    GLsizei length = ftell(fp);
    rewind(fp);/*@注释:将fp指示文件中位置的的指针置于文件的开头位置,并清楚文件爱你结束标志和错误标志*/
    GLchar * shaderChan =new  GLchar[length + 1];
    fread(shaderChan, sizeof(char), length, fp);
    shaderChan[length] = '';
    if (shaderChan == NULL)
    {
    delete[]shaderChan;//删除着色器字符串 
    std::cerr << file << "error" << std::endl;
    exit(EXIT_FAILURE);
    }
    fclose(fp);
    return shaderChan;
    }
    /*@注释*创建并编译着色器*/
     GLuint buildShader(const char* FileName, GLenum shaderType) {
    GLchar*shaderChan = readShaderSource(FileName);//以字符串的形式读取文件
     
    GLuint shaderHandle = glCreateShader(shaderType);
    glShaderSource(shaderHandle, 1,&shaderChan, NULL);
    //(const GLchar**)把着色器对象与相应的着色器字符相关联
    delete[]shaderChan;//删除着色器字符串
     
    glCompileShader(shaderHandle); //编译着色器
     
    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
    // 若失败...
    std::cerr << FileName << "failed to compile:" << std::endl;
     
    GLint logsize;
    glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &logsize);
    char*logMsg = new char[logsize+1];
    glGetShaderInfoLog(shaderHandle, logsize, NULL, logMsg);
    std::cerr << logMsg << std::endl;
    delete[] logMsg;
    exit(EXIT_FAILURE);
    }
    return shaderHandle;
     /*@注释*初始化着色器*/
     GLuint InitShader(const char *vertexShaderFilename, const char *fragmentShaderFilename)
    {    
    /*创建顶点着色器对象和片元着色器对象*/ 
    GLuint vertexShaderHandle = buildShader(vertexShaderFilename, GL_VERTEX_SHADER);
    GLuint fragmentShaderHandle = buildShader(fragmentShaderFilename, GL_FRAGMENT_SHADER);
     
    GLuint programHandle = glCreateProgram();
    glAttachShader(programHandle, vertexShaderHandle);
    glAttachShader(programHandle, fragmentShaderHandle);
     
    glLinkProgram(programHandle);
     
    GLint linkSuccess; 
    glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) {
    // 判断连接是否成功...
    std::cerr <<  "shader program failed to link:" << std::endl;
    GLint logsize;
    glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logsize);
    char*logMsg = new char[logsize];
    glGetProgramInfoLog(programHandle, logsize, NULL, logMsg);
    std::cerr << logMsg << std::endl;
    delete[]logMsg;
    exit(EXIT_FAILURE); 
    }
     
    glUseProgram(programHandle);
    return programHandle;
    }
     /*@注释*初始化GLSL*/
    void
    init(void)
    /*@注释:初始化四个顶点*/
    vec3 vertices[4] = {
    vec3(1.0, -1.0,0.0),
    vec3(-1.0,-1.0, 0.0),
    vec3(0.0,1.0, 0.0),
    vec3(0.0, 0.0, 0.6)
    };
    /*@注释:调用递归划分Subdivide the original tetrahedron*/
    divide_tetra(vertices[0], vertices[1], vertices[2], vertices[3],
    NumTimesToSubdivide);
     
    /*@注释: 创建一个顶点数组对象*/
    GLuint vao;
    glGenVertexArrays(1, &vao);/*注释:顶点数组对象标识申请,管理着顶点属性的集合*/
    glBindVertexArray(vao);/*@注释:在这里将做3个事情:1、如果参数是非0,并且是glGenvertexArrays()返回的新值,未经glBindVertexArray的
             *那么他将创建一个新的顶点数组对象(这里才真正创建),并且与其名称关联起来。
             *2、如果绑定包已经创建过的顶点数组对象,那么该顶点数组对象将被激活。这便于帧间切换绘制数据
             *3、如果输入参数是0那么OpenGL将不再使用程序所分配的任何顶点数组对象,并且将渲染状态重设为默认值。*/
     
    /*@注释 创建并初始化一个缓冲区对象*/
    GLuint buffer;
    glGenBuffers(1, &buffer);/*注释:申请顶点缓存对象标识。*/
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    /*注释:申请顶点缓存对象标识。
    *指定顶点缓存对象的用途,GL_ARRAY_BUFFER表示顶点数据。之力glBindBuffer同样完成了3项工作:
    *1、如果是第一次绑定对象(第二个参数),他是一个非0的无符号整型,那么将创建一个与名称对应的(第一个参数)新的缓存对象
    *2、如果绑定到一个已经创建的缓存对象,那么她将被激活为当前使用对象。
    *3、如果第二个参数是0,那么OpenGL不再为当前名称(第一个参数)应用任何缓存对象。*/
    glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(YanSe), NULL, GL_STATIC_DRAW);
    /*注释:glBufferData( GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage )
    *向缓存对象输入数据的环节:, glBufferData是真正为缓存对象分配存储空间。
    *1、target目标:顶点数据(GL_ARRAY_BUFFER)、索引数据(GL_ELEMENT_ARRAY_BUFFER)、OpenGL的像素数据(GL_PIXEL_UNPACK_BUFFER)、
    *从OpenGL中获取的像素数据(GL_PIXEL_PACK_BUFFER)、缓存之间复制数据(GL_COPY_READ_BUFFER/GL_COPY_WRITE_BUFFER)、
    *纹理缓存中存储的纹理数据(GL_TEXTURE_BUFFER)、一致性变量(GL_UNIFORM_BUFFER)
    *2、size:表示缓存数据的总量,字节数。
    *3、data:是客户端应用程序的内存指针,数据的来源。要么是NULL,否则如果合法则将会有size大小的数据从客户端拷贝到服务端(显卡内存),如果data数据未初始化
    *将保留size大小的内存备用。
    *4、usage:用于设置分配数据之后的读取和写入方式,这关系都OpenGL对于缓存对象存储数据中的最优分配方案的管理。说白了,这个参数试图向OpenGL提供
    *这堆数据的用途,是否只读,是否静态,用于绘制?拷贝?通过内置标识符的方式告诉OpenGL,OpenGL根据信息来优化内存分配,管理。*/
    glBufferSubData(GL_ARRAY_BUFFER, 0,sizeof(points) ,points);  
    /*@注释*glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex_positions), vertex_positions );
    *用数据部分替换目标缓存的内容,注意在glBufferData中我们的data为NULL,所以在这里才真正初始化。
    *这个接口使得我们的操作更为灵活,对数据的组织更为紧凑,因为我们只为顶点坐标数据和颜色数据分配了一块连续的空间。
    *第二个参数是偏移地址,第三个参数是替换数据的大小,第四个参数是客户端内存指针,也就是数据源。
    *需要注意的是不可超越glBufferData保留的内存。
    *到这里关于缓存对象的操作只是最简单的部分,还有很多OpenGL接口供我们去灵活控制,优化。*/
    glBufferSubData(GL_ARRAY_BUFFER,  sizeof(points),sizeof(YanSe) ,YanSe); 
    /*@注释*glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertex_positions), sizeof(vertex_colors), vertex_colors);*/
     
     
    /*@注释*载入着色器并使用所得到的着色器程序*/
    GLuint program = InitShader("vshader3.glsl", "fshader3.glsl");
    glUseProgram(program);
     
    /*@注释* 初始化顶点着色器中的顶点位置属性*/
    GLuint loc = glGetAttribLocation(program, "vPosition");
    glEnableVertexAttribArray(loc);
    /*@注释*参数对应于glVertexAttribPointer的index.也就是location值,与这个值相关联的定点数组将被启用*/
    glVertexAttribPointer(loc, 3, GL_FLOAT, GL_FALSE, 0,
    BUFFER_OFFSET(0));
    /*@注释* / glVertexAttribPointer(GLuint index, Glint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer)
    //index:着色器中属性的位置,还记得layout(location = 0)的定义么,就是这个location.
    //size:表示每个顶点该属性需要更新的分量数目,这里顶点坐标为4个float,所以就是4.值的范围可以是1,2,3,4或GL_BGRA
    //type:数据类型
    //normalized:使用顶点数据之前是否要进行归一化。
    //stride:每组数据之间是否要进行偏移,如果是0则,数据是紧密的。
    //pointer:表示缓存对象中,从开始位置开始计算数组数据的偏移值*/
     
     
    GLuint se = glGetAttribLocation(program, "vColor");
    glEnableVertexAttribArray(se);/*@注释*启用颜色属性数组 */
    glVertexAttribPointer(se, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points)));
     
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);/*@注释*背景色 */
    /*@注释*建立视图*/
    glLoadIdentity();
      glMatrixMode(GL_PROJECTION); 
    glEnable(GL_DEPTH_TEST);/*@注释*开启深度缓存测试*/
    glEnable(GL_CULL_FACE);///*@注释*启动多边形剔除功能*/
     //*@注释*这里glortho也可以为gluOrtho2D( 1.0, 1.0,1.0, 0.0);*/
     glOrtho(1.0,0.0,0.0,1.0,0.0,1.0); 
    }
     
    //----------------------------------------------------------------------------
     
    void
    display(void)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glDrawArrays(GL_TRIANGLES, 0, NumVertices);
    glFlush(); 
    }
     
    //----------------------------------------------------------------------------
     
    void
    keyboard(unsigned char key, int x, int y)
    {
    switch (key) {
    case 033:
    exit(EXIT_SUCCESS);
    break;
    }
    }
    void changeSize(int w, int h)
    {
    /*@注释:重新定义视口*/
    glViewport(0, 0, w, h);
    /*@注释:重新设置投影变换*/
    if (h == 0) h = 1;/*@注释:防止高为0产生除0错误*/
    float ratio = 1.0 * w / h;/*@注释:宽高比*/
    glMatrixMode(GL_PROJECTION);/*@注释:当前矩阵设为投影矩阵*/
    glLoadIdentity();/*@注释:清空投影矩阵*/
    gluPerspective(45, ratio, 1, 1000);/*@注释:重设投影矩阵*/
    /*@注释:模型视点变换*/
    glMatrixMode(GL_MODELVIEW);/*@注释:当前矩阵设为模型视点矩阵*/
    }
    //----------------------------------------------------------------------------
     
    int 
    main(int argc, char **argv)
    {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE| GLUT_RGBA  | GLUT_DEPTH);/*@注释:这里要GLUT_SINGLE*/
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(540, 540);
    glutInitContextVersion(3, 1);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE); 
     
    glutCreateWindow("Simple GLSL example");  
    /*@注释:窗口大小变化时的处理函数 */
    glewExperimental = GL_TRUE;
    glewInit();
     
    /*@注释:检测是否支持基本的顶点着色器和片元着色器*/
    if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
    {
    printf("Ready for GLSL ");
    }
    else
    {
    printf("No GLSL support ");
    exit(1);
    }
        init();
      glutDisplayFunc(display); 
    glutIdleFunc(display);
    glutReshapeFunc(changeSize);/*@注释:注册窗口大小改变时的回调函数 changeSize*/ 
    glutKeyboardFunc(keyboard); 
     
    glutMainLoop(); 
    return 0;
    }  
     
     
    上面是这里代码的效果图
      
     
     
     
     
     更改点坐标和颜色可获得其他效果图
     
     
     
     
  • 相关阅读:
    SQL Server 2005的通用分页存储过程
    沉默的羔羊 赵传
    [转]Ubuntu 10.04 安装 codeblocks10.051 过程详细解析
    VMware7.1.5虚拟机安装Ubuntu 11.10使用share folders共享目录
    【转】libmemcached在windows下的PHP扩展(php_memcached.dll下载)
    Ubuntu升级之后The disk drive for / is not ready yet or not present的解决方法
    基于libmemcached,php扩展memcached的安装
    ubuntu configure的问题解决
    Ubuntu安装CodeBlocks相关问题(不能编译或者编译通过但不能生成可执行文件)
    ubuntu笔记
  • 原文地址:https://www.cnblogs.com/xujiayu/p/4881226.html
Copyright © 2011-2022 走看看