셰이더와 GPU 파이프라인 · 정점 셰이더와 프래그먼트 셰이더 · 실습
셰이더 두 개와 그 사이
목표
정점 셰이더와 프래그먼트 셰이더를 파이썬 함수로 쓰고, 그 사이에 래스터라이저를 놓아 실제로 그림을 뽑습니다. 이 실습이 끝나면 GLSL 코드를 읽을 때 각 값이 어디서 와서 어디로 가는지 보이게 됩니다.
왜 중요한가
셰이더는 파이프라인 아무 데나 열어 준 것이 아닙니다. 구조는 그대로 두고 정점 단계와 프래그먼트 단계만 열었습니다. 그래야 나머지(래스터라이즈, 깊이 판정, 혼합)를 하드웨어가 계속 병렬로 처리할 수 있습니다.
그 제약이 셰이더의 규칙을 만듭니다. 정점 셰이더는 정점을 만들거나 없앨 수 없고, 프래그먼트 셰이더는 이웃 픽셀의 결과를 볼 수 없습니다. 대신 두 단계 사이의 통로가 명확합니다 — 정점 셰이더가 varying 으로 내보내면 래스터라이저가 무게중심 좌표로 섞어 프래그먼트 셰이더에 넘겨 줍니다. 이 구조를 손으로 한 번 만들어 보면 GPU 프로그래밍의 제약이 왜 그 모양인지 이해됩니다.
단계
1. /root/stages 에 도구 상자를 놓습니다.
2. /root/stages/vs.py — 정점 셰이더.
3. /root/stages/varying.py — 값 보간.
4. /root/stages/fs.py 와 pipeline.py — 프래그먼트 셰이더와 out/uv.png.
5. /root/stages/out/u1.png, u2.png, u3.png — 유니폼만 바꾸기.
6. /root/stages/out/discard.png — 프래그먼트 버리기.
7. /root/stages/out/final.png 와 out/07-counts.txt — 호출 횟수.
참고
- 그림은
nohup python3 -m http.server 8080 -d /root/stages/out &로 띄우고 웹 미리보기 에서http://localhost:8080/을 엽니다. - 한 장을 그리는 데 몇 초 걸립니다. 프래그먼트 셰이더가 2만 번 넘게 불리기 때문인데, 그 느림 자체가 이 실습에서 볼 것 중 하나입니다.
- 흔한 실수 하나:
varyings를 보간하지 않고 첫 정점의 값을 그대로 쓰는 것입니다. 그러면 삼각형이 한 가지 색으로 칠해집니다. - 흔한 실수 둘: 화면 좌표로 옮길 때 y 뒤집기를 빠뜨리는 것입니다. 그림이 위아래로 뒤집혀 나옵니다.
단계 7개
- 그리기 도구 상자를 놓는다
- 정점 셰이더
- 래스터라이저가 값을 섞는다
- 프래그먼트 셰이더와 첫 그림
- 유니폼만 바꾼다
- 프래그먼트를 버린다
- 어느 단계가 몇 번 불렸나