2014-06-11 34 views
5

Son projemde donanımsal yan tessellation ile çalışıyorum. Uygulamak istediğim boru hattı düşük bir poli örgü almalı, onu tessellate etmeli ve bir yer değiştirme haritası uygulamalıdır. Döşeme, iyi görünmesini beklediğim gibi iyi çalışıyor. Bununla birlikte, yer değiştirme haritasını, mozaikleme değerlendirme gölgelendiricisine uyguladığım zaman, biraz rastgele olan bir çıktı elde ediyorum. GLSL Tessellation Displacement Mapping

Bu

yer değiştirme olmadan çıktı Bu aynı doku kullanarak (benim yer değiştirme etkinleştirdiğinizde ne alıyorum

enter image description here

(benim texCoords doğru olup olmadığını doğrulamak için bir doku olarak heightmap kullanılır) 'dir renklendirme ve yer değiştirme) her ikisi için de:

enter image description here

gölgelendirici kodu aşağıdaki gibidir:

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

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

// GEOMETRİ

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

// FRAGMAN

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

Eğer birisi bana yardım edebilirse iyi olur. @ AndonM.Coleman için

+0

her zaman deplasman taşımak görünen bazı alanları vardır şu anda (bir unorm doku verilmiş yüzeyden dışa dönük olmak deplasman olmamalı silindirler *** içerisindeki köşeler? TES'te normal hesaplamanızın yanlış bir şey olduğundan şüpheleniyorum. Belki de TES'te hesapladığınız normal geometri/parçalara kadar geçebilir ve doğru görüp görmediğini görmek için görselleştirebilirsiniz. –

+1

Aslında: "gFacetNormal" çıkışı yalnızca geometri gölgelendiricisindeki ilk köşeniz için tanımlanmıştır. Çıktıların her bir “EmitVertex (...)” sonra GLSL şartnamesine göre ayarlanması veya tanımlanamayacakları. Birçok uygulama, son değeri ayarlanmış olarak yeniden kullanır, ancak bunun açık bir şekilde çalışması için bu davranışa güvenemezsiniz. 'GFacetNormal' öğesini her 'EmitVertex''den önce bir kez ayarlamanız gerekir. * 'void EmitVertex()' - "Çıkış değişkenlerinin mevcut değerlerini geçerli çıkış ilkeline yayar. Bu çağrının ardından çıkış değişkenlerinin değerleri tanımsızdır." * –

+0

Tavsiye için teşekkürler! Bunun hile yapacağını düşünmezdim, ama aslında her şeyi bozan "gFacetNormal" idi. Rutini uygulamakla ilgilenen herkesin kodunu düzenleyeceğim. –

cevap

2

teşekkürler ben aslında meseleyi

çözüldü: gFacetNormal sadece geometri gölgelendiricideki ilk köşe için tanımlanan çıktı. Çıkışlar, her EmitVertex (...) 'den sonra GLSL spesifikasyonuna göre ayarlanmalı veya tanımsız olacaktır. Birçok uygulama, son değeri ayarlanmış olarak yeniden kullanır, ancak bunun açık bir şekilde çalışması için bu davranışa güvenemezsiniz. Her EmitVertex'ten bir kere gFacetNormal ayarlamalısınız. void EmitVertex() - "Çıkış değişkenlerinin mevcut değerlerini mevcut çıkış primitifine yayar. Bu çağrının geri dönüşünde, çıkış değişkenlerinin değerleri tanımsızdır."Beni

Aptal olduğunu fark etmemiş, ancak burada çalışan koddur:

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

// mozaikleme KONTROL

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

// mozaikleme DEĞERLENDİRME

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

// GEOMETRİ

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

// FRAGMAN

#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

Dürüst olmak gerekirse, biraz kafam karıştı. Bu değiştirdiğin *** tek şey mi? Geometri Shader * tessellasyondan sonra * çalışır, bu yüzden gerçekten garip deplasman GS için bir değişiklik yaparak çözülmemelidir. Çözeceği şey, aydınlatma ile ilgili sorunlardır. –

+1

Tavsiyenize yorum yaptığım gibi ben de kafam karışmıştı. Ancak gölgelendirici kod, düzenlediğim tek şey. Bu değişiklikler ile ilgili olarak ben sadece vertex çıktısını değiştirdim ve geometrinin gölgelendirmesindeki normallerin hesaplamasını sildiğimden, normalleri TÜM aşamalardan geçiriyorum. –