Graphics Programming

멍청한 리팩토링 본문

Season 1/OpenGL

멍청한 리팩토링

minseoklee 2017. 4. 6. 22:48


디퍼드 셰이딩을 구현하려고 오랜만에 프로젝트를 열었다. 그런데 렌더러 설계가 내가 왜 이렇게 했는지 도저히 이해할 수 없는 상태다. 왜 재질이 셰이더 프로그램을 생성하고, 두 물체가 같은 재질을 공유하는데 속성 설정이 다르면 매 프레임마다 셰이더를 다시 컴파일하는 거지...


그래서 디퍼드 셰이딩은 건드리지도 못하고 기존의 포워드 셰이딩 코드를 장기간 리팩토링하고 있다. 리팩토링하면 설계만 바뀌어야지 동작이 깨지면 안되는데 깨져버렸다. 방향광에 의한 섀도우 매핑을 리팩토링하다 렌더러가 그만...



크...크리링이 죽었어.jpg - 고급유머



원본 코드와 대조하며 하루를 꼬박 보냈지만 소용이 없었다. GLintercept를 써가며 모든 오류 메시지를 해결했지만 섀도우 매핑은 살아나지 않았다.


섀도우 매핑을 구현하려면 렌더 패스가 2단계 필요하다.


1. light space에서 보는 깊이 값을 별도의 텍스처에 저장한다.

2. 물체를 그릴 때 물체에 포함되는 점과 light space에서 본 그 점의 깊이를 비교한다.


깊이 값 텍스처를 화면에 그려봤지만 멀쩡했다. 2단계 코드가 틀렸다는 건데, 이것도 기존 코드와 완전히 똑같았다.


그렇게 이틀을 쓰레기통에 버리고 결국 원인을 찾았다. 텍스처에 깊이 값을 그릴 때, 그림자 판별할 때 각각 물체의 변환 행렬이 필요한데, 전자에서는 올바른 행렬을 넘기고 후자에서는 엉뚱한 물체의 변환 행렬을 넘기고 있었다.



변환 행렬의 x축 bias가 너무 커서 혹시 저기 오른쪽에 동떨어진 물체의 행렬인가 싶었고, 확인해보니 맞았다.


리팩토링하면서 최적화한답시고 1단계에서 projection * view * model을 캐싱해놨는데 모델이 여러 개니까 결국 마지막에 그려진 와이어프레임 상자의 model 행렬로 덮어씌워진 것. 2단계에서 이걸 가져다 썼으니 당연히 변환된 값이 틀릴 수 밖에 없다.




오랜만에 이 글을 읽어보니 이 때는 디버깅을 정말 힘들게 했다. 지금 디버깅한다면 렌더독으로 캡쳐해서 유니폼 버퍼에 업로드되는 행렬과 섀도우 맵의 업데이트 과정을 살펴보고 버그를 바로 잡아냈을 것이다.

Comments