OpenGL ES 2.0 编程指南 学习

OpenGL ES 2.0 Programme Guide 

基础内容学习小结

1. OverView 

ES2.0绘图管线示意图:

VertexArray 绘图场景中所有的物体空间位置由点坐标数组构成。

VertexShader: 对每个点的位置进行变换计算光照方程式生成每点的颜色,生成或者变换纹理坐标。基本结构示意图:

Attributes  ---- 采用点向量数组形式传入的每个点的数据。

Uniforms  ---- vertex shader 使用常量数量。

Sampler  ---  表示纹理的特殊常量。可选。

Varying Variable -- Vertex Shader的输出变量,作为Fragment Shader的输入。必须与Fragment Shader中的输入Varying一一对应。

gl_Position 是每个点固有的Varying .表示点的空间位置。

Primitive Assembly : 管线中这个流程是对所有的点数据进行点线面等基础图元的组装。这个过程会对所有的图元进行剪切和筛选。对于不在视区空间中的部分进行剪切,对于不可见的面进行筛选。

Rasterization : 光栅化的过程就是对所有的经过Primitive Assembly图元转换成屏幕上可以显示的二维Fragment。 

Fragment Shader:通过shader程序对Fragment进行处理。基本结构如下图:

Per-Fragment Operations :每个Fragment的操作。每个Fragment在屏幕上都有一个显示坐标(wx,wy)。基本流程:

这些流程基本是一些在frame buffer 中的2D像素操作。 

2  OPENGL ES 2.0 1.1的兼容性

2.01.1 不兼容。

1.1 几乎可看作是OPENGL的子集。采用固定管线编程。

2.0 则全部采用Shader语言来操作。

3  EGL 

ES2.0绘图需要一个上下文context 和 绘图surface . Context用来存储ES2.0的管线状态机,surface则表示绘图的缓冲及其属性。EGL是一个介于OPENGL ES 绘图语言和本地视窗系统之间的中间层。因此EGL使得OPENG ES 的平台无关性。

基本流程:

1) Query the displays that are available on the device and initialize them. 

2) Create a rendering surface.

3) Create a rendering context.   Attach context before start doing graphic .

Eg:

eglDisplay = eglGetDisplay((EGLNativeDisplayType)0); //获取默认显示设备

eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion); //初始化,返回版本号

eglChooseConfig(eglDisplay, pi32ConfigAttribs, &eglConfig, 1, &iConfigs); //选择一个配置。eglConfig是返回的配置,pi32ConfigAttribs是输入的配置属性,是一个int数组,以key-value的顺序存放属性和值。

eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType) NULL, NULL);//根据egl配置创建显示Surface

eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, pi32ContextAttribs); //根据egl配置和上下文配置创建上下文。pi32ContextAttribs也是一个int数组,以key-value的顺序存放属性和值。

eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); //绑定设置当前的上下文和surface.

Ok,下面可以开始使用gl开关的函数绘图了。

4  Opengl ES 2.0 Shader编程 OverView

编写vertex Shaderfragment shader源码。

创建两个shader 实例:GLuint   glCreateShader(GLenum type);

Shader实例指定源码。 glShaderSource

在线编译shaer源码 void   glCompileShader(GLuint shader)

创建program  GLuint   glCreateProgram(void)

绑定shaderprogram 。 void   glAttachShader(GLuint program, GLuint shader)。每个program必须绑定一个vertex shader 和一个fragment shader

链接program 。 void   glLinkProgram(GLuint program)

使用porgram 。 void   glUseProgram(GLuint program)

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

5. Shader语言中的数据类型与变量

1) Uniforms and Attributes

Uniforms 是一个program 中统一分配的,vertext fragment中同名的Uniform必须同类型。对应于不经常变化的变量。

Attributes 变化率高的变量。主要用来定义输入的每次点属性。

Uniforms and Attributes shader中通过location 和 name 来对应的。

通过GLint   glGetUniformLocation(GLuint program,const char* name).根据一个Uniform的名称获取其location.

通过 glUniform***系列函数可以给一个location 设置一个Uniform的值。

2) 数据类型

三类基本类型:float , int , boolean

复合类型: 

浮点、整型、布尔向量   vec2 , vec3,vec4 

矩阵          mat2, mat3,mat4 

结构体  用基本类型和复合类型构建结构体。

变量初始化。可以由简单类型初始化复杂类型。

