大家好,接下来将为大家介绍OpenGL ES 3. 天空盒 立方体贴图。
OpenGL ES 立方体贴图本质上还是纹理映射,是一种 3D 纹理映射。立方体贴图所使的纹理称为立方图纹理,它是由 6 个单独的 2D 纹理组成,每个 2D 纹理是立方图的一个面。
天空盒技术的思路很明确,具体说就是将场景放置在一个很大的立方体中,立方体的每个面是一个纹理正方形,如下图所示。
为了在观察位于天空盒内部的场景时有真实天空背景的效果,组成天空盒的 6 个纹理正方形上需要各自映射一幅正方形的天空纹理图。这 6 幅纹理图是可以无缝拼接的,如下图所示。
立方图纹理的采样通过一个 3D 向量(s, t, r)作为纹理坐标,这个 3D 向量只作为方向向量使用,OpenGL ES 获取方向向量触碰到立方图表面上的纹理像素作为采样结果。方向向量触碰到立方图表面对应的纹理位置作为采样点,要求立方图的中心必须位于原点。
立方图各个面的指定方法与 2D 纹理基本相同,且每个面必须为正方形(宽度和高度必须相同)。
立方图纹理的使用与 2D 纹理基本一致,首先生成一个纹理,激活相应纹理单元,然后绑定到 GL_TEXTURE_CUBE_MAP
类型纹理。
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
由于立方图包含 6 个纹理,每个面对应一个纹理,需要调用glTexImage2D
函数 6 次,OpenGL ES 为立方图提供了 6 个不同的纹理目标,对应立方图的 6 个面,且 6 个纹理目标按顺序依次增 1。
GL_TEXTURE_CUBE_MAP_POSITIVE_X 右向纹理
GL_TEXTURE_CUBE_MAP_NEGATIVE_X 左向纹理
GL_TEXTURE_CUBE_MAP_POSITIVE_Y 上向纹理
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 下向纹理
GL_TEXTURE_CUBE_MAP_POSITIVE_Z 后向纹理
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 前向纹理
加载6片纹理图像
int[] textureIdA=new int[6];//存放天空盒6面的纹理id的数组
//加载纹理
textureIdA[0]=initTexture(R.raw.skycubemap_back);
textureIdA[1]=initTexture(R.raw.skycubemap_left);
textureIdA[2]=initTexture(R.raw.skycubemap_right);
textureIdA[3]=initTexture(R.raw.skycubemap_down);
textureIdA[4]=initTexture(R.raw.skycubemap_up);
textureIdA[5]=initTexture(R.raw.skycubemap_front);
将立方图的 6 个面对应的图像数据加载到纹理,其中mBoxImg
为图像数据的数组:
glGenTextures(1, &m_TextureId);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_TextureId);
for (int i = 0; i < 6; ++i)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
GL_RGBA, mBoxImg[i].width, mBoxImg[i].height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, mBoxImg[i].ppPlane[0] );
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
类似于普通的 2D 纹理,在使用立方图纹理绘制物体之前,需要激活相应的纹理单元并绑定到立方图上。不同的是,对应的片段着色器中,采样器变成了 samplerCube
,并且纹理坐标变成了三维方向向量。
#version 300 es
precision mediump float;
in vec3 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform samplerCube s_SkyBox;
void main()
{
outColor = texture(s_SkyBox, v_texCoord);
}
天空盒的绘制:
glUseProgram(m_ProgramObj);
glBindVertexArray(m_SkyBoxVaoId);
glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, m_TextureId);
glUniform1i(m_SamplerLoc, 0);
glDrawArrays(GL_TRIANGLES, 0, 36);
最后,欢迎大家一起交流学习:微信:liaosy666 ; QQ:2209115372 。