2014-06-11 13 views
5

w moim ostatnim projekcie Pracuję nad tesselacją strony sprzętowej. Rurociąg, który chcę zaimplementować, powinien mieć niską siatkę polietylenową, przetopić ją i zastosować mapę przemieszczeń.Mapowanie przesunięcia w tesselacji GLSL

Tesselacja działa dobrze i dokładnie tak, jak się spodziewałem. Jednak po zastosowaniu mapy przemieszczeń w module cieniującym do oceny teselacji otrzymuję wynik nieco losowy.

To wyjście bez przemieszczenia (użyłem heightmap jako tekstury w celu sprawdzenia, czy moje texCoords są dokładne)

enter image description here

To co mam, kiedy włączyć mój przemieszczenia (stosując tę ​​samą fakturę zarówno do barwienia i przemieszczenia):

enter image description here

Kod modułu cieniującego jest w następujący sposób: 012

// cieniowania wierzchołków

#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 KONTROLA

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

// GEOMETRIA

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

Byłoby miło, gdyby ktoś mógł mi pomóc w tym.

+0

Gdyby nie przemieszczenie zawsze być skierowana na zewnątrz od powierzchni danego się unorm tekstury (teraz masz jakieś obszary, w których pojawia się przesunięcie, aby przesunąć vertices *** inside *** the cylinder)? Podejrzewam, że coś jest nie tak z twoimi normalnymi obliczeniami w TES. Być może mógłbyś przekazać normalny, który obliczyłeś w TES, do geometrii/fragmentu i wizualizować go, aby sprawdzić, czy wygląda on poprawnie? –

+1

W rzeczywistości: wyjście 'gFacetNormal' jest zdefiniowane tylko dla pierwszego wierzchołka w module cieniującym geometrii. Wyjścia muszą być ustawione po każdym 'EmitVertex (...)' zgodnie ze specyfikacją GLSL, lub będą niezdefiniowane. Wiele implementacji wykorzystuje ponownie ostatni zestaw wartości, ale nie możesz polegać na tym zachowaniu, jeśli chcesz, aby to działało przenośnie. Musisz ustawić 'gFacetNormal' przed każdym' EmitVertex'. * 'void EmitVertex()' - "Emituje bieżące wartości zmiennych wyjściowych do bieżącego prymitywu wyjściowego.Wracając z tego wywołania, wartości zmiennych wyjściowych są niezdefiniowane." * –

+0

Dzięki za radę !!! Nie pomyślałbym, że to załatwi sprawę, ale tak naprawdę to "gFacetNormal" zniszczyło wszystko. Będę edytować kod dla wszystkich, którzy są zainteresowani wdrożeniem rutyny. –

Odpowiedz

2

Dzięki @ AndonM.Coleman Rozwiązałem sprawę

W rzeczywistości: wyjście gFacetNormal jest zdefiniowana tylko dla pierwszego wierzchołka w shader geometrii. Wyjścia muszą być ustawione po każdym EmitVertex (...) zgodnie ze specyfikacją GLSL lub będą niezdefiniowane. Wiele implementacji wykorzystuje ponownie ostatni zestaw wartości, ale nie możesz polegać na tym zachowaniu, jeśli chcesz, aby to działało przenośnie. Musisz ustawić gFacetNormal raz przed każdym EmitVertex. void EmitVertex() - "Emituje bieżące wartości zmiennych wyjściowych do bieżącego prymitywu wyjściowego, a po powrocie z tego wywołania wartości zmiennych wyjściowych są niezdefiniowane."

głupie nie zauważyć, ale tutaj jest kod działa:

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

// teselacji KONTROLA

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

// teselacji OCENA

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

// GEOMETRIA

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

Szczerze mówiąc, jestem nieco zdezorientowany. Czy to właśnie *** *** zmieniłeś? Shader geometrii uruchamia * po * tesselacji, więc naprawdę dziwne przesunięcie nie powinno być rozwiązane przez wprowadzenie modyfikacji do GS. To, co może rozwiązać, to problemy z oświetleniem. –

+1

Cóż, tak jak skomentowałem twoją radę, byłem też bardzo zdezorientowany. Ale kod edytora jest jedyną rzeczą, którą edytowałem. Odnośnie tych zmian, zmodyfikowałem tylko wynik na jeden vertex i skoro przechodzę normalne przez WSZYSTKIE etapy, usunąłem obliczenia normalne w shaderze geometrii. –