OpenGL ES 2.0编程基础

来源:互联网 发布:以人为鉴,可以知得失 编辑:程序博客网 时间:2024/06/13 01:54

http://blog.csdn.net/sunqunsunqun/article/details/7649628http://blog.csdn.net/sunqunsunqun/article/details/7649628

http://blog.csdn.net/sunqunsunqun/article/details/7649628

http://blog.csdn.net/sunqunsunqun/article/details/7649628

OpenGL ES 2.0编程基础

分类: OpenGL ES Android 1013人阅读 评论(0) 收藏 举报
编程shaderattributes存储bufferfloat

本人在学WebGL,WebGL的资料很少,由于WebGL是OpenGL ES 2.0的子集,所以先学习一下OpenGL ES 2.0的基础知识。OpenGL中既有固定管线处理流程,也可以使用shader进行可编程的管线处理,OpenGL ES 2.0是完全可编程的管线流程,而没有固定管线流程,这给我们增加了更多的灵活度,以前可以让OpenGL替我们做的事情,现在必须要我们在shader中自己去实现,这可以使我们更深入的理解OpenGL ES 2.0图形绘图流程。

本文参考了http://blog.csdn.net/racehorse/article/details/6593719


1.OpenGL中的图形处理固定管线流程:


现在的显卡允许程序员自己编程实现上述流水线中的两个阶段:

·顶点shader实现顶点变换阶段的功能

·片断shader替代片断纹理化和色彩化的功能


2.OpenGL ES 2.0中的可编程管线流程:



3.顶点着色器:



4.片段着色器:


5.Shader开发流程:

        a.编写vertex Shader和fragment shader源码。

        b.创建两个shader 实例:GLuint glCreateShader(GLenum type); [gl.createShader]

        c.给Shader实例指定源码。 glShaderSource [gl.shaderSource]

        d.编译shaer源码 void glCompileShader(GLuint shader) [gl.compileShader]

        e.创建shader program -- GLuint glCreateProgram(void) [gl.createProgram] 

        f.绑定shader到program 。 void glAttachShader(GLuint program, GLuint shader)。每个program必须绑定一个vertex shader 和一个fragment shader。 [gl.attachShader]         g.链接program 。 void glLinkProgram(GLuint program) [gl.linkProgram]

        h.使用porgram 。 void glUseProgram(GLuint program) [gl.useProgram]

        i.* 对于使用独立shader编译器编译的二进制shader代码,可使用glShaderBinary来加载到一个shader实例中。


6.Uniforms变量:

Uniform变量是OpenGL ES着色器语言中的一种变量类型修饰符。Uniform变量用来存储只读值,这些值通过OpenGL ES 2.0 API传递给着色器。Uniforms常用于存储着色器需要的各种数据,比如变换矩阵、光线参数以及颜色等。输入着色器的常量参数(顶点或者片段)应该被作为Uniform类型传入进去。

  如果顶点着色器和片段着色器被连接到同一个program对象中,它们会分享相同的uniform变量。因此,如果一个Uniform变量在顶点着色器中声明了,并且也在片段着色器中声明了,那么二者的声明必须匹配。当应用程序通过API装载uniform变量时,其值在顶点着色器和片段着色器中均可获得。 Uniform变量常用于在硬件中进行“常量存储”。


7.Attributes变量:

Attribute变量只能够在顶点着色器中使用,用于逐个指定到顶点着色器的输入。Attributes典型的用来存储位置、法线、纹理坐标和颜色。理解的关键在于attributes存储着每个顶点绘制所需要的数据。下面这个例子中,a_position是位置属性,a_texCoord0是纹理坐标属性。

uniform mat4 m_matModelViewProjection;

attribute vec4 a_position;//position attribute

attribute vec4 a_texCoord0;//texture coordinate attribute

varying vec2 v_texCoord;

 

void main(void)

{

    gl_Position =matViewProjection* position;

    v_texCoord =  a_texCoord0;

}

注:gl_Position是内置的变量。


8.Varyings变量:

Varyings变量用来存储顶点着色器的输出,并且也是片段着色器的输入。每个顶点着色器输出需要传递给片段着色器的的数据,这些数据用一个或多个varying变量来声明。这些变量也同时在片段着色器中声明(有着相同的类型),并且在基元的光栅化过程中会进行线性插值。其声明如下所示:

varying vec2 texCoord;

varying vec4 color;

必须在顶点着色器和片段着色器中同时声明varying,且其声明必须完全相同。



9.给shader中的uniform赋值:

uniform vec3 uAmbientColor;这样给uAmbientColor赋值:

ambientColorLocation = gl.getUniformLocation(shaderProgram,"uAmbientColor");

gl.uniform3f( ambientColorLocation, 1.0,1.0,1.0 );

 

uniform bool uUseLighting;这样给uUseLighting赋值:

useLightingLocation = gl.getUniformLocation(shaderProgram,"uUseLighting");

gl.uniform1i(useLightingLocation,要赋值的布尔值);

 

uniform float uAlpha;赋值用到的是

alphaLocation = gl.getUniformLocation(shader, "uAlpha");

gl.uniform1f(alphaLocation,0.7);

 

uniform mat4 mv;这样给mat4赋值:

mvLocation = gl.getUniformLocation(shaderProgram, "mv");

gl.uniformMatrix4fv(mvLocation,false, new Float32Array([…]);

 

总结:uniform赋值时,先从shader中根据uniform变量的名称通过gl.getUniformLocation(shaderName,"uniformName")获取其地址,然后根据地址通过gl.uniform*(…)对其进行赋值。


10.给shader中的attribute赋值:

attribute vec3 position;

var positionLocation = gl.getAttribLocation(shader,"position");

gl.enableVertexAttribArray(positionLocation);

//////////////////////////////////////////////////////////////////

var positionBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

gl.bufferData(gl.ARRAY_BUFFER,newFloat32Array([…]), gl.STATIC_DRAW);

gl.vertexAttribPointer(positionLocation,3, gl.FLOAT, false, 0, 0);

 

与uniform赋值不同,对attribute进行赋值时,在initShaders时,首先要通过gl.getAttribLocation(shader,"attributeName")获取attribute变量的地址,然后通过调用gl.enableVertexAtribArray(attributeLocation)来启用该attribute变量。上面的操作只需要调用一次即可。然后在循环drawScene的时候,如果buffer之前就已经通过gl.bufferData赋值(比如在initialBuffers()的时候对其赋值),如果buffer的值没有改变(比如坐标值未变)那么就不需要在每次渲染的时候再通过bufferData在对其赋值,只需在每次渲染的时候,通过gl.bindBuffer和gl.vertexAttribPointer将buffer的值传递给着色器中的attribute变量即可,对shader中的attribute变量进行赋值。可参见 一个使用drawElements绘图的简单Demo