C++ 구현


위 gif 가 작업물임


헬로월드 별찍기 printf 찍는 콘솔창 그거 맞음


내용 길고 수학 많이나오고 난해하니

짤만 보고 나가도 무방함


GPT 적극적으로 활용함 (써도 개빡셈)










위 영상은 앵간한 사람들은 다 한번쯤은 봤을 거임

막연히 나도 저런거 한번 만들어봐야겠다는 생각을 평소 가지고있었고,
이 작업물은 그 생각을 실행으로 옮긴 거임

그리고 디시는 그림 50개 제한있어서 본론 일부 사진으로 대체함






중간시연



일단 대략적인건 다 이야기 했고,


워낙 구현한게 많아 다 다룰 수는 없어서 생략된게 좀 있음

설명안한 것들은 어차피 그 정도는 아니라서 스킵해도 무방함


어차피 여기까지 하나하나 읽는 사람도 없을거 같고


아무튼 이야기한거 + 생략한거 모든걸 구현하고


그리고 발생하는 온갖 잡버그를 디버깅하고 수정하고 난 후의 첫 결과물은 다음과 같음






잘못 그려지긴 하지만

그래도 굴러는 간다는 점에서 의의가 있음









시행착오와 개선


씬 구성에는 directional light를 썼었음

태양광 같은거임





이론도 그렇고 구현도 그렇고 light 벡터는 버텍스에서 광원 쪽으로 향해야함

이부분 실수했었고 수정했음


이거 찾는데 무수한 간격의 시간이 소요되었음








많이 나아졌음

그런데 아직도 버그가 있음

일단 이건 차치하고










정육면체 그리면 원래 이렇게 그려짐


위에 그렸던 건 사실 y scale 압축시킨 직육면체였음


이 문제가 발생하는 이유는 console창 char 한칸 cell의 크기가 세로가 더 길기 때문임






콘솔창 셀의 세로가 대충 2배 기니 0.5 곱했음









일단 비율 문제는 해결했는데


아직도 뭔가 문제가 있음


수많은 노가다와 시간간격이 소요된 후,


이게 Z Fighting 문제임을 알아냈음


정육면체라서 버텍스의 Z 값이 같으니 Z buffer method가 제대로 작동을 안함


그래서...








Back Face Removal




일단 이론은

View Coordinate 에서, 

polygon의 법선벡터가 음수면 back face 이다 -> 컬링해라

인데


결론부터 말하면

잘 작동안함

아무튼 잘 안됨






Back Face Removal2



back face culling 다른버전임


보니깐 폴리곤 배열된걸 CCW 돌려서

버텍스의 위치만으로 면의 법선벡터를 구할 수 있음


이게 어떻게 가능하냐면 

애초에 모델 만들 때, 

폴리곤의 법선벡터가 모델의 외부로 향하도록 버텍스 순서를 맞춰서 전처리함 






Z 위치만 다른 두 삼각형을 가정해보자,

일반적으론, 저 두삼각형 외적 돌리면 같은 법선이 나와야하는데,

메쉬에 삼각형 집어넣을 때, 하나는 ABC 순서로 집어넣고

다른건 ACB 순서로 집어넣어서 외적돌렸을 때, 다른방향이 나오게 하는거임


그 후 평면위의 아무 한 점 잡아서 (보통 vertex 의 p0)

카메라까지의 방향벡터를 구하고 (to eye)

to eye 벡터랑 내적 돌려서 이게 양수이면 카메라에서 보임, 음수면 back face라 컬링 가능임




위 수식은 간단한 증명임

s(x) 는 삼각형을 포함하는 평면의 방정식

카메라의 위치는 (0, 0, 0) 이 정석이므로 0을 집어넣음





이건 평면위의 아무 점을 잡던간에 판별에 영향을 주지 않음을 보여주는 증명

e1 e2는 평면위의 평행하지 않은 두 벡터이고 이걸로 평면위의 어떠한 점이라도 표현 가능함

내적시켜보면 싹다 0으로 날라가서 부호가 항상 일정함을 보여줌


결론적으로, Back face culling 까지 적용하고 나면











꽤 잘 작동한다









Texture


이제 텍스쳐 만들어야함




텍스쳐 자체는 뭐 별거 없음

이미지 정보가 rgb데이터로 width height 이렇게 존재할텐데

그거 가중치 기반으로 정보 추출해오는거임


width 100, height 100 짜리 이미지에

예를들어 Sample(0.5, 0.5) 한다 가정해보자

그러면 pixel[50][50] 인덱스의 rgb 가져오는거임 (인덱스 디테일은 살짝 다르겠지만 대충 이런느낌이라는 뜻임)


뭐 CLAMP REPEAT NEAREAST LINEAR는 딱히 다룰 주제는 아닌 것 같고






대충 이런느낌으로 색깔에 곱해서 썼음


텍스쳐 매니저 만들기

패턴베이크 이미지등록

렌더링 파이프라인에 끼워넣기

수많은 시간간격이 소요된 버그들 수정 

등등의 많은 일이 있었지만

딱히 할만한 이야깃거리는 아니라서 스킵함


골때리는건 보정보간임







perspective correct


일단 문제는 다음과 같음


Vertex에는


position,

normal, 

color,

uv,


가 존재함


근데 파이프라인은

PVM * vertex 하고, 

vextex의 각 x y z 를 w 로 나눠서 ndc로 맞추는데


color랑 uv는 이런과정을 안거친다는 것이고,

이를 바라센트릭 보간 가중치를 그대로 갖다쓰면 왜곡이 발생함


그래서,


보정 보간을 해야하는데

증명 빡셈





이를 NDC 로 투영시키면

위 수식과 같이 나옴




color든 uv든, 

바라센트릭으로 레스터라이즈할때, 이 수식으로 구현해야함








구현은 위와 같음

u_over_w, r_over_w .. 

등등은 u/w , r/w 랑 같음

연산감소용으로 미리 전처리해서 구해두는 값



아무튼 최종적으로





체커텍스쳐 적용












벽돌 텍스쳐 적용









결론



이제 온갖 구현된걸 기반으로


대충 메인이랑 엔진 사이에 


인풋핸들러 카메라컨트롤러 월드메이커 같은 추상층 몇개 끼얹어서 공간 만들면 (난이도 : 쉬움)


아래 GIF 처럼 나옴






Further Work



방향성은 매우 많은 듯함



1. 멀티쓰레드, GPU 등의 병렬화 및 analysis 


2. 스타1, 메월 같은 2D 플랫폼에 그대로 이식해서 3D게임 만들기


3. 레이트레이싱


4. 이대로 DOOM 제작작


5. 코드 최적화


6. 각종 기법들 적용해보고 성능 analysis



등등 있는데 일단 한동안은 그대로 냅둘듯