可以通过常量下标访问矩阵,变量数组,向量中的分量。

操作与C语言类似。

 函数。传参指定in out 或者inout

 If else 流控制。

 For循环。只支持常数循环次数。

无论下标,还是循环变量,都只能使用编译时可确定的常数。

Uniform  前辍修饰的变量初始值由外部程序赋值。在program中具有统一访问空间。存储空间有限

Attribute  前辍修饰的变量定义的是每个vertex的属性变量,包括位置,颜色,法线和纹理坐标

Uniform 和 Attribute  类型的变量在shader中是只读的,只能由外部主机程序传入值。

6. Vertex  Attribute

1Vertex Attributes 是每点的属性数据。与一个index序号绑定。

外部程序可通过 glBindAttribLocation将一个attribute 名与一个index绑定起来。

当然,OPENGL ES 内部会自动绑定所有attributes.外部程序只需要通过 glGetAttribLocation获取指定attribute名的index. 

2)Attribute传值有两种方式:

可以通过 glVertexAttribPointer会话vertex Array数组。

可以通过 glVertexAttrib** 给指定location(index)attribute赋值。

7.  Primitive Assembly and Rasterization 

1Primitive : 三角形 ,线 , 点 

三角形绘制时可使用:GL_TRIANGLES GL_TRIANGLE_STRIP GL_TRIANGLE_FAN三种模式。

绘线可用:GL_LINES  GL_LINE_STRIP GL_LINE_LOOP三种模式

线宽可用:void   glLineWidth(GLfloat width)进行设置。

绘点可用:  GL_POINTS. 绘点vertex Shader中内置gl_PointSize输出变量。定义点的半径

   2Drawing Primitives

绘制primitves时可用的两个函数:

void   glDrawArrays(GLenum mode, GLint first, GLsizei count)

void   glDrawElements(GLenum mode, GLsizei count,GLenum type, const GLvoid *indices) 

这两个函数调用前都需要绑定点属性数组,主要是坐标数组。后都给定下标数组来绘制primitive,绘制大量的mesh时,有利于提高性能。

3) Primitive Assembly

坐标体系: 

Primitive Assembly基本流程

Clipping :

视区空间,六个面组成。对于每个primitive,凡在空间外的都clip掉。

Perspective Division 

标准化坐标,即齐次坐标(x,y,z,w)转化为(x/w,y/w,z/w,1) 其中x,y,z绝对值均小于w

Viewport Transformation 

将标准化后的空间坐标转换到平面可视窗口范围内的坐标上。窗口范围定义void   glViewport(GLint x, GLint y, GLsizei w, GLsizei h) 

其中Xw,Yw,Zw是窗口坐标,Z是深度坐标。

Rasterization :为每个primitive生成一个fragment。一个fragment由屏幕像素坐标(Xw,Yw)和其他的fragment数据组成,这些数据将在fragment shader中被使用。

Culling : 对triangle进行Rasterization之前必须确定它是正面还是反面朝向观察者,Culling操作将会忽略背向观察者的面。首要的问题是如果区分三角形的正面和反面,这跟绘制三角形时三个点的顺序有关。如下图:

通过 void   glFrontFace(GLenum dir) 来设定三角形的正面。Dir可为GL_CW or GL_CCW(默认). 意思就是如果三角形三个点的绘制顺序为v0,v1,v2,站在观察者的位置,如果v0,v1,v2路径与 glFrontFace设定的时针方向相同,那么面向观察者的这一面就是正面,否则就是反面。

Culling其他相关接口:

void   glCullFace(GLenum mode) 选择要Cull的面,参数可为 GL_FRONT, GL_BACK, and GL_FRONT_AND_BACK。默认是GL_BACK

void   glEnable(GLenum cap)

void   glDisable(GLenum cap) 

其中 cap参数为 GL_CULL_FACE 。 使能、禁止GL_CULL_FACE功能。

8. Vertex Shader 

Shader能做的事: 

基于点操作的矩阵乘法位置变换.

根据光照公式计算每点的color值。

生成或者转换纹理坐标。

Vertex Shader OVERVIEW:

1)Built-In Special Variables  输出给管线的后端。

gl_Position : 点坐标。

gl_PointSize : point sprite的半径大小。绘制单点时用。

gl_FrontFacing: bool值。自动生成。

2)Built-In Uniform State

uniform gl_DepthRangeParameters gl_DepthRange; 窗口坐标深度远近值。

