一、本文关注的问题:
? Shader and program 对象介绍 ?创建并编译一个Shader对象 ? 创建并链接一个Program对象 ? 获取并设置uniforms ? 获取并设置attributes
在OpenGL ES中,每个program对象有且仅有一个Vertex Shader对象和一个Fragment Shader对象连接到它。
Shader:类似于C编译器
Program:类似于C链接器
glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令。
二、Shader和Program编程概述
1. 创建Shader 1)编写Vertex Shader和Fragment Shader源码。
2)创建两个shader 实例:GLuint glCreateShader(GLenum type);
3)给Shader实例指定源码。 glShaderSource
4)在线编译shaer源码 void glCompileShader(GLuint shader)
2. 创建Program
1)创建program GLuint glCreateProgram(void)
2)绑定shader到program 。 void glAttachShader(GLuint program,GLuint shader)。每个program必须绑定一个Vertex Shader 和一个Fragment Shader。
3)链接program 。 void glLinkProgram(GLuint program)
4)使用porgram 。 void glUseProgram(GLuint program)
对于使用独立shader编译器编译的二进制shader代码,可使用glShaderBinary来加载到一个shader实例中。
三、Shading Language中的数据类型与变量 1. Uniforms and Attributes
Uniforms 是一个program 中统一分配的,vertext 和fragment中同名的Uniform必须同类型。对应于不经常变化的变量(用于存储只读常量值的变量)。
Attributes 变化率高的变量。主要用来定义输入的每个点属性。
Uniforms and Attributes 在shader中通过location 和 name 来对应的。
2. 数据类型
1)三类基本数据类型:float,int,boolean
2)复合类型:浮点、整型、布尔向量 vec2,vec3,vec4。vector访问方式有以下两种:
(1).操作:数学{x,y,z,w},颜色{r,g,b,a}或 纹理坐标{s,t,r,q},但不能混用,举例如下:
vec3 myVec3 = vec3(0.0,1.0,2.0); // myVec3 = {0.0,2.0} vec3 temp; temp = myVec3.xyz; // temp = {0.0,2.0} temp = myVec3.xxx; // temp = {0.0,0.0,0.0} temp = myVec3.zyx; // temp = {2.0,0.0}
(2)[ ]操作:[0]对应x,[1]对应y,[2]对应z,[3]对应w。[ ]中只能为常量或uniform变量,不能为整数量变量(如:i,j,k)。
3)矩阵:mat2,mat3,mat4 (按列顺序存储)
mat3 myMat3 = mat3(1.0,// 第一列 0.0,// 第二列 0.5,1.0); // 第三列
可用[ ]或.操作符来访问:
mat4 myMat4 = mat4(1.0);// Initialize diagonal to 1.0 (identity) vec4 col0 = myMat4[0];// Get col0 vector out of the matrix float m1_1 = myMat4[1][1];// Get element at [1][1] in matrix float m2_2 = myMat4[2].z; // Get element at [2][2] in matrix
4)常量
const float zero = 0.0; const float pi = 3.14159; const vec4 red = vec4(1.0,1.0); const mat4 identity = mat4(1.0);
5)结构体: 用基本类型和复合类型构建结构体。
struct fogStruct { vec4 color; float start; float end; } fogVar; fogVar = fogStruct(vec4(0.0,0.0),// color 0.5,// start 2.0); // end vec4 color = fogVar.color; float start = fogVar.start; float end = fogVar.end;
6)数组:类似于C语言,索引从0开始。在创建时不能被初始化,索引只能为常量或uniform变量。
float floatArray[4]; vec4 vecArray[2];
7)操作
支持的操作有:*,/,+,-,++,--,=,+=,-=,*=,/=,==,!=,<,>,<=,>=,&&,^^,||
- floatmyFloat;
- vec4myVec4;
- mat4myMat4;
- myVec4=myVec4*myFloat;
-
- myVec4=myVec4*myVec4;
- myVec4=myMat4*myVec4;
- //myMat4*myVec4
- myMat4=myMat4*myMat4;
- //myMat4*myMat4
- myMat4=myMat4*myFloat;
- //thescalarmyFloat
前面矩阵的行数就是结果矩阵的行数,后面矩阵的列数就是结果矩阵的列数。
8)自定义函数:
vec4myFunc(inoutfloatmyFloat,
- outvec4myVec4,
- mat4myMat4);
函数不能递归调用,因为GPU不一定有Stack和流控。
9)Shading Language内嵌函数
主要有以下几类函数:
(1)角度和三角函数
(2)指数函数
(3)通用函数(绝对值、取整、取余、取小数部分等)
(4)几何函数
(5)矩阵函数
(6)向量比较函数
(7)纹理查找函数
(8)Derivative函数
10)控制流
if(color.a<0.25)
- {
- color*=color.a;
- }
- else
- color=vec4(0.0);
-
-
- //无论下标,还是循环变量,都只能使用编译时可确定的常数。
- for(inti=0;i<3;i++)
- {
- sum+=i;
- }
以下不允许(因为下标为变量或loop次数为变量):
floatmyArr[4];
- sum+=myArr[i];
- //INDEXINGWITHNONCONSTANTEXPRESSION
- ...
- uniformintloopIter;
- inti=0;i<loopIter;i++)
-
11)Uniforms(前辍修改) Uniform前辍修饰的变量初始值由外部程序赋值。在program中具有统一访问空间,存储空间有限。在Shader中是只读的,只能由外部主机程序传入值。
它用于存储shader需要的各种数据,如:变换矩阵、光照参数和颜色。基本上,对于Shader是一个常量,但在编译时其值未知,则应当作为一个uniform变量。
Uniform变量在Vertex Shader和Fragment Shader之间共享。当使用glUniform***设置了一个uniform变量的值之后,Vertex Shader和Fragment Shader中具有相同的值。
Uniform变量被存储在GPU中的“常量存储区”,其空间大小是固定的,可通过API<glGetIntegerv>查询(GL_MAX_VERTEX_UNIFORM_VECTORS或 GL_MAX_FRAGMENT_UNIFORM_VECTORS)。
12)Attributes(前辍修改)
Attribute类型的变量只有Vertex Shader才有。Attribute前辍修饰的变量定义的是每个Vertex的属性变量,包括位置,颜色,法线和纹理坐标
Attribute类型的变量在Vertex Shader中是只读的,只能由外部主机程序传入值。
Attribute类型的变量:是为每个被正在画的顶点所指定的数据。在画图前,每个顶点的属性由应用程序输入。
与Uniform变量一样,其存储数量也是有限制的。可用glGetIntegerv(GL_MAX_VERTEX_ATTRIBS)进行查询。GPU至少支持8个属性,所以Vertex Shader源码中不要超过8个attributes。
13)Varyings
Varying变量用于存储Vertex Shader的输出和Fragment Shader的输入。在Vertex Shader和Fragment Shader中必须申明同一个Varying变量。
与Uniform和Attribute一样,其存储数量也是有限制的,可用glGetIntegerv(GL_MAX_VARYING_VECTORS)进行查询。GPU至少支持8个Varying vector,所以Vertex Shader源码中不要超过8个Varying vector。
GLint maxVertexAttribs; // n will be >= 8 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&maxVertexAttribs);
14)预处理
#define
- #undef
- #if
- #ifdef
- #ifndef
- #else
- #elif
- #endif
- __LINE__
- __FILE__
- __VERSION__
- GL_ES
15) Uniform Attribute Varying存储空间最小值
变量类型 |
GPU必须支持的最小个数 |
Vertex Uniform Vectors |
128 |
Fragment Uniform Vectors |
16 |
Vertex Attributes |
8 |
Varying Vectors |
8 |
16) 精度限定(Precision Qualifiers)
关键词:lowp highp mediump
(1)指定变量精度(放在数据类型之前):
highpvec4position;
- varyinglowpvec4color;
- mediumpfloatspecularExp;
(2)指定默认精度(放在Vertex和Fragment shader源码的开始处):
precisionhighpfloat;
- precisionmediumpint;
在Vertex Shader中,如果没有默认的精度,则float和int精度都为highp;在Fragment Shader中,float没有默认的精度,所以必须在Fragment Shader中为float指定一个默认精度或为每个float变量指定精度。
17)结果一致性
invariant可被应用于任何Vertex ShaderVarying输出变量,其目前是保证相同的操作和相同的输入,其结果一样。因为由于Shader精度不一样,其结果有可能不一样。
uniformmat4u_viewProjMatrix;
- attributevec4a_vertex;
- invariantgl_Position;
- voidmain
- //…
- gl_Position=u_viewProjMatrix*a_vertex;
- //valueinall
- //shaderswiththe
- //sameviewProjMatrix
- //andvertex
- }
也可指定所有的输出变量都为:invariant
#pragmaSTDGLinvariant(all)
四、获取和设置Uniforms
通过GLint glGetUniformLocation(GLuint program,const char* name).根据一个Uniform的名称获取其location.
通过 glUniform***系列函数可以给一个location 设置一个Uniform的值。
voidglUniform1f(GLintlocation,GLfloatx)
- voidglUniform1fv(GLintlocation,GLsizeicount,constGLfloat*v)
- voidglUniform1i(GLintlocation,GLintx)
- voidglUniform1iv(GLintlocation,153); background-color:inherit; font-weight:bold">constGLint*v)
-
- voidglUniform2f(GLintlocation,GLfloatx,GLfloaty)
- voidglUniform2fv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniform2i(GLintlocation,GLintx,GLinty)
- voidglUniform2iv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniform3f(GLintlocation,GLfloaty,GLfloatz)
- voidglUniform3fv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniform3i(GLintlocation,GLinty,GLintz)
- voidglUniform3iv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniform4f(GLintlocation,GLfloatz,GLfloatw);
- voidglUniform4fv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniform4i(GLintlocation,GLintz,GLintw)
- voidglUniform4iv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniformMatrix2fv(GLintlocation,
- GLbooleantranspose,constGLfloat*value)
- voidglUniformMatrix3fv(GLintlocation,153); background-color:inherit; font-weight:bold">voidglUniformMatrix4fv(GLintlocation,153); background-color:inherit; font-weight:bold">constGLfloat*value)
为矩阵uniform变量设置值的函数中的transpose必须为GL_FALSE,它目的为兼容性,但在 OpenGL ES 2.0中并没有工作。
一旦你设置了一个Program中unifrom变量的值之后,即使你激活了另外一个Program,此uniform的值不变。即uniform变量是Program的局部变量。
五、VertexAttributes
Vertex属性即顶点数据,它指定了每个顶点的数据。在OpenGL ES1.1中,顶点属性有四个预定义的名字:position(位置),normal(法线),color(颜色),和 texture coordinates(纹理坐标)。在OpenGL ES2.0中,用户必须定义“顶点属性的名字”。
1. 常量顶点属性(Constant Vertex Attribute)
常量顶点属性对所有顶点都是一样的。因此只需要指定一个值就可以应用于所有顶点。一般很少使用。其设置函数有:
void glVertexAttrib1f(GLuintindex,GLfloatx);
voidglVertexAttrib2f(GLuintindex,GLfloaty);
voidglVertexAttrib3f(GLuintindex,GLfloatz);
voidglVertexAttrib4f(GLuintindex,GLfloatw);
voidglVertexAttrib1fv(GLuintindex,153); background-color:inherit; font-weight:bold">constGLfloat*values);
voidglVertexAttrib2fv(GLuintindex,153); background-color:inherit; font-weight:bold">constGLfloat*values);
voidglVertexAttrib3fv(GLuintindex,153); background-color:inherit; font-weight:bold">voidglVertexAttrib4fv(GLuintindex,153); background-color:inherit; font-weight:bold">constGLfloat*values);
2.如何装载顶点数据?(Vertex Arrays)
Vertex Array(顶点数组):是一个存储在应用程序空间(Client)中的内存buffer,它存储了每个顶点的属性数据。
如何把顶点数据组的数据传递给GPU呢?
void glVertexAttribPointer(GLuint index,
GLint size,//每个属性元素个数有效值1-4(x,w) GLenum type,//数组中每个元素的数据类型 GLboolean normalized, GLsizei stride,//如果数据连续存放,则为0或
//size*sizeof(type) const void *ptr) //顶点数组指针
举例如下:
copy
GLfloatvVertices[]={0.0f,0.5f,0.0f,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> -0.5f,-0.5f,
- 0.5f,0.0f};
- //Settheviewport
- glViewport(0,esContext->width,esContext->height);
- //Clearthecolorbuffer
- glClear(GL_COLOR_BUFFER_BIT);
- //Usetheprogramobject
- glUseProgram(programObject);
- //Loadthevertexdata
- glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,vVertices);
2.1一个顶点的所有属性存储在一起(Array of Structures)
如下图所示,顶点的位置(x,z)、法线(x,z)和两个纹理坐标(s,t)存储在一起,如下图所示:
例子代码如下(当然,此代码在CPU上运动):
#defineVERTEX_POS_SIZE3//x,yandz
- #defineVERTEX_NORMAL_SIZE3//x,yandz
- #defineVERTEX_TEXCOORD0_SIZE2//sandt
- #defineVERTEX_TEXCOORD1_SIZE2//sandt
- #defineVERTEX_POS_INDX0
- #defineVERTEX_NORMAL_INDX1
- #defineVERTEX_TEXCOORD0_INDX2
- #defineVERTEX_TEXCOORD1_INDX3
- //thefollowing4definesareusedtodeterminelocationofvarious
- //attributesifvertexdataisarestoredasanarrayofstructures
- #defineVERTEX_POS_OFFSET0
- #defineVERTEX_NORMAL_OFFSET3
- #defineVERTEX_TEXCOORD0_OFFSET6
- #defineVERTEX_TEXCOORD1_OFFSET8
- #defineVERTEX_ATTRIB_SIZEVERTEX_POS_SIZE+
- VERTEX_NORMAL_SIZE+
- VERTEX_TEXCOORD0_SIZE+
- VERTEX_TEXCOORD1_SIZE
- float*p=malloc(numVertices*VERTEX_ATTRIB_SIZE
- *sizeof(float));
- //positionisvertexattribute0
- glVertexAttribPointer(VERTEX_POS_INDX,VERTEX_POS_SIZE,
- GL_FLOAT,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> VERTEX_ATTRIB_SIZE*float),248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> p+VERTEX_POS_OFFSET);
- //normalisvertexattribute1
- glVertexAttribPointer(VERTEX_NORMAL_INDX,VERTEX_NORMAL_SIZE,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> (p+VERTEX_NORMAL_OFFSET));
- //texturecoordinate0isvertexattribute2
- glVertexAttribPointer(VERTEX_TEXCOORD0_INDX,VERTEX_TEXCOORD0_SIZE,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> (p+VERTEX_TEXCOORD0_OFFSET));
- //texturecoordinate1isvertexattribute3
- glVertexAttribPointer(VERTEX_TEXCOORD1_INDX,VERTEX_TEXCOORD1_SIZE,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> (p+VERTEX_TEXCOORD1_OFFSET));
2.2 顶点的每个属性单独存储(Structure of Arrays)
例子代码如下(当然,此代码在CPU上运动):
#define VERTEX_POS_SIZE 3 // x,y and z
#define VERTEX_NORMAL_SIZE 3 // x,y and z
#define VERTEX_TEXCOORD0_SIZE 2 // s and t
#define VERTEX_TEXCOORD1_SIZE 2 // s and t
#define VERTEX_POS_INDX 0
#define VERTEX_NORMAL_INDX 1
#define VERTEX_TEXCOORD0_INDX 2
#define VERTEX_TEXCOORD1_INDX 3
#define VERTEX_ATTRIB_SIZE VERTEX_POS_SIZE +
VERTEX_NORMAL_SIZE +
VERTEX_TEXCOORD0_SIZE +
VERTEX_TEXCOORD1_SIZE
float *position = malloc(numVertices * VERTEX_POS_SIZE *
sizeof(float));
float *normal = malloc(numVertices * VERTEX_NORMAL_SIZE *
sizeof(float));
float *texcoord0 = malloc(numVertices * VERTEX_TEXCOORD0_SIZE *
sizeof(float));
float *texcoord1 = malloc(numVertices * VERTEX_TEXCOORD1_SIZE *
sizeof(float));
// position is vertex attribute 0
glVertexAttribPointer(VERTEX_POS_INDX,VERTEX_POS_SIZE * sizeof(float),position);
// normal is vertex attribute 1
glVertexAttribPointer(VERTEX_NORMAL_INDX,VERTEX_NORMAL_SIZE * sizeof(float),normal);
// texture coordinate 0 is vertex attribute 2
glVertexAttribPointer(VERTEX_TEXCOORD0_INDX,VERTEX_TEXCOORD0_SIZE *
sizeof(float),texcoord0);
// texture coordinate 1 is vertex attribute 3
glVertexAttribPointer(VERTEX_TEXCOORD1_INDX,VERTEX_TEXCOORD1_SIZE * sizeof(float),//也可为0,因为数据是紧接着存放的
texcoord1);
2.3. 哪种顶点属性数据存储方式在GPU上性能更好?
答案是:把一个顶点的所有属性放在一起(array of structures)。其原因是每个顶点的属性数据以连续的方式读取,使内存访问效率更高。其缺点是,如果要修改其中部分属性数据,将导致整个属性buffer全部重新装载,解决此问题的方法是把这些需要动态修改的属性数据放在单独的buffer中。
五、 顶点属性数据类型优化
顶点属性数据类型不会影响在GPU上每个顶点占用的内存,但在Render a Frame时,它影响CPU与GPU之间的内存带宽。推荐尽量使用GL_HALF_FLOAT_OES。
六、glVertexAttribPointer中的归一化参数
如果normalized为GL_FALSE:则直接把数据转换为GLfloat,因为Vertex Shader内部把顶点属性当作GLfloat(32位)来进行存储。
GL_BYTE,GL_SHORT or GL_FIXED被归一化为[-1,1];GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT被归一化为[0.0,1.0]。具体转换公式为:
3、选择常量或顶点数组Vertex Attribute
可通过以下函数来Enable或Disable顶点数组(Vertex Array)。
void glEnableVertexAttribArray(GLuint index); void glDisableVertexAttribArray(GLuint index);
其关系如下图所示:
4、申明attribute变量(在Vertex Shader中)
Attribute变量的数据类型只能为:float,vec2,vec4,mat2,and mat4;Attribute变量不能为数组或结构。如下面的申明是错误的:
attributefoo_ta_A;
- attributevec4a_B[10];
每个GPU支持GL_MAX_VERTEX_ATTRIBS vec4。float、vec2和vec3也被当作一个vec4来进行存储;mat2、mat3、mat4被分别当作2、3、和4个vec4来进行存储。
5、把“顶点属性索引”绑定到“顶点属性名”
把“顶点属性索引”绑定到“顶点属性名”有以下两个方法:
1)OpenGL ES 2.0把“顶点属性索引”绑定到“顶点属性名”,当link program时,OpengGL ES 2.0执行此绑定。然后应用程序通过glGetAttribLocation(失败时返回-1)获取“顶点属性索引”。
GLintglGetAttribLocation(GLuintprogram,constGLchar*name)
2)应用程序通过glBindAttribLocation把“顶点属性索引”绑定到“顶点属性名”,glBindAttribLocation在program被link之前执行。
voidglBindAttribLocation(GLuintprogram,GLuintindex,153); background-color:inherit; font-weight:bold">constGLchar*name)
在link program时,OpenGL ES 2.0对每个顶点属性执行如下操作:
(1)首先检查属性变量是否被通过glBindAttribLocation绑定了属性索引,如果是,则使用此绑定的属性索引;否则,为之分配一个属性索引。
在应用程序中,一般使用函数glBindAttribLocation来绑定每个attribute变量的位置,然后用函数glVertexAttribPointer为每个attribute变量赋值。
6、顶点buffer对象(Vertex Buffer Objects)
顶点数组(Vertex Array)被保存在客户端内存,当执行glDrawArrays或 glDrawElements时,才把它们从客户端内存copy到图形内存。这样占用了大量的内存带宽,Vertex Buffer Objects允许OpengGL ES2.0应用在高性能的图形内存中分配并cache顶点数据,然后从此图形内存中执行render,这样避免了每次画一个原语都要重发送数据。
Vertex Buffer Objects有以下两种类型:
(1)array buffer objects:通过GL_ARRAY_BUFFER标记创建,并存储vertex data。
(2)element array buffer objects:通过GL_ELEMENT_ARRAY_BUFFER标记创建,并存储indices of a primitive。
创建和绑定Vertex Buffer Objects例子代码如下:
voidinitVertexBufferObjects(vertex_t*vertexBuffer,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GLushort*indices,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GLuintnumVertices,GLuintnumIndices
- GLuint*vboIds)
- glGenBuffers(2,vboIds);
- glBindBuffer(GL_ARRAY_BUFFER,vboIds[0]);
- glBufferData(GL_ARRAY_BUFFER,numVertices*sizeof(vertex_t),108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> vertexBuffer,GL_STATIC_DRAW);//savevertexattributedata
- //bindbufferobjectforelementindices
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vboIds[1]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> numIndices*sizeof(GLushort),indices,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GL_STATIC_DRAW);//saveelementindicesthatmakeuptheprimitive
- 有无Vertex Buffer Object画图例子:
#defineVERTEX_POS_SIZE3//x,yandz
- #defineVERTEX_NORMAL_SIZE3//x,yandz
- #defineVERTEX_TEXCOORD0_SIZE2//sandt
- #defineVERTEX_POS_INDX0
- #defineVERTEX_NORMAL_INDX1
- #defineVERTEX_TEXCOORD0_INDX2
- //
- //vertices–pointertoabufferthatcontainsvertexattribute
- data
- //vtxStride–strideofattributedata/vertexinbytes
- //numIndices–numberofindicesthatmakeupprimitive
- //drawnastriangles
- //indices-pointertoelementindexbuffer.
- //
- voiddrawPrimitiveWithoutVBOs(GLfloat*vertices,GLintvtxStride,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GLintnumIndices,GLushort*indices)
- GLfloat*vtxBuf=vertices;
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
- glEnableVertexAttribArray(VERTEX_POS_INDX);
- glEnableVertexAttribArray(VERTEX_NORMAL_INDX);
- glEnableVertexAttribArray{VERTEX_TEXCOORD0_INDX);
- glVertexAttribPointer(VERTEX_POS_INDX,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GL_FLOAT,vtxStride,vtxBuf);
- vtxBuf+=VERTEX_POS_SIZE;
- vtxBuf+=VERTEX_NORMAL_SIZE;
- glVertexAttribPointer(VERTEX_TEXCOORD0_INDX,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> VERTEX_TEXCOORD0_SIZE,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GL_FALSE,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> glBindAttribLocation(program,VERTEX_POS_INDX,"v_position");
- glBindAttribLocation(program,VERTEX_NORMAL_INDX,"v_normal");
- glDrawElements(GL_TRIANGLES,numIndices,GL_UNSIGNED_SHORT,indices);
-
voiddrawPrimitiveWithVBOs(GLintnumVertices,GLfloat*vtxBuf,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GLintvtxStride,GLintnumIndices,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> GLushort*indices)
- GLuintoffset=0;
- GLuintvboIds[2];
- //vboIds[0]–usedtostorevertexattributedata
- //vboIds[1]–usedtostoreelementindices
- glGenBuffers(2,vboIds);
- glBindBuffer(GL_ARRAY_BUFFER,vboIds[0]);
- glBufferData(GL_ARRAY_BUFFER,vtxStride*numVertices,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> vtxBuf,GL_STATIC_DRAW);
- sizeof(GLushort)*numIndices,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> indices,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> (constvoid*)offset);
- offset+=VERTEX_POS_SIZE*sizeof(GLfloat);
- glVertexAttribPointer(VERTEX_NORMAL_INDX,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> offset+=VERTEX_NORMAL_SIZE*sizeof(GLfloat);
- (constvoid*)offset);
- glDrawElements(GL_TRIANGLES,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> glDeleteBuffers(2,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> }
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|