GLSL曲面位移映射

时间:2014-06-11 15:08:42

标签: opengl glsl tessellation

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

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

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

enter image description here

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

enter image description here

着色器代码如下:

// 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;

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.2f);

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

// GEOMETRY

#version 430

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

uniform mat4 ModelView;

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

void main() {
    vec3 A = tePosition[2] - tePosition[0];
    vec3 B = tePosition[1] - tePosition[0];
    vec4 N = vec4( normalize(cross(A, B)) , 0.0);
    gFacetNormal = N.xyz;

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

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

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

    EndPrimitive();
}

// FRAGMENT

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

如果有人可以帮助我,那就太好了。

1 个答案:

答案 0 :(得分:2)

感谢@ AndonM.Coleman我解决了这个问题

  

实际上:输出gFacetNormal仅为几何着色器中的第一个顶点定义。必须在每个EmitVertex(...)之后根据GLSL规范设置输出,否则它们将是未定义的。许多实现重用最后一个值集,但如果您希望它可以移植,则不能依赖该行为。你需要在每个EmitVertex之前设置一次gFacetNormal。 void EmitVertex() - “将输出变量的当前值发送到当前输出原语。从此调用返回时,输出变量的值未定义。”

愚蠢的我不注意,但这是工作代码:

// VERTEX

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

// TESSELLATION 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;
    }
}

// TESSELLATION EVALUATION

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

// GEOMETRY

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

// FRAGMENT

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