OpenGL – GLSL曲面细分位移映射 (Tessellation Shader Texcoord)

在我最近的项目中,我正在使用硬件端曲面细分.我想要实现的管道应采用低多边形网格,对其进行细分并应用置换贴图.

Tessellation工作正常,就像我预期的那样.但是,当我在曲面细分评估着色器中应用置换贴图时,我得到一个有点随机的输出.

这是没有位移的输出(我使用高度图作为纹理来验证我的texCoords是否准确)

这是我启用移位时获得的(使用相同的纹理进行着色和置换):

着色器代码如下:

// VERTEX SHADER

#version 430

layout(location = 0) in vec4 vertex;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec2 texCoord;

out vec3 vPosition;
out vec3 vNormal;
out vec2 vTexCoord;

void main() {
    vPosition = vertex.xyz;
    vNormal = normal.xyz;
    vTexCoord = texCoord;
}

// TESS CONTROL

#version 430

layout(vertices = 3) out;

in vec3 vPosition[];
in vec3 vNormal[];
in vec2 vTexCoord[];
out vec3 tcPosition[];
out vec3 tcNormal[];
out vec2 tcTexCoord[];

uniform float innerTessLevel;
uniform float outerTessLevel;

void main(){

    float inTess  = innerTessLevel;
    float outTess = outerTessLevel;

    tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
    tcNormal[gl_InvocationID]   = vNormal[gl_InvocationID];
    tcTexCoord[gl_InvocationID] = vTexCoord[gl_InvocationID];
    if(gl_InvocationID == 0) {
        gl_TessLevelInner[0] = inTess;
        gl_TessLevelInner[1] = inTess;
        gl_TessLevelOuter[0] = outTess;
        gl_TessLevelOuter[1] = outTess;
        gl_TessLevelOuter[2] = outTess;
        gl_TessLevelOuter[3] = outTess;
    }
}

// TESS EVAL

#version 430

layout(triangles, equal_spacing, ccw) in;

in vec3 tcPosition[];
in vec3 tcNormal[];
in vec2 tcTexCoord[];
out vec3 tePosition;
out vec2 teTexCoord;
out vec3 teNormal;

uniform mat4 ModelViewProjection;
uniform mat4 ModelView;

uniform sampler2D texHeight;

void main(){
    vec3 p0 = gl_TessCoord.x * tcPosition[0];
    vec3 p1 = gl_TessCoord.y * tcPosition[1];
    vec3 p2 = gl_TessCoord.z * tcPosition[2];
    vec3 pos = p0 + p1 + p2;

    vec3 n0 = gl_TessCoord.x * tcNormal[0];
    vec3 n1 = gl_TessCoord.y * tcNormal[1];
    vec3 n2 = gl_TessCoord.z * tcNormal[2];
    vec3 normal = normalize(n0 + n1 + n2);

    vec2 tc0 = gl_TessCoord.x * tcTexCoord[0];
    vec2 tc1 = gl_TessCoord.y * tcTexCoord[1];
    vec2 tc2 = gl_TessCoord.z * tcTexCoord[2];  
    teTexCoord = tc0 + tc1 + tc2;

    float height = texture(texHeight, teTexCoord).x;
    pos += normal * (height * 0.5f);

    gl_Position = ModelViewProjection * vec4(pos, 1);
    teNormal    = vec3(ModelView * vec4(normal,0.0)).xyz;
    tePosition  = vec3(ModelView * vec4(pos,1.0)).xyz;
}

//几何

#version 430

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

uniform mat4 ModelView;

in vec3 tePosition[3];
in vec2 teTexCoord[3];
in vec3 teNormal[3];
out vec3 gFacetNormal;
out vec2 gTexCoord;

void main() {

    gFacetNormal = teNormal[0];
    gTexCoord = teTexCoord[0];
    gl_Position = gl_in[0].gl_Position; EmitVertex();

    gFacetNormal = teNormal[1];
    gTexCoord = teTexCoord[1];
    gl_Position = gl_in[1].gl_Position; EmitVertex();

    gFacetNormal = teNormal[2];
    gTexCoord = teTexCoord[2];
    gl_Position = gl_in[2].gl_Position; EmitVertex();

    EndPrimitive();
}

//分段

#version 430

layout(location = 0) out vec4 fragColor;

in vec3 gFacetNormal;
in vec2 gTexCoord;

uniform float lit;
uniform vec3 light;
uniform sampler2D texHeight;

void main() {
    #ifndef ORANGE_PURPLE
    vec3 color = gl_FrontFacing ? vec3(1.0,0.0,0.0) : vec3(0.0,0.0,1.0);
    #else
        vec3 color = gl_FrontFacing ? vec3(1.0,0.6,0.0) : vec3(0.6,0.0,1.0);
    #endif
    if (lit > 0.5) {
        color = texture(texHeight, gTexCoord).xyz; 
        vec3 N = normalize(gFacetNormal);
        vec3 L = light;
        float df = abs(dot(N,L));
        color = df * color;
        fragColor = vec4(color,1.0);
    }
    else {
        fragColor = vec4(color,1.0);
    }
}