zoukankan      html  css  js  c++  java
  • 3D Computer Grapihcs Using OpenGL

    上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的。

    这节我们将为这两个三角形进行更加自由的着色——五个顶点各自使用不同的颜色。

    要实现这个目的,我们分两步进行,首先

    在顶点数组里增加数据用来表示颜色

    修改sendDataToOpenGL()函数中的verts数组:

     1     GLfloat verts[] =
     2     {
     3         +0.0f, +0.0f,        //Vertex 0
     4         +1.0,  +0.0, +0.0f,    //Color  0
     5         +1.0f, +1.0f,        //Vertex 1
     6         +0.0,  +1.0, +0.0f,    //Color  1
     7         -1.0f, +1.0f,        //Vertex 2
     8         +0.0,  +0.0, +1.0f,    //Color  2
     9         -1.0f, -1.0f,        //Vertex 3
    10         +0.5f, +0.3f, +0.1f,//Color  3
    11         +1.0f, -1.0f,        //Vertex 4
    12         +0.1f, +0.4f, +0.2f,//Color  4
    13     };

    增加了5*3=15个元素,穿插在每个顶点位置后,表示颜色的r,g,b值。现在每5个数据描述一个顶点,前两个表示顶点位置,后三个表示颜色。

    为了把这些数据输入到GPU,我们还需要启用第二个通道。(我们之前只启用了一个通道0)

    修改sendDataToOpenGL()函数:

     1 void MyGlWindow::sendDataToOpenGL()
     2 {
     3     GLfloat verts[] =
     4     {
     5         +0.0f, +0.0f,        //Vertex 0
     6         +1.0,  +0.0, +0.0f,    //Color  0
     7         +1.0f, +1.0f,        //Vertex 1
     8         +0.0,  +1.0, +0.0f,    //Color  1
     9         -1.0f, +1.0f,        //Vertex 2
    10         +0.0,  +0.0, +1.0f,    //Color  2
    11         -1.0f, -1.0f,        //Vertex 3
    12         +1.0f, +1.0f, +0.0f,//Color  3
    13         +1.0f, -1.0f,        //Vertex 4
    14         +0.0f, +1.0f, +1.0f,//Color  4
    15     };
    16 
    17     GLuint vertexBufferID;
    18     glGenBuffers(1, &vertexBufferID);
    19     glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    20     glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
    21 
    22     GLushort indices[] =
    23     {
    24         0,1,2,
    25         0,3,4,
    26     };
    27     GLuint indexBufferID;
    28     glGenBuffers(1, &indexBufferID);
    29     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
    30     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    31 
    32     glEnableVertexAttribArray(0);
    33     glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
    34 
    35     glEnableVertexAttribArray(1);
    36     glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (char*)(sizeof(GLfloat) * 2));
    37 }

    注意第33行,函数glVertexAttribPointer函数第三个参数变成了sizeof(GLfloat)*5,原因是Stride变成了5个float,如前所述,5个元素描述一个顶点。

    另外增加了第35和36行,35行开启了通道1,这个1和前面的0是和Shader中的layout (location = x)对应的,稍后进行详解。

    第36行glVertexAttribPoint函数的第一个参数对应35行的1, 第二个参数表示三个元素为一组。

    需要特别注意的是最后一个参数,它表示本组数据的起始偏移值,本组数据的第一个位置在代码中的第六行,它前面有2个元素,所以这里是sizeof(GLfloat)*2,但是由于该函数第四个参数的类型是char*类型,我们只能强制转换为char * 。

    然后我们需要

    修改Shader

     1 const char* vertexShaderCode =
     2 "    #version 430                            
    "
     3 "                                            
    "
     4 "    in layout(location=0) vec2 position;    
    "
     5 "    in layout(location=1) vec3 vertexColor; 
    "
     6 "                                            
    "
     7 "    out vec3 passingColor;                  
    "
     8 "                                            
    "
     9 "    void main()                             
    "
    10 "    {                                       
    "
    11 "      gl_Position= vec4(position,0.0,1.0);  
    "
    12 "      passingColor= vertexColor;            
    "
    13 "    }                                       
    "
    14 "                                            
    "
    15 "                                            
    ";
    16 
    17 const char* fragmentShaderCode =
    18 "    #version 430                            
    "
    19 "                                            
    "
    20 "    in vec3 passingColor;                   
    "
    21 "    out vec4 finalColor;                    
    "
    22 "                                            
    "
    23 "                                            
    "
    24 "    void main()                             
    "
    25 "    {                                       
    "
    26 "      finalColor = vec4(passingColor,1.0);  
    "
    27 "    }                                       
    "
    28 "                                            
    "
    29 "                                            
    ";

    先看Vertex Shader。

    增加了第5行。

    仔细看一下第4行和第5行,对比sendDataToOpenGL()函数的33和36行, location=0指定了通道0, vec2说明了需要二维向量(2个float),33行函数的前两个参数也分别是0(表示通道0),2(表示两个元素),两者是相对应的。

    ShaderCode的第5行和sendDataToOpenGL()的36行也是对应的。

    再对应verts[]数组对比着看,就会发现其工作原理。verts数组每五个元素为一组,每组的前两个元素将被发送到通道0,后三个元素将被发送到通道1。

    另外Vertex Shader还增加了第7行,这里使用了out关键字定义了一个三维向量passingColor,说明这个参数将被发送出去,传递到渲染管线的下一个环节。而在main中,我们把刚刚从通道2接受到的数据(存在vertexColor里)传递给passingColor。所以说相当于我们没有对通道2传递进来的数据做任何处理,直接发送到下一个环节。

    观察Fragment Shader,我们增加了20行,注意看这行和Vertex Shader的第7行非常相似,除了第一个关键字改成了in。

    这种匹配是GLSL的一种固定模式,上游的out 变量会传递给下游的in变量,只要两者保持一致性。

    在Fragment Shader的main中,我们把最终的颜色输出改成了 vec4(passingColor,1.0),也就是我们把这个颜色表现了出来。

    纵观全局,我们这次做的修改将把verts数组中新增的一些信息传递先传递到Vertex Shader中,然后传递到FragmentShader中,最终输出成顶点的颜色。

    编译运行我们看到两个彩色的三角形:

  • 相关阅读:
    小技巧与阅读感悟
    Android常见漏洞介绍(1):Intent Scheme URL 攻击
    利用Mallet工具自动挖掘文本Topic
    Xie Tao的几个小建议PPT:关于读Paper,如何与他人交流,赶Deadline
    Python解析DNS数据包
    iOS 横竖屏适配 笔记
    多工程联编,cocopods的使用
    Call to unavailable function 'system': not available on iOS
    xxx referenced from: xxx in xxx.o
    YYModel学习总结YYClassInfo(1)
  • 原文地址:https://www.cnblogs.com/AnKen/p/8337825.html
Copyright © 2011-2022 走看看