简单的程序天空盒

时间:2012-03-25 22:01:47

标签: opengl glsl

作为尝试生成一个非常简单的天空的一部分,我创建了一个天空盒(基本上是一个从(-1,-1,-1)到(1,1,1)的立方体,它是绘制的在我的所有几何体之后,通过以下简单的顶点着色器强制到后面:

#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 normal;

out Data
{
    vec4 eyespace_position;
    vec4 eyespace_normal;
    vec4 worldspace_position;
    vec4 raw_position;
} vtx_data;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    mat4 view_without_translation = view;
    view_without_translation[3][0] = 0.0f;
    view_without_translation[3][1] = 0.0f;
    view_without_translation[3][2] = 0.0f;

    vtx_data.raw_position = position;
    vtx_data.worldspace_position = model * position;
    vtx_data.eyespace_position =  view_without_translation * vtx_data.worldspace_position;

    gl_Position = (projection * vtx_data.eyespace_position).xyww;
}

由此,我试图将天空显示为一个非常简单的渐变,从顶部的深蓝色到地平线上的浅蓝色。

显然,简单地根据每个片段的Y坐标混合我的两种颜色会看起来非常糟糕:你正在看一个盒子而不是一个圆顶的事实很快就会清楚,如下所示:

wrong skybox

请注意框内左上角和右上角相当明显的“角落”。

本能地,我认为明显的解决方法是将每个片段的位置标准化,以获得单位球体上的位置,然后取出该坐标。我认为这会产生一个对于给定的“高度”恒定的值,如果这是有意义的话。像这样:

#version 330
in Data
{
    vec4 eyespace_position;
    vec4 eyespace_normal;
    vec4 worldspace_position;
    vec4 raw_position;
} vtx_data;

out vec4 outputColor;

const vec4 skytop = vec4(0.0f, 0.0f, 1.0f, 1.0f);
const vec4 skyhorizon = vec4(0.3294f, 0.92157f, 1.0f, 1.0f);

void main()
{  
    vec4 pointOnSphere = normalize(vtx_data.worldspace_position);
    float a = pointOnSphere.y;
    outputColor = mix(skyhorizon, skytop, a);
}

然而结果与第一个截图大致相同(我可以在必要时发布它,但由于它在视觉上类似于第一个,我现在正在跳过它来缩短这个问题)。

经过一些随机摆弄(货物崇拜编程,我知道:/),我意识到这有效:

void main()
{  
    vec3 pointOnSphere = normalize(vtx_data.worldspace_position.xyz);
    float a = pointOnSphere.y;
    outputColor = mix(skyhorizon, skytop, a);
}

唯一的区别是我没有它的W分量来标准化位置。

这是工作结果:(截图中的差异很明显,但在动作中非常明显) correct skybox

所以,最后,我的问题是:为什么在以前的版本失败时这会起作用?我必须误解一些关于同质坐标的非常基本的东西,但我的大脑现在没有点击!

1 个答案:

答案 0 :(得分:3)

GLSL normalize本身不处理齐次坐标。它将坐标解释为属于R^4。这通常不是你想要的。但是,如果vtx_data.worldspace_position.w == 0,则规范化应产生相同的结果。

我不知道vec3 pointOnSphere = normalize(vtx_data.worldspace_position);的含义是什么,因为左侧也应该有vec4类型。