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.