셰이더 21.11.30

김주현·2021년 11월 30일

셰이더

목록 보기
5/18

조명 이어서

빛에 재질을 추가해주자.

g_vLightDiffuse

디퓨즈를 추가하는게 의미가 있을까? 이미 텍스처가 색깔을 표현해주고있다.

픽셀마다 무슨 색을 반사하면되는지를 정의해놓은게 텍스처다.

Out.vColor이 지형의 디퓨즈머테리얼이라고 할수있다.

결국 vColor에 이 디퓨즈값에 Shade를 곱해준것밖에안된다

(g_vLightDiffuse vDiffuse) shade 하는게 정상적인 방법이다.

Terrain에서 LightDiffuse에 값은 던져주자.

빛의 흰색이였기때문에 기존과같이 지형의 모든색을 반사한다.

만약 빨간색 빛을 비추면 빨간색으로 보인다.

재질

지형의 셰이더에 지형의 재일을 추가하자.
g_vMtrlAmbient = vector(0.3f ...)

다음 Out.vColor에 빛의 앰비언트와 머테리얼의 엠비언트를 곱해서 더해주자.

너무 하얗게 표현된다.

이값은 명암에 더해주자 그런데 이러면 1보다 큰 명암이 생길수있다. saturate로 1보다 크지않게 해주자.

보면 빛이 안받는 부분이 검은색으로 표현되었으나 이제는 어느정도 색이 표현된다.

스펙큘러

정반사광원에 의한 색상 -> 주로 하이라이트 조명을표현하기위해 사용

빛의 반사벡터와 카메라의 시선벡터를 내적해서 각도를 구하자.

카메라의 위치벡터가 필요하다. v_cameraPosition

vs_out과 ps_in에 스펙큘러 추가해주자.

스펙큘러를 계산해보자.

reflect()라는 함수가있다 두벡터를 넣어주면 된다

좌표계를 월드로 맞춰주고 정규화해서 넣어주자

빛의 반사벡터 vReflect를 구하자

카메라의 시선벡터 vCamLook을 구하자

현재 vPosition는 로컬이다 월드인 Out.vWorldPos로 해주자.

이렇게 스펙큘러를 구했다

아직 스펙큘러의 색상을 정하지 못했다.
빛의 스펙큘러와 재질의 스펙큘러 정의해주자.

빛의 스펙큘러와 재질의스펙큘러를 곱해서 스펙큘러의 색상을 정하고 구한 스펙큘러를 곱해서 이를 Out.vColor에 더해주자.

터레인에서 스펙큘러 던져주고 파이프라인을통해 뷰행렬을가져와서 카메라의 포지션을 던져주자.

현재 스펙큘러의 범위가 너무 넓다 pow로 30승정도 해주자.

현재로는 다중광원을 표현하기 힘들다
현재 세이더 전처리 셰이더라 부른다 (그리기 전에 처리함)

나중에 후처리셰이더를 학습한다 먼저 그리고 빛연산을 한다.
(이는 다중점광원을 편하게 구현할수있다)

메쉬

애니메이션의 유무에따라 메쉬를 나눌수있다.

부모로 메쉬 컴포넌트를 선언하자

우선 엔진에 메쉬컴포넌트를 추가해보자.

애니메이션이 없는 메쉬 - CMesh_Static;

애니메이션이 있는 메쉬 - CMesh_Dynamic;

메쉬 클래스

외부로 내보낼것이다 ENGINE_DLL 추가
CComponent를 상속받는다.
생성자의 인자로 장치를 받는다.

Mesh_static

외부 파일에 포함되어있는 정점들이다 파일을 읽어서 그릴수있는 상태를 만들어줄것이다.

CMesh를 상속받는다.

경로를 나눠서 받자 경로와 이름으로
Create()함수
(장치,경로,이름)

클라이언트 bin - 리소스에 메쉬 폴더로 메쉬를 보관하자.

