纹理贴图
纹理贴图是OpenGL渲染的重要基础操作之一,其本质就是在创建的窗口上,用程序读取图片数据,然后显示出来。
预备知识:
1.纹理坐标范围:0~1
2.纹理与图像坐标的对应关系:纹理坐标在左下角为原点(0,0);而图像是从左上角第一行从左到右逐行读取的,所以其左上角为原点(0,0);
纹理贴图的具体实现步骤为:
读取纹理文件->生成纹理ID->生成纹理->设置纹理参数。下文将简要说明了该过程。
1.读取纹理文件
在该程序中,借助第三方库stb_image来读取纹理文件。关于stb_image的更多细节在此并不进行讨论。
GLint iChannel=0;
FILE* pFile=fopen(texture_file_path,"rb");
const unsigned char* pImageData=stbi_load_from_file(pFile,&m_iTexWidth,&m_iTexHeight,&iChannel,0);
2.生成纹理ID
利用glGenTextures() 函数生成当前纹理的ID,同时使用glBindTexture() 函数进行纹理绑定。为了防止生成失败,还应使用glIsTexture() 函数进行检查
glGenTextures(1,&m_iTexture);
glBindTexture(GL_TEXTURE_2D,m_iTexture);
if (glIsTexture(m_iTexture)==GL_FALSE)
{
fprintf(stderr,"Is not currently the name of texture.Or some error occurs.Please check.\n");
getchar();
glfwTerminate();
return ;
}
3.生成纹理
利用glTexImage2D() 函数将缓存中的图形数据生成二维的纹理
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,m_iTexWidth,m_iTexHeight,0,GL_RGB,GL_UNSIGNED_BYTE,pImageData);
4.设置纹理参数
利用glTexParameteri() 函数设定纹理的贴图方式、放大、缩小的处理。
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_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);
为了实现一次将顶点坐标数据和纹理坐标传输到移动端,将顶点坐标数据和纹理坐标定义在同一个数组中,如下所示。其中,每一行的前三个数据表示顶点坐标,后两个数据表示纹理坐标。关于纹理坐标的设置可参考预备知识。
static const GLfloat g_fVertexBufferData[]={
-1.0f,-1.0f,0.0f,0.0f,1.0f,
1.0f,-1.0f,0.0f,1.0f,1.0f,
0.0f,1.0f,0.0f,0.5f,0.0f,
};
由上对顶点坐标和纹理坐标的设定,可以得出如下渲染代码:
glEnableVertexAttribArray(m_CurrentShader.GetVertexIndex());
glBindBuffer(GL_ARRAY_BUFFER,m_CurrentVertex.GetVertexBuffer());
glVertexAttribPointer(m_CurrentShader.GetVertexIndex(),3,GL_FLOAT,GL_FALSE,5*sizeof(GLfloat),(void *)0);
glEnableVertexAttribArray(m_CurrentShader.GetUVIndex());
glVertexAttribPointer(m_CurrentShader.GetUVIndex(),2,GL_FLOAT,GL_FALSE,5*sizeof(float),(void *)12);
glDrawArrays(GL_TRIANGLES,0,3);
glDisableVertexAttribArray(m_CurrentShader.GetVertexIndex());
glDisableVertexAttribArray(m_CurrentShader.GetUVIndex());
首先,利用glEnableVertexAttribArray() 函数使能顶点坐标的属性矩阵,然后使用glBindBuffer() 函数绑定该顶点坐标,并通过glVertexAttribPointer() 函数设定其对应的顶点属性值。关于glVertexAttribPointer() 函数最后两个参数的一点说明:其中最后一个参数表示第一个顶点的起始位置,倒数第二个参数表示相邻同类顶点的距离。另外,对于纹理坐标的使用也是一样的。
原始纹理图片:
图1
运行调试结果:
图2