2014-06-11 5 views
5

최근 프로젝트에서 하드웨어 쪽 테셀레이션으로 작업하고 있습니다. 구현하고자하는 파이프 라인은 낮은 폴리 메쉬를 가져 와서 테셀레이션하고 변위 맵을 적용해야합니다.GLSL 테셀레이션 변위 매핑

테셀레이션은 잘 작동하고 잘 보이는 것처럼 보입니다. 그러나 테셀레이션 평가 쉐이더에서 변위 맵을 적용 할 때 어느 정도 랜덤 한 출력을 얻습니다.

는 변위없이 출력이 내가 같은 질감을 사용하여 (내 변위를 활성화 할 때 내가 무엇을 얻을

enter image description here

(내 texCoords이 정확한지 여부를 확인하기 위해 텍스처로 하이트를 사용)입니다 착색 변위) 모두 :

enter image description here

셰이더 코드는 다음과 같다 : 012

3,516,

// 정점 셰이더

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

누군가 나를 도와 줄 수 있으면 좋을 것입니다. @ AndonM.Coleman에

+0

항상 변위가 이동할 것으로 보인다 일부 지역이 지금의 (a unorm 질감을 주어 표면에서 바깥쪽으로 향하게 변위 안 꼭지점 *** *** 실린더 안쪽)? 나는 TES에서 당신의 정상적인 계산에 문제가 있다고 생각합니다. 아마도 TES에서 계산 한 법선을 기하학/조각으로 전달하고 시각화하여 올바른 것으로 보았습니까? –

+1

사실 : 출력 'gFacetNormal'은 기하 구조 쉐이더의 첫 번째 정점에 대해서만 정의됩니다. GLSL 명세에 따라'EmitVertex (...) '마다 출력을 설정해야합니다. 그렇지 않으면 정의되지 않습니다. 대부분의 구현에서는 마지막 값 세트를 다시 사용하지만이 동작을 이식 가능하게하려면이 동작에 의존 할 수 없습니다. 'EmitVertex' 전에'gFacetNormal'을 한 번 설정해야합니다. *'void EmitVertex()'- "현재 출력 프리미티브에 출력 변수의 현재 값을 내 보냅니다.이 호출에서 돌아 왔을 때 출력 변수의 값은 정의되지 않았습니다."* –

+0

조언 주셔서 감사합니다 !!! 나는 이것이 트릭을 할 것이라고 생각하지 않았지만 실제로는 모든 것을 파열시킨 'gFacetNormal '이었다. 루틴을 구현하는 데 관심이있는 모든 사람들을 위해 코드를 편집합니다. –

답변

2

덕분에 나는 사실 그 문제를

해결 : gFacetNormal는 지오메트리 셰이더에서 첫 번째 정점에 대해 정의 된 출력을. GLSL 사양에 따라 EmitVertex (...)마다 출력을 설정해야합니다. 그렇지 않으면 정의되지 않습니다. 대부분의 구현에서는 마지막 값 세트를 다시 사용하지만이 동작을 이식 가능하게하려면이 동작에 의존 할 수 없습니다. 모든 EmitVertex 앞에 gFacetNormal을 한 번 설정해야합니다. 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; 
} 

// 테셀레이션 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; 
    } 
} 

// 테셀레이션 평가

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

솔직히 말해서, 나는 조금 혼란 스럽다. 이건 *** 당신이 바꾼 *** 것입니까? Geometry Shader는 * 테셀레이션 이후에 실행되므로 GS를 수정하면 정말 이상한 변위가 해결되지 않아야합니다. 그것이 조명으로 문제가 있지만 해결할 수 있습니다. –

+1

글쎄 내가 너의 충고에 대해 언급 한 것처럼 나는 너무 혼란스러워했다. 그러나 쉐이더 코드가 내가 편집 한 유일한 것입니다. 이러한 변경 사항에 대해서는 버텍스 별 출력 만 수정했으며 모든 단계를 통해 법선을 전달하기 때문에 형상 쉐이더에서 법선 계산을 삭제했습니다. –