2014-06-11 59 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

就像我評論你的建議,我也很困惑。但着色器代碼是我編輯的唯一的東西。關於這些變化,我只修改了每個頂點的輸出,並且由於我通過了所有階段的法線,所以我刪除了幾何着色器中法線的計算。 –