为什么人们不使用四面体作为天空盒? [英] Why don't people use tetrahedrons for skyboxes?

查看:25
本文介绍了为什么人们不使用四面体作为天空盒?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

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

顶点着色器:

#version 330 核心出 vec3 目录;统一 mat4 invPV;无效主(){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 返回 = 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 核心在 vec3 目录中;出颜色;统一的samplerCube uTexEnv;无效主(){颜色=纹理(uTexEnv,目录);}

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

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

When rendering a sky with a fixed texture in 3D games, people often create 6 textures in a cube map first, and then render a cube around the camera. In GLSL, you can access the pixels in the textures with a normal instead of a texture coordinate, and you can easily get this normal by normalizing the fragment position relative to the camera. However, this process can be done with any shape that surrounds the camera, because when you normalize each position it will always result in a sphere. Now I'm wondering: Why is it always a cube and not a tetrahedron? Rendering a cube takes 12 triangles, a tetrahedron only 4. And as I already said, any shape that surrounds the camera works. So tetrahedrons take less VRAM and are faster to render, without any downsides? Why not use them?

解决方案

You don't need some environment geometry at all. All you need to do is drawing a full screen quad, and just compute the correct texture coordinates for it. Now with modern GL, we don't even need to supply vertex data for this, we can use attributless rendering:

Vertex Shader:

#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);
}

where invPV is inverse(Projection*View), so it will take your camera orientation as well as the projection into account. This can in principle be even further simplified, depending on how much constraints you can put on the projection matrix.

Fragment Shader:

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

To use this, you simply need to bind an empty VAO and your texture, upload your invPV matrix and call glDrawArrays(GL_TRIANGLE_STRIP, 0, 4).

This approach could of course be used for spherical texture mapping instead of cube maps

这篇关于为什么人们不使用四面体作为天空盒?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