OpenGL ES 3. 天空盒 立方体贴图

大家好,接下来将为大家介绍OpenGL ES 3. 天空盒 立方体贴图。

OpenGL ES 立方体贴图本质上还是纹理映射,是一种 3D 纹理映射。立方体贴图所使的纹理称为立方图纹理,它是由 6 个单独的 2D 纹理组成,每个 2D 纹理是立方图的一个面。

天空盒技术的思路很明确,具体说就是将场景放置在一个很大的立方体中,立方体的每个面是一个纹理正方形,如下图所示。

OpenGL ES 3. 天空盒 立方体贴图_第1张图片

为了在观察位于天空盒内部的场景时有真实天空背景的效果,组成天空盒的 6 个纹理正方形上需要各自映射一幅正方形的天空纹理图。这 6 幅纹理图是可以无缝拼接的,如下图所示。

OpenGL ES 3. 天空盒 立方体贴图_第2张图片

立方图纹理的采样通过一个 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 。

 

 

你可能感兴趣的:(OpenGL,基础)