OpenGL ES 入门 -- 立方体贴图

1,311 阅读4分钟

如果不想安逸的被淘汰,那就奋不顾身的去努力

OpenGL ES 入门 -- 绘制图形

OpenGL ES 入门 -- 渲染图片

OpenGL ES 入门 -- 变换

前言

前面几章内容从绘制到渲染、变换,我已经不能简单的满足静态的效果,所以本章会结合坐标系统来试试天空盒的效果,在天空盒之前,简单介绍下立方体贴图。

效果展示

立方体贴图

我们已经使用2D纹理挺长时间,今天我们来学习下将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图

简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理组成了立方体的一面,那么问题来了,为什么不直接使用6个单独的纹理,而要合并到一个纹理中呢?立方体贴图有一个非常有用的特性,它可以通过一个方向向量来进行索引/采样,假设我们有一个1x1x1的立方体,方向向量的原点位于它的中心,使用一个橘黄色的方向向量来从立方体贴图上采样一个纹理:

如果我们假设把这么一个立方体贴图应用到一个立方体上,采样立方体贴图使用的方向向量将和立方体的顶点位置非常相像,这样的话只要立方体的中心位于原点,那么我们就可以使用立方体的顶点位置来对贴图进行采样了,这样我们就可以将所有顶点的纹理坐标当成是顶点位置坐标。

创建立方体贴图

立方体贴图是和其他纹理一样,如果想创建一个立方体贴图的话,我们需要生成一个纹理,并将其绑定到纹理目标上,然后再做其他的纹理操作,这次绑定到GL_TEXTURE_CUBE_MAP

    GLuint textureId;
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureId);

因为立方体贴图包含6个面,所以我们需要调用glTexImage2D函数6次,OpenGLES给我们提供了6个特殊的纹理目标,如下图:

然后我们可以通过遍历数组,从GL_TEXTURE_CUBE_MAP_POSITIVE_X开始遍历,每次枚举值+1,

然后设定纹理的环绕和过滤方式:

在绘制使用立方体贴图的物体之前,首先要激活对应的纹理单元,并绑定立方体贴图,这和普通的2D纹理没什么区别,在片段着色器中,我们使用了一个不同类型的采样器samplerCube,我们将使用texture函数对它进行采样,不过这次我们使用的是一个vec3的方向向量,而不是vec2,片段着色器的代码如下:

天空盒就是立方体贴图的典型案例之一。

天空盒

天空盒是一个包含了整个场景的立方体,它包含了周围环境的6个镜像,让玩家以为他出在一个比实际大的多的环境当中,游戏中使用天空盒的例子有群山、白云或者星空,下面这张截图展示的是星空的天空盒,它来自【上古卷轴3】;

这么一看的话,立方体贴图能完美的满足天空盒的需求,在上图中,我们只需要使用夜空的几张图片,就能让玩家产生位于广袤宇宙中的错觉,但实际上他只是在一个小小的盒子当中。天空盒图像通常是以下形式:

加载天空盒

因为天空盒本身就是一个立方体贴图,所以加载天空盒和加载立方体贴图时并没有什么不同,为了加载天空盒,我们将使用下面的函数,它接受一个包含留个纹理路径的数组:

现在我们就将这个天空盒加载为一个立方体贴图了,它的id是cubemapTexture,我们可以将它绑定到一个立方体上。

GLuint cubemapTexture = loadCubemap(faces);

天空盒着色器

注意,在这个顶点着色器中,我们将输入的顶点位置作为输出给片段着色器的纹理坐标,片段着色器会将它作为输入来采样,

有了立方体纹理,只需要绑定渲染就可以了。

大致实现如上,具体实现时,我们通过透视投影矩阵、视图矩阵达到环视天空盒的效果,具体实现参考Demo,如有什么问题,欢迎交流。

Demo下载地址,欢迎交流