※ 제 개인 공부이므로 풀 소스 코드는 작성하지 않습니다. ※
※ 생략 되어 있는 부분이 많습니다. ※
struct VtxD
{
D3DXVECTOR3 p;
DWORD d;
VtxD() : p(0, 0, 0), d(0xFFFFFFFF) {}
VtxD(FLOAT X, FLOAT Y, FLOAT Z, DWORD D) : p(X, Y, Z), d(D) {}
enum { FVF = (D3DFVF_XYZ | D3DFVF_DIFFUSE), };
};
LPDIRECT3DVERTEXSHADER9 m_pVs;
LPDIRECT3DVERTEXDECLARATION9 m_pFVF;
LPD3DXCONSTANTTABLE m_pTbl;
VtxD m_pVtx[4];
정점은 포지션과, 색상(Diffuse)를 갖고 잇고, 사각형을 만들꺼니까 정점 4개가 필요하다.
// Output Vertex Processing
struct SvsOut
{
float4 Pos : POSITION; // oPos
float4 Dif : COLOR0; // oD0
};
float4x4 m_mtWld; // World * View * Projection Matrix
float4x4 m_mtViwPrj; // View * Projection Matrix
SvsOut VtxPrc( float3 Pos: POSITION, float4 Dif: COLOR0 )
{
float4 P;
SvsOut Out = (SvsOut)0; // Initialized to 0
P = float4(Pos,1); // Expand into float4 and setting w=1
P = mul(P, m_mtWld); // Transform World
P = mul(P, m_mtViwPrj); // Transform View * Projection
Out.Pos = P; // Copy Output Position
Out.Dif = Dif; // Copy Output Diffuse
return Out;
}
SvsOut 정점 구조체를 이용하여 출력 시켜주고 있다. 이전까지와의 다른 점이라면 정점의 위치가 될 float4형 p 변수에 월드행렬(m_mtWld), 뷰*투영행렬(m_mtViwPrj)을 mul함수를 사용하여 곱해줌으로써 정점을 변환하고 있다.
입력으로 받는 정점의 포지션은 float3 형 이지만 파이프라인은 float4형을 사용하기 때문에 float4형으로 만들어주고 마지막 인수인 w에 1을 입력해 준다.
m_pVtx[0] = VtxD(-50, 0, 0, D3DXCOLOR(1, 0, 0, 1));
m_pVtx[1] = VtxD(50, 0, 0, D3DXCOLOR(0, 1, 0, 1));
m_pVtx[2] = VtxD(50, 80, 0, D3DXCOLOR(0, 0, 1, 1));
m_pVtx[3] = VtxD(-50, 80, 0, D3DXCOLOR(1, 0, 1, 1));
m_pdev->SetRenderState(D3DRS_LIGHTING, FALSE);
m_pdev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
D3DXMATRIX mtWld; // World Matrix
D3DXMATRIX mtViw; // View Matrix
D3DXMATRIX mtPrj; // Projection Matrix
float fAngle = D3DXToRadian(GetTickCount()*0.1f);
D3DXMatrixRotationY(&mtWld, fAngle);
mtWld._43 -= 1.f;
m_pdev->GetTransform(D3DTS_VIEW, &mtViw); // Device에서 뷰 행렬을 가져온다.
m_pdev->GetTransform(D3DTS_PROJECTION, &mtPrj); // Device에서 투영 행렬을 가져온다.
m_pdev->SetVertexShader(m_pVs);
m_pdev->SetVertexDeclaration(m_pFVF);
// 전역 변수 값 설정: 상수 테이블 사용
m_pTbl->SetMatrix(m_pdev, "m_mtWld", &mtWld); // World Matrix
m_pTbl->SetMatrix(m_pdev, "m_mtViwPrj", &(mtViw * mtPrj)); // View * Projection Matrix
m_pdev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_pVtx, sizeof(VtxD));
m_pdev->SetVertexShader(NULL);
m_pdev->SetVertexDeclaration(NULL);
D3DRS_CULLMODE 모드를 NONE으로 해주면 컬링을 하지 않아 앞면 뒷면 다 보이게 된다. 우린 사각형을 Y축을 기준으로 계속해서 돌릴꺼니까 양면이 보여야 되니까.
GetTransform() 를 이용해서 각각의 행렬을 가져오고, SetMatrix()을 이용하여 셰이더 파일의 m_mtWld와, m_mtViwprj에 접근하여 값을 설정해준다.
D3DXToRadian(GetTickCount()*0.1f)을 이용해서 움직일 각도를 계산하고 D3DXMatrixRotationY() 을 이용해서 월드행렬에 적용해줌으로써 계속해서 Y각도가 바뀌는 사각형이 랜더링 되는 것이다.
mtWld._43 -= 1.f; 이 부분은 딱히 쓰이는 부분은 없는거 같은데. 월드 행렬의 _43이라고 하면 z축을 나타내는것으로 z축에 -1만큼 움직여라 라고 보면 된다. 마지막으로 월드 행렬(m_mtWld)와, 뷰*투영 행렬(m_mtViwPrj)를 따로 사용할 필요없이 셋다 곱해서 하나의 행렬로 사용해도 된다.
여기서는 월드행렬에 계속해서 로테이션Y를 해주기 위해서 따로 사용한거 같다. 셰이더 파일에도 보면 그렇기 때문에 float4x4형을 2개 만들어 각각 월드, 뷰*투영 행렬로 사용하고 있는듯 하다. 뭐 결론은.. 특별히 처리할 내용이 없는 부분이라면 미리 행렬들을 곱해서 사용하면 된다는것.
'Shader' 카테고리의 다른 글
8. 텍스처를 입혀보자. (지구) (0) | 2017.02.06 |
---|---|
7. 알록달록 사각형을 돌려보자.(변환2) (0) | 2017.02.06 |
5. 알록달록 삼각형을 그려보자.(Semantic 시맨틱2) (0) | 2017.02.03 |
4. 보라색 삼각형을 그려보자.(Semantic 시맨틱) (0) | 2017.02.03 |
3. 청록색 삼각형을 그려보자(uniform, varing 키워드) (0) | 2017.02.02 |