这部分内容的基础是OpenGL中一个新类型的纹理(texture)对象:Cubemap。
物体还是认为是scene而非model吧,其下有mesh,译作网格,不再用面元的称呼,但是要记住mesh和网格没关系。
Cubemap简介
在定义时,通过glBindTexture(GL_TEXTURE_CUBE_MAP, texture)进行,使得texture对象指向一个cubemap。
由于Cubemap的主要功能,它经常不需要使用mipmap特性,所以其属性设置只需要将filter设为线性;由于cubemap不需要在除边缘外的点取值,或者说其采样利用的是一个固定三维向量,所以其wrap虽然有s、t、r三个坐标,但是大多数功能下只设为edge。
其功能包含skybox、reflection、refraction等。
skybox
名字叫skybox但是其功能其实更相当于设置环境,它是一个用于表示环境、背景等一系列概念的功能。
其实现可以简单描述为:渲染一个使用cubemap纹理的方块物体,位于原点,再用片段坐标作为它的采样器。
下面是一些比较奇怪的难点。
skybox和early depth testing(Early-Z)
skybox如果能利用早期深度测试以排除掉大量无效片段的渲染,将大幅提升性能,但这需要一些重要知识。
透明片段与不透明片段的区别
通常的习惯,不透明片段完全先于透明片段被写入帧缓冲,并且这步操作的设置是默认的,即能运用早期深度测试、且能更新深度缓冲区。
透明片段的渲染,已经知道它利用的是混合特性,所以只要它通过测试应该被渲染,那么它就不应该修改深度缓冲。
不透明->深度绝对相关,透明->深度相对无关
早期深度测试(Early-Z)
给出一个只有一层的、简略的单薄的渲染帧管线:
顶点着色器、曲面细分、几何着色器、裁剪、光栅化、片段着色器、模板测试、深度测试、混合、写入帧缓冲。
早期深度测试在光栅化阶段,后期深度测试在片段着色器之后,早期深度测试在光栅化时就将片段深度与深度缓冲区比较,排除了一部分片段。这是为了减少开销巨大的片段着色器的调用。
对于在skybox中渲染透明物体,如果透明物体被先渲染,那么skybox的部分片段将被E-Z排除,而非与透明片段混合。
一个能进行的示例
skybox渲染时,设置z为1.0。
skybox视作不透明物体与其他不透明物体一起渲染。为了减少额外的开销,将skybox比其他不透明物体后渲染。
透明物体在之后一起渲染,glDepthMask(GL_FALSE),使得透明物体能通过深度测试,不会被其他透明物体遮挡。
部分透明的scene
对于一个部分透明的scene,最优做法是在设计它的时候就将透明部分和不透明部分分在不同的mesh中,这能够避免写出一个带有条件判断的shader。
其次,由于前面的操作要求关闭深度缓冲,那么不透明部分遮挡而非混合的逻辑不能表示出来,因为不能判断前后。
environment mapping
这是为了解决在仅使用skybox时会出现的不能正确表达其他模型的问题,因为skybox不包含其他模型,对它的采样会忽略其他模型的影响。
reflection和refraction
对skybox的反射,只需要在片段处用反射的向量对skybox采样即可。
对skybox的折射,通过计算反射角再对skybox采样。但是由于一个物体中可能进行两次折射,这种折射的计算是粗略的。
环境贴图(environment mapping)的原理
skybox是一种静态环境贴图,通常也要求位置运动不改变渲染结果。这里讨论的是动态环境贴图。
对于一个需要利用动态环境贴图的scene,首先在这个scene之外的六个方向创建一个cubemap纹理,再在渲染这个scene的片段时在动态的cubemap上采样。
各种反射、折射的物体都可能需要用到动态环境贴图。
对于一个如汽车的物体,要表现它的镜面性质,就需要在汽车的周围的环境贴图。对于水底物体的折射,也需要在水底物体的环境贴图;而水面上反射需要水面上的环境贴图。对于水体的环境贴图,通常的生成方式将是在水面以上和水面以下分别用作反射和折射的计算,即进行了截断。
动态环境贴图的性能开销巨大,所以有各种奇奇怪怪看不懂的办法优化。
小结
(虽然内容不多但是尝试做一下小结)
cubemap是一种纹理类型,通常用于作为环境贴图。
环境贴图分为静态环境贴图和动态环境贴图。
静态环境贴图通常用作skybox,作为不变环境。
动态环境贴图主要用作反射、折射等,功能与模板测试有一定交叉。
comment 评论区
star_outline 咱快来抢个沙发吧!