TouchDesigner의 GeometryShader

11826 단어 TouchDesignerGLSL
TouchDesigner는 지오메트리 셰이더도 지원합니다. 사용합시다!



준비



우선 적당하게 Sphere를 냅니다. Sphere의 Primitive Type은 Polygon으로 둡니다.



VertexShader 및 FragmentShader



그런 다음 GLSL MATGeo COMP에 재질로 설정합니다. 그런 다음 GLSL Text DAT로 작성된 셰이더를 저장하는 세 가지를 만들고 각각 Vertex, Geometry, Fragment 및 이름을 바꾸고 GLSL MAT 매개 변수에 연결합니다.



여기까지 할 수 있으면, 버텍스 셰이더와 프래그먼트 쉐이더를 기술해 갑시다. (Phong MAT등으로부터 Output한 것으로 전혀 OK입니다만, 지오메트리 쉐이더가 메인이므로 최소한으로 하고 있습니다.)

Vertex
out int cameraIndex;

void main(){
    cameraIndex = TDCameraIndex();
    gl_Position = TDDeform(P);
}

조각
out vec4 fragColor;

void main(){
    fragColor = vec4(1.0);
}

GeometryShader 작성



과거의 파이프라인에서는 정점은 CPU측에서 준비하는 것이고, GPU측에서 그 수를 늘리거나 줄일 수 없었습니다. 거기서, 이 정점을 증감하는 기능을 GPU상에서 실현하는 쉐이더 스테이지가 짜넣어졌습니다. 그것이 지오메트리 셰이더가 됩니다. 정점의 증감에 의해, 실질적으로 프리미티브를 조작할 수가 있습니다.

Geometry
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

in int[] cameraIndex;

void main(){
    vec3 P0 = gl_in[0].gl_Position.xyz;
    vec3 P1 = gl_in[1].gl_Position.xyz;
    vec3 P2 = gl_in[2].gl_Position.xyz;

    gl_Position = uTDMats[cameraIndex[0]].worldCamProj * vec4(P0, 1.0);
    EmitVertex();

    gl_Position = uTDMats[cameraIndex[1]].worldCamProj * vec4(P1, 1.0);
    EmitVertex();

    gl_Position = uTDMats[cameraIndex[2]].worldCamProj * vec4(P2, 1.0);
    EmitVertex();
}

첫 번째, 첫 번째 줄 layout(〜) in;에서 기하학 셰이더에 들어오는 프리미티브를 지정하고 두 번째 줄 layout(〜) out;에서 출력 할 프리미티브를 지정합니다. 그리고, gl_in[i].gl_Position 로 입력된 프리미티브의 Position 정보를 꺼내고 있습니다.

파이프라인에서 지오메트리 셰이더의 스테이지는 버텍스 셰이더와 조각 셰이더 사이에 위치합니다. 따라서 버텍스 셰이더에서는 좌표 변환(TD에서는 TDWorldToProj() )을 하지 않고 그대로 지오메트리 셰이더에 Position 정보를 보냅니다. 마지막으로, gl_Position 에 좌표 변환 행렬을 곱한 Position 정보를 세트해, EmitVertex() 로 정점을 다음의 스테이지에 돌려줍니다. 위에서는 그대로 Position의 정보를 받아 들였을 뿐이므로 외형에는 변화가 일어나고 있지 않습니다.



GeometryShader로 다각형으로 분할하여 이동



그럼, 이번은 Hello World로서 폴리곤으로 분할해 법선 방향으로 움직여 보겠습니다.

Geometry
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

uniform float time;
uniform float dispScale;

in int[] cameraIndex;

void main(){

    vec3 P0 = gl_in[0].gl_Position.xyz;
    vec3 P1 = gl_in[1].gl_Position.xyz;
    vec3 P2 = gl_in[2].gl_Position.xyz;

    vec3 d0 = P0 - P1;
    vec3 d1 = P2 - P1;

    for(int i = 0; i < 3; i++){
        vec4 P = gl_in[i].gl_Position;
        vec3 N = normalize(cross(d1, d0));

        float disp = 2.0 + sin(time * 5.0) * dispScale;     
        P += vec4(P.xyz + N * disp, 1.0);

        gl_Position = uTDMats[cameraIndex[i]].worldCamProj * P;
        EmitVertex();
    }
}



다각형이 분할된 상태로 움직입니다. 이것으로 표현의 폭을 넓힐 수 있을 것 같네요!

참고



셰이더의 기본 지식은 '게임 제작자가 되기 위한 3D 그래픽 기술'을 읽는 것이 좋습니다. TouchDesigner 특유의 Uniform에 대해서는 공식 Wiki Write a GLSL Material를 참조하십시오.

좋은 웹페이지 즐겨찾기