1. 오늘 배운점/느낀점
2. 엔진 구현 사항(주말 보충 수업 내용으로 대체)
- 전체적인 그래픽스 이론들을 공부해보는 수업.
- DirectX란 뭘까. 왜 쓸까. opengl이나 vulcan도 있는데 왜 쓰지?
그리고 DirectX12도 있는데, 왜 11을 쓸까.
opengl은 모바일(안드로이드, IOS) 환경, vulcan은 그 후손.
DirectX는 PC(윈도우) 환경 전용.
- GPU는 코어수가 엄청나게 많음. cpu 대비 처리량이 엄청나게 많음.
따라서 GPU를 사용할 수 있는 API가 필요함. 그것이 DirectX
- 12를 하려면, 11을 경험해야함.
11보다 더 로우 레벨의 함수를 제공하는게 12임.
11에서 쓰던 OMSet-() 함수 한줄이 12에선 5~6줄을 써야함. 훨씬 더 많은 일을 해야함.
그만큼 더 섬세한 작업이 가능함. 그래서 초보자는 11을 먼저 경험 후 12를 쓰는게 올바른 방법.
- 그럼 Dx11을 써서 GPU에 작업을 내릴 예정임.
대량의 데이터를
유튜브에 BRD 3D GPU는 어떻게 작동할까 보면 좋음.
- 게임 랜더링이란, 화면 속 엄청난 픽셀에 하나하나 색상을 넣어주는 것.
픽셀 셰이더는 픽셀 하나하나마다 실행되는 셰이더. 이 친구가 각 픽셀의 색상정보를 결정함.
대량의 픽셀을 직렬로 처리하면 엄청나게 느려짐. 따라서 GPU를 통해서 대량의 픽셀을 병렬처리가 필요해짐.
그렇기 때문에 GPU의 코어수가 엄청나게 많은 것. 그에 비해 cpu는 코어수가 비교적 엄청 적어서, 비효율적.
- GPU를 그래픽 랜더링 목적에만 쓰는게 아니고, ai에도 쓰임. 즉, gpu를 연산목적으로 쓰는 것. 이때는 GPGPU라고 함.
이를 General Perpose GPU라고 부름. Compute Shader도 마찬가지의 개념. 파티클 할 때 사용하게 될 수도.
이를 하나하나 오브젝트로 하는게 아니라, 이동 속도, 크기변화, 색상 등등 빠르게 계산하는게 ComputeShader를 씀.
하나하나 입자를 하나의 코어가 병렬적으로 업데이트함. 또 지형 랜더링에서도 컴퓨트 셰이더를 씀.
이때 파티클 하나를 GPU 코어 하나가 담당하게 됨. 다만,DX11에서 컴퓨트 셰이더는 그렇게 효율이 좋진않음.
그래서 엔비디아 Cuda를 씀. 다만 우리는 쿠다 쓰면 안됨. 엔비디아 글카만 되기때문.
- 물체 하나가 그려질 때, 랜더링 파이프라인
IA: 정점 데이터와 정점의 레이아웃 정보를 받는 단계.
레이아웃은 정점의 형태(정점 하나 속 좌표, 컬러, 노말(라이팅처리)벡터, 탄젠벡터, ...)를 설명해주고 있음.
레이아웃 없이 모든 정점을 VB에 다 올려버리면, 어디서부터 어디까지가 좌표인지, 컬러인지, ... 모름.
그래서 결국 이게 VS에서 이를 뽀아서 쓸 수 있게 하는 것. ex. TEXCOORD 시멘틱이 붙어있는 정점 정보를
레이아웃을 통해 가져오고, 이를 VS 인자에 담아주겠다 라는게 가능해짐.
또한 레이아웃이 있기 때문에, VS IN 구조체에는 꼭 다 가져올 필요도, 순서를 지킬 필요도 없어짐. 이는 시멘틱 덕분.
VS: ia 단계로부터 받은 정보를 가지고, 정점 버퍼에 있는 데이터들을 최종적으로 NDC 좌표계(투영 좌표계)로 옮겨야함.
Nomalized Device Coord.(-1 ~ 1) (3d로 옴긴다?)
유저가 설정한 게임 해상도는 다르기 때문에 NDC 좌표계가 필요해짐.
PS에서 각 픽셀별로 호출되야하기 때문에, 픽셀이 선별되어야 함.
그래서 VS는 ia단꼐에서 받은 정점 하나를 NDC에 하나하나 각 정점 픽셀을 선별함.
그리고 NDC에서 PS를 위해서 해당 면의 모든 픽셀을 선별함. 이는 레스터라이저에서 함.
즉 각 정점의 보간도 레스터라이저에서하고, ndc에서 삐져나간 정점은 제외하면서 ndc에 해당하는 픽셀만 가려내줌.
이를 클리핑 처리.
물론 VS로만 NDC로 보내는 건 아님, hull/domain/geo 셰이더(테셀레이션)도 있음.
이 셋의 특징은 파이프라인 중간에 정점을 생성 시키려고 하는 셰이더임.ex. 지형에 가까워질수록 정점이 늘고 멀어지 면 줄어듬.
RS: VS에서 NDC에다가 각 정점을 찍어두었음. 그럼 이상태에서 ps에서 쓰일 각 픽셀을 선별해냄.
이는 해상도에 따라서 그 갯수가 달라짐. 그리고 그 각 픽셀은 정점에 따라 보간되어있음.
OM: 최종적으로 랜더타겟에 찍기 전에 두 가지를 테스트함. 뎁스 & 블랜드
즉, 깊이 테스트(더 가까운 깊이(Less)의 픽셀이 보임)를 시작함.
또 그게 바로 보이는 건 아님. 알파 블랜딩을 한다면, 도착점에 이전 픽셀들과의 색상 블랜드가 이뤄짐.
순수 로컬 스페이스 상에서의 Rect의 좌표는 [-0.5, 0.5]
그럼 NDC에는 화면의 절반만큼 찍히게됨.
동차 좌표계: w가 1인 좌표계.
벡터에서는 0이면 방향벡터(x, y, z가 벡터성분이라는 의미), 1이면 정점(x, y, z가 좌표성분이라는 의미)
즉, 정점의 이동은 정점 * 방향벡터의 개념.
만약 방향벡터의 마지막을 1로 둬버리면, 방향벡터도 이동되면서 이상한 방향을 가르키게 됨.
따라서 방향 벡터는 회전만 영향을 받게됨.
투영에서는 w가 1의 의미.
로컬 스페이스의 필요성(모델 스페이스)
뭐하는 곳이냐. 프로그래머와 상관이없음. 아트팀과 관련있음. 마야 3dmax
즉, 모델러가 물체 모델을 디자인하는 곳. 이건 무리가 하기 힘듦.
다만, 사각형, 구, 육면체 등은 엔진에서 가볍게 코드로 만들수 있기 때문에 프로그래머가 가능함.
다만 이때 물체는 로컬 스페이스의 원점을 기준으로 작업됨. 그래야 월드 스페이스에 배치할 때
보편적인 사람들에 의해 보기 편하게 배치됨. 원점 기준이 아니라면, 월드에도 이상한 곳, 이상한 크기로 이동됨.
이때 로컬 스페이스의 정점이 중요한 이유는, 리소스이기 때문.
똑같은 물체(리소스)가 월드 상에 많이 배치되어 있음. 즉, 이들은 로컬 스페이스에 있는 똑같은 물체.
로컬 스페이스의 물체는 돌려쓰는 자원인 것. 이 자원의 좌표가 바뀐다면, 인게임의 모든것이 바뀌게됨.(ex. 피봇)
리소스는 하나이고, VS에서 셈플링을 통해 많이 복제해냄.
월드 스페이스
리소스를 월드 공간에 위치시킬 때, 각 개체에는 트랜스폼 정보가 있어서 이를 곱하면 월드 공간에 배치되게 됨.
뷰 스페이스
카메라는 원점에 위치한다고 기준을 잡음. 그리고 카메라는 z축 방향으로 바라보고 있음.
카메라도 월드 공간 어딘가에 있을거임. 그럼 그 카메라가 바라보는 대로 우리눈에 보여야함.
따라서 월드 스페이스
뷰 행렬의 4행은 카메라 x,y,z의 -x, -y, -z가 되어야함. 그래야 물체가 카메라 위치의 반대로 이동되기 때문.
또 카메라가 바라 보는 방향은 z 축이 되어야 함. 그래서물체에 z축 회전값을 곱해버림. 그럼 마치 카메라가 움직인 착시
회전 행렬을 구하려면 카메라 기준의 트랜스폼의 전치만 시키면 됨. 서로 직교하기때문.???
투영 스페이스
fov가 커지면, NDC는 어차피 -1 1 사이라서 물체가 더 작게 보이게됨.
FOV가 좁아지면 헤드샷 쏘기 쉬워짐. 그러나, 옆에 있어도 모르게됨.
힐러는 fov는 많은 걸 보기위해 크게잡음.
fov를 순간적으로 5도 10도 늘었다 줄어하면 일렁이는 효과가 나타남. 피해 입었을때, 대쉬 받았을때 시야각으로 가능.
메테오 떨어질때, 시야각 설정 + 카메라 쉐이킹만 해도 엄청남.
투영 행렬이 곱해졌다해도 NDC가 아님.
투영하기 직전 상태의 VIEW 공간 상의 좌표일 뿐.
뷰행렬에는 1이 있는데, 이걸 이용해서 투영을 이뤄냄.
근데 왜 1을 둬서할까? 임의의 정점의 얼마를 나눠야 투영이 이뤄지는지 모름.
즉, 뷰행렬의 원소로 해당 값을 둘 수가 없음.
그래서 이전의 뷰공간 Z값을 W에 저장되게끔하고 그걸 나눠서 투영하게 되는 것.
레스터라이저에서 W를 나눠주게 되면 그제서야 NDC가 됨.
레스터 라이저는 W를 안나누고 줘도 알아서 그게 최종 투영 좌표가 아니라는 걸 알고 알아서 나눠줌.
증명하는 방법은 VS가 받은 정점 값을 그대로 넘겨주되 W를 1로 두면 됨. 그럼 1로 레스터라이져가 나눠줌.
0.5로하면 1/2로 나눠주기 때문에 2배 커짐.
시야각에 따라서 Near가 1일 때의 사각형 크기가 달라짐.
근데 NDC는 -1 1이기 때문에, 그 사각형을 노말라이즈 해야만함. 그래서 뷰 행렬에 WIDTH/HEIGHT가 있는데
이 WIDTH와 HEIGHT가 Near 1의 사각형 가로 세로.
NDC 스페이스
컬모드가 무엇이냐에 따라서 카메라가 물체의 앞 혹은 뒤에서 보냐에 따라
물체가 보이고 안보이고 차이남. 정점 랜더링 순서에 따라 Culling 될 수 있기 때문.
앞에 있을 땐 시계방향이었는데, 뒤로 가면
2d에선 상관없는데 3d에선 얼굴이 있다고 쳐보자.
앞에서 얼굴 면이 나오고, 두개골안쪽의 뒤통수 부분은 Culling 되어야 함. 굳이 그릴필요가 없음.
그러나, 뒤에서 보면 또 얼굴면쪽 두개골 안은 계산할 필요가 없기 때문에 컬 모드가 중요해짐.
왜냐하면 얼굴면쪽 두개골 안의 정점은 반대 방향으로 정점 그려지기 때문에 컬모드에 의해 그려지지않음.
그래서 두개골안으로 들어가면ㅇ ㅏ무것도 안보이는 것. 만약 보인다면, 컬모드 논이라서 그냥 다 보이는것.
다만 이러면 최적화가 안됨.
3. 컨텐츠 구현 사항
3-1. 인벤토리 아이템별 수량 보이게끔 구현
3-2. 물약 드래그 드랍 장착 및 소비
- 마우스에 끌려다디는 반투명 액터 클래스 생성함.
인벤토리에서 아이템이 클릭될 시, 반투명 클래스에 그려짐.
- UI Collision 클래스가 필요할듯.
3-3. 퀵슬롯 구현
- 퀵슬롯에 각 칸마다 아이템을 놓으면 장착되게끔 하려함.
- 그러나, 너무 복잡함. 사용시..; 내일..다시하기로.
댓글