0评论

OpenGL ES 颜色和着色

文章来自https://blog.csdn.net/pangrui201/article/details/75269092 2019-03-15 14浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏开发行业精英群711501594

上一篇给大家介绍了OpenGL ES 着色器原理介绍及使用,相信大家对于着色器原理和过程有了较为详细的理解,并且重点讲解了使用顶点着色器来实现opengl基本图元(点,直线,三角形)的位置,那么本节讲解opengl es对颜色的绘制。

三角形扇:

之前讲解如果想描述一个长方形可以用两个三角形来描述,比如:
// Triangle 1
-0.5f, -0.5f,
0.5f, 0.5f,
-0.5f, 0.5f,
// Triangle 2
-0.5f, -0.5f,
0.5f, -0.5f,
0.5f, 0.5f,
……

很容易发现有很多坐标重复的问题,特别是复杂图形这样组成坐标的数组里有大量的数据冗余,为了解决这个问题提出了三角形扇的概念。如下图:

我们在桌子中间引入一个点(0,0)即1位置作为起始点,使用相邻两个顶点创建第一个三角形,接下来的每个顶点都会创建一个三角形,围绕起始点按照扇形展开,当最后重复第二个点时我们知道绘制完成。坐标位置数组也变成如下:
    /*
        float[] tableVerticesWithTriangles = {
            // Triangle Fan
               0,     0,            
            -0.5f, -0.5f,             
             0.5f, -0.5f,
             0.5f,  0.5f,
            -0.5f,  0.5f,            
            -0.5f, -0.5f,
            // Line 1
            -0.5f, 0f, 
             0.5f, 0f,
            // Mallets
            0f, -0.25f,
            0f,  0.25f 
        };*/

在本例AirHockeyRenderer的onDrawFrame中,代码如下:
 /**
     * OnDrawFrame is called whenever a new frame needs to be drawn. Normally,
     * this is done at the refresh rate of the screen.
     */
    @Override
    public void onDrawFrame(GL10 glUnused) {
        // Clear the rendering surface.
        glClear(GL_COLOR_BUFFER_BIT);
        // Draw the table.        
        glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
        // Draw the center dividing line.        
        glDrawArrays(GL_LINES, 6, 2);
        // Draw the first mallet.        
        glDrawArrays(GL_POINTS, 8, 1);
        // Draw the second mallet.
        glDrawArrays(GL_POINTS, 9, 1);
    }

glDrawArrays(GL_TRIANGLE_FAN, 0, 6);指定用6个坐标值绘制三角形扇。

颜色属性:

我们要为每个顶点增加颜色属性代码如下:
       //
        // Vertex data is stored in the following manner:
        // 
        // The first two numbers are part of the position: X, Y
        // The next three numbers are part of the color: R, G, B
        //
        float[] tableVerticesWithTriangles = {   
            // Order of coordinates: X, Y, R, G, B
            // Triangle Fan
               0f,    0f,   1f,   1f,   1f,         
            -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,            
             0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
             0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
            -0.5f,  0.5f, 0.7f, 0.7f, 0.7f,
            -0.5f, -0.5f, 0.7f, 0.7f, 0.7f,
            // Line 1
            -0.5f, 0f, 1f, 0f, 0f,
             0.5f, 0f, 1f, 0f, 0f,
            // Mallets
            0f, -0.25f, 0f, 0f, 1f,
            0f,  0.25f, 1f, 0f, 0f
        };

可以看到为每个顶点增加了三个分量坐标分别对应颜色的红,绿,蓝分量,每个分量值在0-1范围。

打开simple_fragment_shader.glsl和simple_vertex_shader.glsl我们发现里面没有了uniform属性而是varying。varying的意思就是把给他的值进行混合,比如在第一个顶点是红色,第二个顶点是绿色则使用varying后的效果就是组成第一第二顶点连线的直线离第一个顶点越近越呈现红色,直线离第二个点越近越呈现绿色,而且这是一种平滑按比例呈现的效果,用公式表达如下:

这个公式是应用于每个颜色分量的。如下图是从红到绿的直线,

则线上各个颜色分量如下图


上面是直线按照线性比例来实现这种颜色的平滑变化,如果是三角形则是按照构成三角形面积的分量,原理相似。

值得注意的是在代码上引入了 private static final int STRIDE =

(POSITION_COMPONENT_COUNT + COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;因为我们坐标和颜色使用的是同一个缓冲器(这样有利于节省内存,性能)所以我们需要用STRIDE 来表示内存字节偏移量。所以在

onSurfaceCreated里面指定位置的时候使用了这个偏移量

glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,

false, STRIDE, vertexData);指定颜色的时候也使用了这个偏移量STRIDE ,
vertexData.position(POSITION_COMPONENT_COUNT);        
        glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT, 
            false, STRIDE, vertexData);  

本节我们不在使用uniform故在onDrawFrame里面也不需要glUniform4f方法。同时我们也已经把顶点数据和颜色关联起来了,故只需要glDrawArrays方法就能搞定。

本文代码路径:
https://github.com/pangrui201/OpenGlesProject/tree/master/OpenGlesProject_lesson3