【问题标题】:Why don't people use tetrahedrons for skyboxes?为什么人们不将四面体用于天空盒?
【发布时间】:2015-07-13 00:01:42
【问题描述】:

在 3D 游戏中渲染具有固定纹理的天空时,人们通常会先在一个立方体贴图中创建 6 个纹理,然后在相机周围渲染一个立方体。在 GLSL 中,您可以使用法线而不是纹理坐标来访问纹理中的像素,并且您可以通过标准化片段相对于相机的位置来轻松获得此法线。然而,这个过程可以用围绕相机的任何形状来完成,因为当你标准化每个位置时,它总是会产生一个球体。 现在我想知道: 为什么它总是一个立方体而不是一个四面体?渲染一个立方体需要 12 个三角形,一个四面体只有 4 个。正如我已经说过的,任何围绕相机的形状都可以。所以四面体占用更少的 VRAM 并且渲染速度更快,没有任何缺点?为什么不使用它们?

【问题讨论】:

  • Skyboxes 易于实现且易于确定纹理坐标。这就是它更常见的原因。
  • 你不需要纹理坐标。我想弄清楚顶点位置有点困难。

标签: opengl graphics 3d glsl skybox


【解决方案1】:

您根本不需要一些环境几何图形。您需要做的就是绘制一个全屏四边形,并为其计算正确的纹理坐标。现在有了现代 GL,我们甚至不需要为此提供顶点数据,我们可以使用 无属性 渲染:

顶点着色器:

#version 330 core
out vec3 dir;
uniform mat4 invPV;
void main()
{
        vec2 pos  = vec2( (gl_VertexID & 2)>>1, 1 - (gl_VertexID & 1)) * 2.0 - 1.0;
        vec4 front= invPV * vec4(pos, -1.0, 1.0);
        vec4 back = invPV * vec4(pos,  1.0, 1.0);

        dir=back.xyz / back.w - front.xyz / front.w;
        gl_Position = vec4(pos,1.0,1.0);
}

其中invPVinverse(Projection*View),因此它将考虑您的相机方向以及投影。原则上,这可以进一步简化,具体取决于您可以对投影矩阵施加多少约束。

片段着色器:

#version 330 core
in vec3 dir;
out color;
uniform samplerCube uTexEnv;
void main()
{
        color=texture(uTexEnv, dir);
}

要使用它,您只需绑定一个空的 VAO 和您的纹理,上传您的 invPV 矩阵并调用 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)

这种方法当然可以用于球形纹理映射而不是立方体贴图

【讨论】:

  • 从投影空间进行转换以用于屏幕四边形的工作做得很好,没有属性的加分。
【解决方案2】:
  1. 这是视图深度和形状的问题

    最好的 skybox 形状是(半)球体,因为它的渲染表面投影到相机空间几乎没有变形。如果您使用任何其他形状,则会出现投影伪影,尤其是在角落,例如大多数应用程序/游戏使用立方体 skybox。以有限的半径(不仅仅是单个点)查看太阳并旋转视图,使太阳从视图的中间到侧面。然后通常太阳会从圆形/圆盘形扭曲为椭圆形/椭圆形:

    这是由于 skyboxcamera 之间的距离发生了变化。如果将其与直接渲染的星星进行比较:

    然后你就可以看出区别了。第一张图片是谷歌找到的第一张相关图片(来自某些游戏),第二张是我认为 Space Engineers 的屏幕截图,最后一张是由我的 astro 应用程序渲染的,请参见

    因此,远离球体的形状越远,得到的扭曲就越多。

    使用 4 面金字塔甚至比立方体更糟糕,因为边之间的角度更糟糕,会产生更大的伪影。另一个问题是您需要更大尺寸的金字塔来覆盖相同的空间。如果您在 skybox 渲染期间出于某些目的使用 Depth Buffer,则可能会通过增加 Z_far 平面来显着影响精度。

  2. 开销

    6 和 4 个多边形之间的差异并不大,因为 天空盒 很大(覆盖整个视图),速度主要取决于提交到屏幕的像素/纹素数而不是顶点数。所以金字塔可能比立方体更慢,因为它需要更大的面(需要更多的插值器迭代)。但是如果你想使用球形 skybox 那么你还需要球形纹理,因为如果你使用标准立方体纹理,失真仍然存在,而且这些更难维持创建,......那就是为什么更多地使用立方体。

  3. 球形天空盒

    他们需要不同类型的纹理。半球形纹理如下所示:

【讨论】:

  • 你确定吗?如果我使用 6 个标准纹理并将它们映射到具有正常纹理坐标的立方体,那么是的,它会失真。但是由于我在片段着色器中标准化了顶点位置,所以我得到了一个球体,正如你已经说过的,球体非常适合天空盒。而且,面部的插值真的不重要,因为模型的大小完全不相关(如果深度缓冲区被禁用)......
  • @Pikaju 我同意,但要使其工作,您需要球面映射纹理而不是立方纹理,否则您将拥有完美的球形天空盒,其上带有扭曲的纹理,其结果类似于立方体天空盒
  • @Pikaju 在答案末尾添加了半球形纹理示例的图像
  • @Pikaju:不,你不需要球形纹理,立方体贴图就可以了。将球体映射到 2D 纹理时,您总是有一些非最佳参数化。这并不意味着您会在图像中出现失真,它只是意味着有效分辨率会根据您的样本位置而有所不同。对于立方体贴图,最坏的情况是从角落采样。
猜你喜欢
  • 2018-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多