gl_DepthRange可设置

3)Precision Qualifiers 精度限定

对于基于int float的类型变量可以在定义是指定精度,三种:highp,mediump lowp 。 如 highp vec4        position; 

默认精度设定,如precision highp float;  对所有未加精度限定的float,使用默认设定highp。 

4)ES 2.0 Vertex Shader Limitations 

Length of Vertex Shader

Temporary Variables

Flow Control 

For循环。

Conditional Statements

If(bool){} 或者if(bool) {}else{}

Array Indexing:

只能使用常量。

Counting Number of Uniforms Used in a Vertex Shader

OpenGL ES 2.0 实现标准是 128 vec4 entriesuniform常量,被用来存储这几种类型的数值:

Variables declared with the uniform qualifier。如uniform vec4 v;

Const variables.   如: const int i=1;

Literal values。 如 vec(0.0,0.0,0.0,0.0),对于这种情况,应该尽量使用const变量来定义重复的文字常量。如const float z=0.0; 然后使用vec(z,z,z,z)来表示这个0向量。Uniform 存储空间占用会由40.0缩小到一个z.

Implementation-specific constants.

9 . Texturing 

1) 纹理坐标 

2) Texture Objects and Loading Textures

Texture Object采用int句柄来指向。

void   glGenTextures(GLsizei n, GLuint *textures) 创建指定数目的Texture对象。返回句柄到textures

void   glDeleteTextures(GLsizei n, GLuint *textures) 删除对象

绑定纹理void   glBindTexture(GLenum target, GLuint texture),对于2D纹理target使用GL_TEXTURE_2D

加载纹理: void   glTexImage2D(....)

3) Texture Coordinate Wrapping

纹理坐标超出[0,1]范围时映射纹理使用的回绕方式:

Texture Wrap Modes : GL_REPEAT,GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT

4) Using Textures in the Fragment Shader 

fragment shader 中定义uniform sampler2D s_texture;常量。

获取s_texturelocation。 samplerLoc = glGetUniformLocation(

                              userData->programObject, 

                              "s_texture");

使用void   glActiveTexture(GLenum texture) GL_TEXTURE0 ..GL_TEXTURE31指定为当前active texture

使用glBindTexture 绑定一个texture句柄到GL_TEXTURE*

glUniform1i(userData->samplerLoc, GL_TEXTURE* ); 当前激活的GL_TEXTURE*传给s_texture

shader中使用 texture2D内建函数取纹理坐标对应的color值。如:gl_FragColor = texture2D(s_texture, v_texCoord);

5) Texture Subimage Specification

对纹理的子块进行更新。

void   glTexSubImage2D(GLenum target, GLint level,

                       GLint xoffset, GLint yoffset,

                       GLsizei width, GLsizei height,

                       GLenum format, GLenum type, 

                       const void* pixels)

6) Blending 

生成的fragment是具有(x,y,z)坐标的,其中x,y是在窗口中显示的位置。Z是深度坐标。Blending是指当Fragment要显示在窗口中时,如果使能了blend,那么当前fragment的颜色要经过指定的blend方法去与屏幕中已经存在于(xy)坐标上的颜色进行混合。

基本的混合模式是Cfinal = fsource *Csource op (fdestingation*Cdestination)

Csource Cdestination是源和目的颜色,fsourcefdestination是源和目的的系数。也就是最终的颜色将是源和目的的颜色乘以各自的系数然后OP操作进行混合。

void   glBlendFunc(GLenum sfactor, GLenum dfactor);指定对于源和目的都采用什么系数模式。

void   glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB,

                           GLenum srcAlpha, GLenum dstAlpha);

对于源和目的采用分开的系数模式。即alpha部分与RGB部分独立指定。

void   glBlendEquation(GLenum mode); 指定OP操作。

void   glBlendEquationSeparate(GLenum modeRGB,

                               GLenum modeAlpha);对于RGB部分和Alpha部分分开指定OP操作。

7) Reading and Writing Pixels to the Framebuffer 

color buffer中读取图像像素

void   glReadPixels(GLint x, GLint y, GLsizei width,

                    GLsizei height, GLenum format,

                    GLenum type, void *pixels);

其余内容如光照,fogmipmapframebuffer object 等内容由于与目前项目无关,无暇顾及。

[email protected]

                                                              

                                                                       2010-7-29

你可能感兴趣的:(Graphic)