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

Opengl 高度贴图到法线贴图GLSL着色器问题,opengl,graphics,3d,rendering,glsl,Opengl,Graphics,3d,Rendering,Glsl,我正在写一个GPU生成的景观模块。我正在使用OpenGL和GLSL进行生成和可视化。在我编写了heightmap生成着色器之后,我开始考虑照明的法线。我为法线贴图生成编写了一个简单的着色器,虽然有点效果,但结果非常奇怪。法线贴图中存在一些意外的四边形分割。 看 以下是片段着色器: #version 330 uniform sampler2D heightmap; uniform float res_x; uniform float res_y; in vec4 fragmentColor;

我正在写一个GPU生成的景观模块。我正在使用OpenGL和GLSL进行生成和可视化。在我编写了heightmap生成着色器之后,我开始考虑照明的法线。我为法线贴图生成编写了一个简单的着色器,虽然有点效果,但结果非常奇怪。法线贴图中存在一些意外的四边形分割。 看

以下是片段着色器:

#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
}
#版本330
均匀采样二维高度图;
均匀浮点数;
均匀浮点数;
在vec4片段颜色中;
在vec2tc;
在vec4位;
vec3正常;
输出vec4颜色;
真空总管(真空)
{
float x_d=1.0/res_x;//纹理的大小
浮动y_d=1.0/res_y;
//1024=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\ud)).r,(tc.y-y\ud)*1024.0);
vec3 left=vec3((tc.x-xud)*1024.0,texture2D(高度图,tc+vec2(-xud,0.0)).r,tc.y*1024.0);
vec3-right=vec3((tc.x+xu-d)*1024.0,texture2D(heightmap,tc+vec2(xu-d,0.0)).r,tc.y*1024.0);
vec3中心=vec3(tc.x*1024.0,texture2D(heightmap,tc+vec2(0.0,0.0)).r,tc.y*1024.0);
//这4个向量形成4个三角形
vec3上下中心=规格化(上中心);
vec3 bot_减去_中心=规格化(底部-中心);
vec3左_减去_中心=规格化(左-中心);
vec3右中心减去中心=规格化(右中心);
//将4条法线计算为4个三角形
vec3_正常[4];
_法线[0]=规格化(交叉(左_减_中心,上_减_中心));
_法线[1]=规格化(交叉(右_减_中心,顶部_减_中心));
_normal[2]=规格化(交叉(右减中心,右减中心));
_正常[3]=正常化(交叉(左_减_中心,右_减_中心));
//法线的右方向
对于(int i=0;i<4;i++)
if(_normal[i].y<0.0)
_正常[i]=-_正常[i];
color=vec4(((_-normal[0]+_-normal[1]+_-normal[2]+_-normal[3]).xzy/4.0)/2.0+0.5,1.0);//包装正常
}
此缺陷的原因是什么?

纹理坐标从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

不要将
texture2D
与GLSL 3.30着色器一起使用。它已被弃用。texture2D不是问题的原因。您可以只使用三个样本而不是四个样本。@Tara为什么?哪三个样品?怎么做?@zwcloud为什么?演出哪些样品?例如,中间、顶部、右侧。