高度映射到法线贴图GLSL着色器问题

时间:2014-07-13 12:14:14

标签: opengl graphics 3d rendering glsl

我正在为GPU生成景观编写模块。我使用OpenGL和GLSL进行生成和可视化。在我写了一个高度图生成着色器后,我开始考虑照明法线。我为普通地图生成编写了一个简单的着色器,它有点工作,但结果很奇怪。法线贴图中的四边形有一些意外的分割。 请参阅screen capture

以下是片段着色器:

#version 330

uniform sampler2D heightmap;
uniform float res_x;
uniform float res_y;

in vec4 fragmentColor;
in vec2 tc;
in vec4 pos;
in vec3 normal;

out vec4 color;

void main(void)
{
    float x_d = 1.0/res_x; //size of texel
    float y_d = 1.0/res_y;

    //1024 = resolution of hm
    vec3 top = vec3(tc.x*1024.0, texture2D(heightmap, tc + vec2(0.0, y_d)).r, (tc.y + y_d)*1024.0);
    vec3 bottom = vec3(tc.x*1024.0, texture2D(heightmap, tc + vec2(0.0, -y_d)).r, (tc.y - y_d)*1024.0);
    vec3 left = vec3((tc.x - x_d)*1024.0, texture2D(heightmap, tc + vec2(-x_d, 0.0)).r, tc.y*1024.0);
    vec3 right = vec3((tc.x + x_d)*1024.0, texture2D(heightmap, tc + vec2(x_d, 0.0)).r, tc.y*1024.0);
    vec3 center = vec3(tc.x*1024.0, texture2D(heightmap, tc + vec2(0.0, 0.0)).r, tc.y*1024.0);

    //this 4 vectors are forming 4 triangles
    vec3 top_minus_center = normalize(top - center);
    vec3 bot_minus_center = normalize(bottom - center); 
    vec3 left_minus_center = normalize(left - center);
    vec3 right_minus_center = normalize(right - center);

    //calc 4 normals to 4 triangls
    vec3 _normal[4];
    _normal[0] = normalize(cross(left_minus_center, top_minus_center));
    _normal[1] = normalize(cross(right_minus_center, top_minus_center));
    _normal[2] = normalize(cross(right_minus_center, bot_minus_center));
    _normal[3] = normalize(cross(left_minus_center, bot_minus_center));

    //right direction of normal
    for (int i = 0; i < 4; i++)
        if (_normal[i].y < 0.0)
            _normal[i] = -_normal[i];

    color = vec4(((_normal[0] + _normal[1] + _normal[2] + _normal[3]).xzy/4.0)/2.0 + 0.5, 1.0);//packing normal
}

造成这种缺陷的原因是什么?

1 个答案:

答案 0 :(得分:1)

纹理坐标为0到1

我会建议一些事情:

// get the heights
float top = texture2D(heightmap, tc + vec2(0.0, y_d)).r;
float bottom = texture2D(heightmap, tc + vec2(0.0, -y_d)).r;
float left = texture2D(heightmap, tc + vec2(-v_x, 0.0)).r;
float right = texture2D(heightmap, tc + vec2(v_x, 0.0)).r;
// The center one is not really important

vec3 n = normalize(vec3(bottom - top, left - right, 2.0));
// viola, pack it and go