2014-06-11 54 views
5

在我最近的项目中我正在使用硬件方面镶嵌。我想要实施的管道应采用低多边形网格,镶嵌它并应用位移贴图。GLSL Tessellation位移映射

Tessellation工作正常,正如我预期的那样。但是,当我在镶嵌评估着色器中应用位移贴图时,我得到的输出有点随机。

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

enter image description here

这是我所得到的,当我使我的位移(使用相同的纹理两种着色和位移):

enter image description here

着色器代码如下:

//顶点着色器

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

如果有人能够帮助我,那该多好。

+0

不应该产生的位移始终从给予unorm纹理(现在你有其中位移出现移动的部分地区表面朝外顶点***内的***圆柱体)?我强烈怀疑TES中的正常计算有问题。也许你可以将你在TES中计算的正常值传递给geometry/fragment并将其可视化,看看它是否正确? –

+1

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

+0

感谢您的建议!我不会认为这会做到这一点,但实际上它确实是一切毁掉了一切的'gFacetNormal'。 我将编写其他有兴趣实现例程的代码。 –

回答

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

//镶嵌控制

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

//离散方法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; 
} 

//几何

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

说实话,我有点困惑。这是你改变的唯一***的东西吗?几何着色器在*镶嵌之后运行*,所以真正奇怪的位移不应该通过对GS进行修改来解决。它可能解决的问题是照明问题。 –

+1

就像我评论你的建议,我也很困惑。但着色器代码是我编辑的唯一的东西。关于这些变化,我只修改了每个顶点的输出,并且由于我通过了所有阶段的法线,所以我删除了几何着色器中法线的计算。 –