mGlProgram = createProgram(mVertexScript, mFragmentScript); glUseProgram(mGlProgram); //reject attribution GLuint a_pos = glGetAttribLocation(mGlProgram, "a_pos"); GLuint a_tex_coord = glGetAttribLocation(mGlProgram, "a_tex_coord"); //active attribution glEnableVertexAttribArray(a_pos); glEnableVertexAttribArray(a_tex_coord); //assigne attribution glVertexAttribPointer(a_pos, 3, GL_FLOAT, GL_TRUE, sizeof(vertex), 0); glVertexAttribPointer(a_tex_coord, 2, GL_FLOAT, GL_TRUE, sizeof(vertex), (GLvoid*) (sizeof(float) * 3)); //glEnable(GL_TEXTURE_2D); glPixelStorei(GL_PACK_ALIGNMENT, 1); // set 4 bytes for the buffer. glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glActiveTexture(GL_TEXTURE0); glGenTextures(1, &mY); glBindTexture(GL_TEXTURE_2D, mY); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);//if widht and height not 2^n , should set this glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); glGenTextures(1, &mU); glBindTexture(GL_TEXTURE_2D, mU); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); glGenTextures(1, &mV); glBindTexture(GL_TEXTURE_2D, mV); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_BYTE, 0); glFlush();
Function:
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride,const GLvoid * pointer);参数:index指定要修改的顶点属性的索引值size指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))type指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。normalized指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。stride指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。pointer指定第一个组件在数组的第一个顶点属性中的偏移量。该数组与GL_ARRAY_BUFFER绑定,储存于缓冲区中。初始值为0;
通过glPixelStore可以修改像素保存时对齐的方式。像这样:int alignment = 4;glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);第一个参数表示“设置像素的对齐值”,第二个参数表示实际设置为多少。这里像素可以单字节对齐(实际上就是不使用对齐)、双字节对齐(如果长度为奇数,则再补一个字节)、四字节对齐(如果长度不是四的倍数,则补为四的倍数)、八字节对齐。分别对应alignment的值为1, 2, 4, 8。实际上,默认的值是4,正好与BMP文件的对齐方式相吻合。glPixelStorei也可以用于设置其它各种参数。
void glGenTextures (GLsizei n, GLuint *textures); //在数组textures中返回n个当期未使用的值,表示纹理对象的名称 //零作为一个保留的纹理对象名,它不会被此函数当做纹理对象名称而返回GLboolean glIsTexture (GLuint texture); //如果texture是一个已绑定的纹理对象名称,并且没有删除,就返回GL_TRUE;
glActiveTexture && glBindTexture
可以这样简单的理解为:显卡中有N个纹理单元(具体数目依赖你的显卡能力),每个纹理单元(GL_TEXTURE0、GL_TEXTURE1等)都有GL_TEXTURE_1D、GL_TEXTURE_2D等,如下代码:
struct TextureUnit{ GLuint targetTexture1D; GLuint targetTexture2D; GLuint targetTexture3D; GLuint targetTextureCube; ...}; TextureUnit textureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]GLuint currentTextureUnit = 0;
默认情况下当前活跃的纹理单元为0.
void glActiveTexture(GLenum textureUnit){ currentTextureUnit = textureUnit - GL_TEXTURE0 ;}
glActiveTextue 并不是激活纹理单元,而是选择当前活跃的纹理单元。
void glBindTexture(GLenum textureTarget, GLuint textureObject){ TextureUnit *texUnit = &textureUnits[currentTextureUnit]; switch(textureTarget) { case GL_TEXTURE_1D: texUnit->targetTexture1D = textureObject; break; case GL_TEXTURE_2D: texUnit->targetTexture2D = textureObject; break; case GL_TEXTURE_3D: texUnit->targetTexture3D = textureObject; break; case GL_TEXTURE_CUBEMAP: texUnit->targetTextureCube = textureObject; break; }}从示例代码中可以看到:当绑定纹理目标时,所作用的是当前活跃的纹理单元。
void glDrawElements( GLenum mode, GLsizei count,GLenum type, const GLvoid *indices);其中:mode指定绘制图元的类型,它应该是下列值之一,GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_TRIANGLES, GL_QUAD_STRIP, GL_QUADS, and GL_POLYGON.count为绘制图元的数量乘上一个图元的顶点数。type为索引值的类型,只能是下列值之一:GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT。indices:指向索引存贮位置的指针。glDrawElements函数能够通过较少的函数调用绘制多个几何图元,而不是通过OPENGL函数调用来传递每一个顶点,法线,颜色信息。你可以事先准备一系列分离的顶点、法线、颜色数组,并且调用一次glDrawElements把这些数组定义成一个图元序列。当调用glDrawElements函数的时候,它将通过索引使用count个成序列的元素来创建一系列的几何图元。mode指定待创建的图元类型和数组元素如何用来创建这些图元。但是如果GL_VERTEX_ARRAY 没有被激活的话,不能生成任何图元。被glDrawElements修改的顶点属性在glDrawElements调用返回后的值具有不确定性,例如,GL_COLOR_ARRAY被激活后,当glDrawElements执行完成时,当前的颜色值是没有指定的。没有被修改的属性值保持不变。