x 파일안에 메쉬에 대한 정보를 담겨있다.

tga는 사용되는 이미지다.

x파일안에 텍스처의 파일네임이 정의되어있다.
이름은 받아올수있지만 경로는 필요하다.
이를위해 경로와 이름을 따로 받았다

애니메이션이 없는 메쉬를 로드하는건 상대적으로 쉽다.

네컨프로토에서 메쉬파일을 읽어와야한다.

메쉬파일 로드

szFullPath를 선언하고

path를 복사하고 Name을 붙인다

D3DXLoadMeshFromX()로 메쉬를 로드할수있다.

함수의 아웃플 저장하기위한 멤버변수를 선언한다.

LPD3DXBUFFER->GetBufferPointer 버퍼의 가장 앞주소를 가져온다.

m_pAdjacency

LPD3DXBUFFER m_pAdjacency : 인접 폴리곤이덱스에대한 정보

먼저 0번째 폴리곤의 이웃 3개의 인덱스를 저장한다.
다음 1,2...쭉쭉쭉 인덱스에 저장한다.

메쉬정점에 노말이없을경우 계산하기위해 사용될수있음.
법선벡터를 구하는 함수가있고 함수가 인자로 이 버퍼를 요구한다.

m_pMaterials

LPD3DXBUFFER m_pMaterials : 메쉬정보
만약 머테리얼의 GetBufferPointer를 호출하면 void*를 리턴한다.
이를 캐스팅하기위해선 어떤 타입으로 정의되어있는지를 알아야한다.
(m_pAdjacency는 정수형 m_pMaterials는 D3DXMATERIAL)
D3DXMATERIAL을 배열로 담아주는것이다.(이는 재질을 의미한다.)
이메쉬를 로드했을때 파일이름을 뱉어준다(어떤 재질인지를 알기위해).
디퓨즈맵이 여러개이다. 메쉬를 파츠별로 나눠놨다.
A파트는 A디퓨즈맵을 B파트는 B디퓨즈맵을 사용한다.
디퓨즈맵이여러개다 -> 디퓨트마테리얼이여러개다 -> 재질이 여러개다.

사람메쉬를 로드하면 첫번째 메쉬가 몸 전체를 표현하는 경우가 많다.

어쩃든 중요한건 머테리얼을 여러개 가질수있다는것이다.

_ulong m_iNumMaterials 로 몇개의 머테리얼을 가지는지를 저장한다.

m_pMesh

메쉬 컴객체가 존재한다 이곳에 매쉬를 저장한다.

텍스처이름정보는 m_pMaterials에 담긴다.

인자 :
(경로,D3DMESG_MANAGED(메모리관리방법)(VLAM이 꽉차면 시스템메모리로 옮긴다.) 장치객체, adjency,material,material수,메쉬)

점 -폴리곤 -서브셋 -메쉬

서브셋이란? : 폴리곤들의 집합, 재질 정보가 같은 폴리곤들끼리 모아준다.

하나의 폴리곤을그릴때마다 재질을 구해서 그리면 너무많은 연산이 들어간다.

재질을 한번세팅하고 같은재질을쓰는 폴리곤을 쭉그린다.

Render()

메쉬의 DrawSubset()함수가있다. :인자로 인덱스를 받는다. 몇번째 인덱스를 그릴꺼야?

아까 받은 머테리얼의 갯수 m_iNumMaterials가 서브셋의 갯수를 의미한다.

복제할때 Mesh에대한 복사가필요하다 (참조수 증가해주자)

컴포넌트 매니저에 메쉬를 include해주자.

로더에서 메쉬_스태틱의 컴포넌트 원본을 추가해주자.

플레이어로 가서 버퍼대신에 메쉬컴포넌트를 쓰자.
(이제 텍스처도 필요없다 메쉬에서 로드한다.)

애드컴포넌트에서 메쉬 컴포넌트를 추가해주자.

0개의 댓글