着色器的编译和屏幕上面绘图

   关于opengl es的着色器语言,我推荐一个地址:http://imgtec.eetrend.com/blog/1948,这篇文章写的相当不错,大家要是有兴趣可以去看一下。

    我在这里简单总结一下,uniform在着色器中是只读的,不能被修改,它的值只能被opengl es的API注入。Attribute相当于opengl es的API向顶点着色器注入数据的入口,它与uniform的不同之处在于:uniform是全局常量,该全局性对顶点着色器与片元着色器均可见;Attributes是针对每一个顶点的输入数据,而且只能在顶点着色器中使用。varying用于从顶点着色器向片段着色器传递数据,在光栅化阶段,varying变量会被做线性插值处理。

     我们接着讲对着色器的编译。

     在Android里面,着色器文件一遍都放在raw文件夹下面,因此我们要先把内容读取到内存中,接下来的步骤如下:

      1.创建新的着色器对象。

          int shaderID = GLES20.glCreateShader(type);

        这里的type可以代表顶点着色器的 GLES20.GL_VERTEX_SHADER,和片段着色器的GLES20.GL_FRAGMENT_SHADER。

     2.上传和编译着色器的源代码

         GLES20.GLES20.glShaderSource(shaderID, shaderCode);
        GLES20.glCompileShader(shaderID);

      这里的shaderCode表示从raw文件夹下读取的顶点着色器或片段着色器的字符串内容。

     3.对顶点着色器和片段着色器执行第一步和第二步的操作。

     4.新建一个opengl程序,注意,这里的程序指的是opengl中的组件。

        int programID = GLES20.glCreateProgram();

      5.将我们之前创建的顶点着色器和片段着色器的ID附加到这个opengl的程序上。

       GLES20.glAttachShader(programID, vertexShaderID);
       GLES20.glAttachShader(programID, fragmentShaderID);

      6.链接程序,把顶点着色器和片段着色器链接起来。

       GLES20.glLinkProgram(programID);

       7.使用我们创建的opengl程序

        GLES20.glUseProgram(programID);

        然后我们讲讲如何将数据通过opengl es接口注入到着色器当中去。我们以下边的着色器为例:

顶点着色器

attribute vec4 a_Position;

void main()
{
    gl_Position = a_Position;
}

片段着色器:

precision mediump float;

uniform vec4 u_Color;

void main()
{
    gl_FragColor = u_Color;
}

        给uniform属性注入数据:

        1. GLES20.获得uniform的位置

         String U_COLOR = "u_Color";

         int  colorPosition = GLES20.glGetUniformLocation(program, U_COLOR);

         2.把数据传递给uniform

         GLES20.glUniform4f(colorPosition, 1, 1, 1, 1);

         给Attribute属性注入数据:

         1.获得属性的位置

         String A_POSITION = "a_Position";

         positionLocation = GLES20.glGetAttribLocation(program, A_POSITION);

         2.关联属性与顶点数据的数组

          GLES20.glVertexAttribPointer(positionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, 0, vertexArray);

        3.启动该顶点数组

        GLES20.glEnableVertexAttribArray(positionLocation);

        此外还有关于绘制部分,绘制可以分为三种绘制方式:数组绘制,顶点索引绘制,缓冲区绘制

        1.数组绘制,GLES20.glDrawArrays(type, startPosition, count);

        2.顶点 索引绘制,GLES20.glDrawElements(type, indexCount, dataType, indexArray);

        3.缓冲区绘制分为缓冲区对象的创建和缓冲区的绘制。缓冲区分为顶点缓冲区和索引缓冲区。

         比如顶点缓冲区对象的创建:

              int buffers[] = new int[1];

              GLES20.glGenBuffers(length,)//生成缓冲区

              bufferID = buffers[0];

              GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);//绑定缓冲区

               FloatBuffer vertexArray = ................//生成floatBuffer,并且注入数据

                vertexArray.position(0);

           GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexArray.capacity()*BYTES_PER_FLOAT, vertexArray, GLES20.GL_STATIC_DRAW); //将native中的数据传入到GPU

               GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);//解除绑定

        创建索引缓冲区对象和创建顶点缓冲区对象其实差不多,只需要对上面的代码做如下改动:

              1.使用short[]和ShortBuffer作为类型             

              2.使用GLES20.GL_ELEMENT_ARRAY_BUFFER,而不是GLES20.GL_ARRAY_BUFFER

           通过缓冲区绘制,可以使用GLES20.glDrawElements(),只是使用前和使用后需要绑定和解除缓冲区的绑定。

猜你喜欢

转载自my.oschina.net/u/1273706/blog/752471
今日推荐