SetLayerMaskZero -> 모든 레벨(레이어)을 다 찍는 것
SetLayerMask -> 원하는 레이어인덱스를 넣으면 비트값 체크해서 그린다.
해당 카메라에 랜더를 주는 이유 ?
카메라마다 월드상의 위치가 다르다 -> 그 카메라가 중심이 되어야 하기 때문에 뷰행렬&투영법이 다 다르다.
==>> 행렬 세팅하는 부분이 랜더하기 직전으로 옮겨야함..
투영행렬이나 뷰행렬 변환행렬이 이 카메라껄로 셋팅이 되어야하기 때문
셋팅해놓고 랜더링을 돌려야 물체들 입장에서는 자기 트랜스폼에서 월드행렬을 집어넣으면
뷰프로젝션(나를 찍는 카메라)으로 투영되고 이동변환을해서 최종적인 쉐이더 단계에서
해당카메라 시점기준으로 위치가 정해진다.
월드뷰프로젝션변환 계산을 미리 해두면 쉐이더에서 더 편하게 사용할 수 있다.
matWV -> 월드랑 뷰를 곱해놓는 것
matWVP -> 월드랑 뷰랑 프로젝션 곱해놓는 것
카메라 랜더링 전에 해야되는 것
-> 물체마다 서로 다른 도메인을 쓰고 있는 경우, 정리를 해서 랜더링 순서를 잡아주어야한다.
그래서 카메라쪽에 물체를 분류하는 작업을 만들어야 한다.
카메라안에 오브젝트 정렬함수를 만들고, 정렬해서 분류시킬 물체를 미리 담아둘 백터를 선언해둔다.
불투명한 물체 따로 분류
마스크 도메인 쓰는 애들 따로 분류
반투명한 쉐이더 쓰는 애들 따로 분류
==>> 벡터 3개 준비
오브젝트 정렬함수 만들기
물체 분류하는 함수에서
카메라는 레이어체크를 통해서 본인이 어떤 레이어를 그려야 하는지 알고 있다.
현재 레벨로 먼저 접근
모든 레이어를 순회해서 해당 레이어를 내가 그리기로 했는지 체크를 한다.
검출이 되면 레벨한테 해당 레이어를 가져온다.
레이어 안에는 오브젝트들이 들어있다.
게임오브젝트는 다양한 컴포넌트를 가지고 있고, 컴포넌트들 중에서는 랜더링 기능을 담당하는 컴포넌트들이 겹쳐져있다.
게임오브젝트는 랜더링 컴포넌트 중에 하나만 가질 수 있다.
랜더링 관련된 컴포넌트가 들어오면 게임오브젝트는 다시 모든 랜더링 기능을 가진 컴포넌트들은 랜더컴포넌트를 상속받아서 파생된다.
컴포넌트에 들어온 애들 중에 랜더링 기능가진애가 있으면 가리켜 놓는다. -> m_pRenderComponent
카메라한테 물체를 분류
카메라가 화면에 그릴 수 있는 랜더링 조건이 갖춰져야한다.
그리기로 했던 레이어가 있다면 해당 레이어가 소유하고 있는 모든 물체를 가져와서
1. 랜더 컴포넌트가 셋팅이 되어있는지
2. 매쉬나 재질같은 쉐이더 같은 것들이 정상적으로 셋팅이 되어 있는 물체인지 확인한다.
여기까지 ok 면,
3. 랜더컴포넌트의 재질의 쉐이더를 가져와서 쉐이더에 도메인을 확인한다.
OPQUE면 m_vecQpaque.push_back
MASK면 m_vecMask.push_back
TRANSPARENT면 m_vecTransparent.push_back
으로 분류를 해놓는다.
랜더매니저에서 카메라에 랜더링을 하라고 하면
카메라는 자기 기준에 따라서 뷰행렬과 프로젝트행렬 셋팅해두고
쉐이더 도메인에 따라서 물체를 카메라 기준으로 분류를 한다.
이 카메라가 본인이 찍기로 한 레이어가 있고, 그 레이어에 속해있는 애들 중에서
어떤 도메인 쉐이더를 쓰느냐에 따라 순차적으로 랜더링을 해 나간다.
hlsl에서 행렬은 기본적으로 열 우선이다. => 컬럼메이져
우리가 원하는 효과를 얻으려면 곱할 때
클로퍼가 뒤로가야하고 행렬이 앞에 와야한다.
mul에서 순서를 거꾸로 곱해주면 순서가 바뀐다.
열우선인 행이랑 백터4성분을 곱할때 멀에서 순서를 뒤집어주면 가능하다.
매트릭스값을 넘겼을 때, 행우선이라고 row_major 키워드를 붙인다.
기본 디폴트를 열 우선으로 하기 때문에 row_major 를 붙인다.
이걸 안하려면 보내기 직전에 전치해서 보내면 된다.
오브젝트 계층관계
3D에서 굉장히 중요하다.
변수명 앞에 전부 Relative 를 붙였다 -> 누군가로부터 상대적인개념, offset
월드에다 배치하고 싶은 값을 relative에 넣는다 -> 왜 월드로 안하고.. ?
게임 오브젝트끼리 부모자식관계를 설정할 것이다.
부모 자식 관계를 설정하면 좋은점 ?
좀 복잡한 오브젝트를 설계할 때..
ex) 함정 설계
하나의 게임 오브젝트가 함정으로서 역할을 하기가 쉽지 않다.
함정관련해서 랜더링 해야 될 것들이 많기 때문이다.
칼날부분만 랜더링하는 부분이 있을 것이고,
사슬같은 부분은 랜더링 하는 것도 있고
조인트 부분을 랜더링 하는 부분도 있을 것이다.
게임오브젝트 여러개를 연결해서 하나의 거대한 단위를 구성한다고 했을 때, 내가 만약 위쪽에 있는 사실에 매달리는 축이되는 것을 이동하면 나머지 사슬과 칼날은 그자리에 가만히 있게 된다.
하지만 조인트를 이동시킬때 나머지 부분도 다 따라와야한다..
조인트는 부모이기 때문이다~
그래서 조인트를 잡아 끌면 다같이 이동을 하는 것이다
그래서 게임오브젝트끼리 부모관계가 형성이 된다.
결국 월드이 배치되는 것은 조인트이고, 조인트의 relative pos가 곧 월드 pos이다.
최상위 부모이기 때문에 이렇게 인식될 수 있는 것이다.
사실오브젝트는 .조인트가 아무리 움직여도 0, 0, 0 이다..
근데 부모가 움직이면 따라다니는 이유는?
0, 0, 0 이라는 기준 자체가 부모로부터 상대적인 좌표로 바뀌는 것이기 때문이다.
누군가의 자식으로 들어가버리는 순간 그때부터 그 오브젝트들의 포지션 정보는 상대좌표가 되는 것이다.
내 위로 부모가 없는 오브젝트는 그 상대의 개념이 월드가 되는 것이라 월드로부터의 상대적인 위치가 되는 것이다.
부모가 있다면 부모가 나의 기준이 되고 부모의 좌표가 나의 원점이 되는것이고, 거기로부터 상대적인 좌표가 되는 것이다.
즉, 월드좌표가 아닌 것이다..
월드좌표를 계산하려면 부모좌표에서부터 상대적인 위치를 누적해서 곱해서 계산을 해와야한다.
즉, 부모가 있는 오브젝트들의 relative pos 는 월드 pos가 아니다.
부모로부터의 상대적인 pos이다.(크기랑 회전도)
* 행렬을 곱하는 순서 중요
자식의 행렬 * 부모행렬 ==> 부모를 먼저 곱하면 안된다.
why?
자식의 좌표가 (100, 0 0) 이라 했을 때, 부모가 위치 이동을 하면
거기서부터 우측으로 100 이동한 것이 자식이다.
즉, 부모가 이동을 하면 자식의 최종 월드는 계속 바뀌는 것이다.
자식의 최종 월드행렬 안에는 부모의 이동행렬까지 다 들어가 있어야 된다는 것이다.
그래야 월드상에서 자식의 최종 위치를 알 수가 있다.
자식의 이동행렬 부터 생각.
자식을 먼저 이동시키면 오른쪽으로 100만큼 이동..
그리고 부모의 이동량을 누적하면 결국엔 똑같다.
그래서 사실 자식을 먼저 곱하든 부모를 먼저 곱하든 이동 관련에선 상관없다.
하지만, 크기와 회전이 문제이다.
자식입장에서는 회전을 했을 때 자기자리에서 돌아야한다 (자전)
본인의 상대적인 회전은 자기 자리에서 자전을 해야한다.
부모를 먼저 가버리면 이동이 먼저 누적됐기 때문에
제자리에서 도는게 아니라 엉뚱한데서 돌고, 우측으로 100을 가니까 이상한 곳에서 쳐다보게 된다.
게임오브젝트들은 레이어를 아무렇게나 다 가리킬 수 없다.
부모 자식 관계가 꼬일 수 있기 때문에 호출 순서가 중요하기 때문이다
최상위 부모가 아닌 자식 오브젝트는 아무리 해당 레이어 소속이어도 레이어가 직접적으로 가리키지 않게 한다.
최상위 부모 오브젝트만 레이어가 직접적으로 가리키게 한다.
레이어 클래스의 tick 과 finaltick도 최상위 부모 오브젝트만 사용이 가능하다.
자식 오브젝트는 부모의 레이어에 포함이 되어 있기 때문에
게임 오브젝트 tick에서 부모 오브젝트의 연산이 끝나고 나면, (계층구조이기 때문에)
자식 오브젝트를 호출해서 업데이트하게 한다.
부모가 자식 랜더 호출해주지 않는다.
랜더는 카메라에서 물체별로 다 분류처리를 해서
물체별로 시점을 분류해서 개별적으로 호출 들어갈 것이다.