OpenGL에서 멀티 패스 셰이더는 어떻게 작동합니까?


13

Direct3D에서 멀티 패스 셰이더는 문자 그대로 프로그램 내에서 패스를 정의 할 수 있기 때문에 사용이 간편합니다. OpenGL에서는 원하는만큼 많은 버텍스, 지오메트리 및 프래그먼트 셰이더를 셰이더 프로그램에 제공 할 수 있기 때문에 조금 더 복잡해 보입니다.

멀티 패스 셰이더의 일반적인 예는 툰 셰이더입니다. 한 패스는 실제 셀 쉐이딩 효과를 수행하고 다른 패스는 윤곽선을 만듭니다. 두 개의 정점 셰이더 "cel.vert"및 "outline.vert"와 두 개의 프래그먼트 셰이더 "cel.frag"및 "outline.frag"(HLSL에서 수행하는 방식과 유사)가있는 경우 어떻게해야합니까 풀 툰 쉐이더를 만들기 위해 결합?

다중 패스 GLSL 쉐이더의 이론을 알고 싶기 때문에 지오메트리 쉐이더를 사용할 수 있다고 말하고 싶지 않습니다.)


"Direct3D에서 멀티 패스 셰이더는 문자 그대로 프로그램 내에서 패스를 정의 할 수 있기 때문에 사용이 간편합니다." 아뇨. FX 파일에서 패스를 정의 할 수 있지만 HLSL 셰이더와 동일하지 않습니다.
— Nicol Bolas

답변:


11

멀티 패스 뒤에는 "이론"이 없습니다. "멀티 패스 셰이더"는 없습니다. 멀티 패스는 매우 간단합니다. 하나의 프로그램으로 객체를 그립니다. 그런 다음 다른 프로그램으로 객체를 그립니다 .

FX 파일과 같은 D3DX 항목을 사용하여 이러한 추가 패스를 숨길 수 있습니다. 그러나 그들은 여전히 ​​그렇게 작동합니다. OpenGL에는 단순히 숨을 곳이 없습니다.


1

셀 셰이더로 오브젝트를 렌더링 한 다음 아웃 라인 셰이더로 다시 렌더링하십시오.


1
두 가지 셰이더 프로그램을 만들어야합니까? 그렇다면 내가 원하는만큼 버텍스 / 형상 / 조각 셰이더를 셰이더 프로그램에 제공 할 수있는 이유는 무엇입니까? 하나의 프로그램으로이를 수행 할 수있는 방법이 있어야합니다.
— jmegaffin

1
여러 버텍스 (등) 셰이더를 제공하지 않습니다. 주요 기능은 하나뿐이므로 여러 개의 진입 점이 없습니다. 프로그램을 만들기 위해 서로 연결된 여러 파일을 가질 수 있다는 점에서 C 프로그램과 매우 유사합니다. 이러한 파일을 다른 프로그램간에 공유 할 수 있으므로 코드를 복제 할 필요는 없지만 각 파일이 반드시 자체 프로그램 인 것은 아닙니다.
— 질긴 검볼

1
그렇게하는 방법입니다. 한 셰이더 쌍으로 한 번 렌더링 한 후 (버텍스 + 프래그먼트) 다른 쌍으로 다시 렌더링하거나 동일한 버텍스 셰이더 + 다른 프래그먼트 셰이더를 사용하십시오. 때로는 버퍼로 렌더링하고 다른 셰이더를 사용하여 최종 결과에 '블렌드'합니다.
— Valmond

1

OpenGL 4.0에는 균일 한 서브 루틴이 있습니다. 이를 통해 오버 헤드가 거의없이 런타임시 교체 할 수있는 기능을 정의 할 수 있습니다. 따라서 각 패스마다 1 개의 기능을 만들 수 있습니다. 각 셰이더 유형마다 1 개의 기능이 있습니다.

거기에 여기에 튜토리얼 .

이전 OpenGL 버전의 경우 가장 좋은 방법은 여러 가지 셰이더를 사용하고 서로 바꾸는 것입니다. 그렇지 않으면 0.0 또는 1.0의 유니폼을 곱한 값을 합산하여 켜거나 끌 수 있습니다. 그렇지 않으면 조건부 if 문을 사용할 수 있지만 OpenGL은 모든 실행 / 패스마다 가능한 모든 결과를 실행하므로 너무 무겁지 않아야합니다.


0

GLSL에 대해 많은 것을 알고있는 사람들이 있으므로 레코드를 똑바로 세우기를 바랍니다. 그러나 내가 본 것에 따라 조각 쉐이더에서 다음과 같은 작업을 수행 할 수 있어야합니다 (의사 코드, I 실제 GLSL을 더 잘 아는 사람들에게 맡길 것입니다.)

out vec4 fragment_color
vec4 final_color
final_color = flat_color
If this fragment is in shadow
    final_color = shadow_color
If this fragment is an edge
    final_color = edge_color
If this fragment is a highlight
    final_color = highlight_color
fragment_color = final_color

if이 방법으로 s 를 사용 하면 여러 패스와 같은 것을 얻을 수 있습니다. 말이 돼?

편집 : 또한 SO에 대한이 질문이 오해를 없애는 데 도움 이 되기를 바랍니다 .


2
GLSL은 활성화되지 않은 경우에도 모든 분기가 if 분기의 모든 명령문을 실행한다는 점에 유의해야합니다. 분명히 모든 것을 계산하고 모든 색상을 합산하지만 값을 1.0 또는 0.0으로 곱하여 활성화 또는 비활성화하는 것이 더 빠릅니다.
— David C. Bishop

1
@ DavidC.Bishop : 사실이 아닙니다. 적어도 사실이 보장 되지는 않습니다 . 컴파일러는 실제 브랜치가 더 빠른지 또는 "모든 것을 계산하고 나중에 정렬"하는 방법이 더 빠른지 결정합니다.
— Nicol Bolas

1
또한 @ DavidC.Bishop이 언급 한 동작은 셰이더와 GPU에만 국한되지 않습니다. 테스트 된 값을 아직 사용할 수없는 경우 일반 프로그램을 실행하는 최신 CPU는 분기 중 하나 이상을 추측 적으로 실행합니다. 잘못된 것으로 판명되면 롤백하고 다시 실행합니다. 결과적으로 평균 속도가 크게 향상됩니다.
— ipeet
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.