part 3 directx graphics core programming chap 9. shader programming using high level shader language...

40
Part 3 Part 3 DirectX Graphics Core DirectX Graphics Core Programming Programming Chap 9. Shader Programming using High Level Shader Lang Chap 9. Shader Programming using High Level Shader Lang uage uage DirectX9 DirectX9 에에에에 에에에에 에에에에 에에에에 HLSL HLSL 에 에에에에 에 에에에에 Per-Pixel Lighting Per-Pixel Lighting 에 에에 에 에에 Chapter 10. Using Advanced Shader Effect Chapter 10. Using Advanced Shader Effect Cube Environment Mapping Effect Cube Environment Mapping Effect Realtime Shadowing Effect Realtime Shadowing Effect Chapter 11. X File Chapter 11. X File X X 에에에 에에에 에에 에에에 에에 에에에 에에에 에에 에에에 에에 Chapter 12. Handling *.md3 Files Chapter 12. Handling *.md3 Files HLSL Shader HLSL Shader *.md3 *.md3 에에에 에에에 에에에 에에 에에 에에에 에에에 에에에 에에 에에

Upload: derick-bishop

Post on 14-Dec-2015

251 views

Category:

Documents


4 download

TRANSCRIPT

Page 1: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

Part 3Part 3DirectX Graphics Core ProgrammingDirectX Graphics Core Programming

Chap 9. Shader Programming using High Level Shader LanguageChap 9. Shader Programming using High Level Shader Language DirectX9DirectX9 에서부터 지원되는 에서부터 지원되는 HLSLHLSL 을 사용하여 을 사용하여 Per-Pixel LightingPer-Pixel Lighting 을 을

구현구현

Chapter 10. Using Advanced Shader EffectChapter 10. Using Advanced Shader Effect Cube Environment Mapping EffectCube Environment Mapping Effect

Realtime Shadowing EffectRealtime Shadowing Effect

Chapter 11. X FileChapter 11. X File X X 파일에 저장된 기하 정보의 이용파일에 저장된 기하 정보의 이용

Chapter 12. Handling *.md3 FilesChapter 12. Handling *.md3 Files HLSL ShaderHLSL Shader 와 와 *.md3 *.md3 파일을 이용한 캐릭터 엔진 구현파일을 이용한 캐릭터 엔진 구현

Page 2: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

Chapter 10Chapter 10Using Advanced Shader EffectUsing Advanced Shader Effect

숙명여자대학교 이과대학숙명여자대학교 이과대학

정보과학부 멀티미디어과학전공정보과학부 멀티미디어과학전공

조교수 이종우조교수 이종우

[email protected]@sookmyung.ac.kr

Page 3: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 3

• Cube MapCube Map 을 만들고 호출하는 방법을 만들고 호출하는 방법• 동적인 굴절과 반사 매핑 처리 방법동적인 굴절과 반사 매핑 처리 방법• 그림자와 그림자 부피 효과그림자와 그림자 부피 효과

ContentsContents

Page 4: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 4

Using Cube MapUsing Cube Map

• Reflection MappingReflection Mapping

– 빛이 반사된 표면을 처리하는 기법 빛이 반사된 표면을 처리하는 기법 반사 매핑 반사 매핑 , , 환경 매핑환경 매핑

• 반사 표면을 처리하는 기법반사 표면을 처리하는 기법– 방법 방법 11

• 빛의 물리적 성질에 대한 모델링을 한 후빛의 물리적 성질에 대한 모델링을 한 후

• 물체로부터 반사된 물체로부터 반사된 secondary lightsecondary light 에 대한 에 대한 ray tracingray tracing 을 실시을 실시

– 방법 방법 22

• 미리 만들어둔 주위 환경을 물체 표면에 입혀서미리 만들어둔 주위 환경을 물체 표면에 입혀서

• 반사가 일어난 것 같은 효과를 내는 기법반사가 일어난 것 같은 효과를 내는 기법

• 여기서 “여기서 “미리 만들어둔 주위 환경미리 만들어둔 주위 환경”을 ”을 큐브 환경 맵큐브 환경 맵 또는 또는 큐브 큐브 맵맵이라고 함이라고 함

Page 5: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 5

Using Cube Map Using Cube Map (( 계속계속 ))

• Cube Map Cube Map 생성하기생성하기– 큐브 맵을 입힐 물체가 들어갈 자리에 물체 대신 카메라를 놓고 큐브 맵을 입힐 물체가 들어갈 자리에 물체 대신 카메라를 놓고

여섯 방향으로 렌더링을 하거나 사진을 찍는다여섯 방향으로 렌더링을 하거나 사진을 찍는다 ..

– 이 이 66 장의 그림들은 시야각 장의 그림들은 시야각 9090 도의 정사각형 모양 도의 정사각형 모양 그래야 그래야 큐브에 입혔을 때 이음매가 잘 연결될 것임큐브에 입혔을 때 이음매가 잘 연결될 것임 !!

Page 6: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 6

Using Cube Map Using Cube Map (( 계속계속 ))

• Cube Map Cube Map 사용하기사용하기

– R = I – 2 * (I R = I – 2 * (I N) * N N) * N

Page 7: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 7

Example : CubeMapExample : CubeMap

• 환경 매핑을 이용하여 크롬 재질의 반짝거리는 주전자를 환경 매핑을 이용하여 크롬 재질의 반짝거리는 주전자를 그리는 예그리는 예– VSVS 가 각 정점에서의 시선 벡터와 반사 벡터를 계산가 각 정점에서의 시선 벡터와 반사 벡터를 계산

– VSVS 가 이를 가 이를 PSPS 에게 전달에게 전달

– PSPS 는 이를 이용해 큐브 맵에서 데이터를 꺼내와 결과물로 는 이를 이용해 큐브 맵에서 데이터를 꺼내와 결과물로 내보냄내보냄

Page 8: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 8

Example : CubeMap Example : CubeMap (( 계속계속 ))

• CD3DApplicationCD3DApplication 클래스클래스class CMyD3DApplication : public CD3DApplication{ D3DXMATRIXA16 m_matProject; D3DXMATRIXA16 m_matView; D3DXMATRIXA16 m_matWorld;

CD3DFont* m_pFont; CD3DMesh* m_pSkyBox;

ID3DXMesh* m_pD3DXMesh; // D3DX mesh to store teapot

LPD3DXEFFECT m_pEffect; // VS, PS 코드 컴파일 결과로 받을 효과 클래스 인스턴스 LPDIRECT3DCUBETEXTURE9 m_pCubeMap; // 환경 맵을 위한 텍스쳐 클래스 인스턴스 D3DXVECTOR4 m_vEyePos; // 시선 위치와 시선 벡터

protected: HRESULT RenderSceneIntoEnvMap(); HRESULT RenderScene(CONST D3DXMATRIXA16* pView, CONST D3DXMATRIXA16* pProject, BOOL bRenderTeapot ); …… HRESULT LoadXFile(TCHAR*);

public: LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); CMyD3DApplication();};

class CMyD3DApplication : public CD3DApplication{ D3DXMATRIXA16 m_matProject; D3DXMATRIXA16 m_matView; D3DXMATRIXA16 m_matWorld;

CD3DFont* m_pFont; CD3DMesh* m_pSkyBox;

ID3DXMesh* m_pD3DXMesh; // D3DX mesh to store teapot

LPD3DXEFFECT m_pEffect; // VS, PS 코드 컴파일 결과로 받을 효과 클래스 인스턴스 LPDIRECT3DCUBETEXTURE9 m_pCubeMap; // 환경 맵을 위한 텍스쳐 클래스 인스턴스 D3DXVECTOR4 m_vEyePos; // 시선 위치와 시선 벡터

protected: HRESULT RenderSceneIntoEnvMap(); HRESULT RenderScene(CONST D3DXMATRIXA16* pView, CONST D3DXMATRIXA16* pProject, BOOL bRenderTeapot ); …… HRESULT LoadXFile(TCHAR*);

public: LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); CMyD3DApplication();};

Page 9: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 9

Example : CubeMap Example : CubeMap (( 계속계속 ))

• 생성자 생성자 & & OneTimeSceneInit()OneTimeSceneInit()CMyD3DApplication::CMyD3DApplication(){ m_strWindowTitle = _T("CubeMap"); m_d3dEnumeration.AppUsesDepthBuffer = TRUE; m_dwCreationWidth = 800; // Width used to create window m_dwCreationHeight = 600; m_pFont = NULL; m_pD3DXMesh = NULL; m_pSkyBox = NULL; m_pEffect = NULL; m_pCubeMap = NULL;}

HRESULT CMyD3DApplication::OneTimeSceneInit(){ D3DXMatrixIdentity( &m_matWorld );

m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_pSkyBox = new CD3DMesh(); if(!m_pFont || !m_pSkyBox) return E_OUTOFMEMORY;

return S_OK;}

CMyD3DApplication::CMyD3DApplication(){ m_strWindowTitle = _T("CubeMap"); m_d3dEnumeration.AppUsesDepthBuffer = TRUE; m_dwCreationWidth = 800; // Width used to create window m_dwCreationHeight = 600; m_pFont = NULL; m_pD3DXMesh = NULL; m_pSkyBox = NULL; m_pEffect = NULL; m_pCubeMap = NULL;}

HRESULT CMyD3DApplication::OneTimeSceneInit(){ D3DXMatrixIdentity( &m_matWorld );

m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_pSkyBox = new CD3DMesh(); if(!m_pFont || !m_pSkyBox) return E_OUTOFMEMORY;

return S_OK;}

Page 10: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 10

Example : CubeMap Example : CubeMap (( 계속계속 ))

• InitDeviceObjects()InitDeviceObjects()

HRESULT CMyD3DApplication::InitDeviceObjects(){ TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("teapot.x")); LoadXFile(strFile); // m_pD3DXMesh for teapot model

if (FAILED(m_pSkyBox->Create(m_pd3dDevice, _T("lobby_skybox.x")))) return D3DAPPERR_MEDIANOTFOUND;

// Restore the device-dependent objects m_pFont->InitDeviceObjects( m_pd3dDevice );

HRESULT hr; if (FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, "hlsl.fx", NULL, NULL, D3DXSHADER_DEBUG, NULL, &m_pEffect, NULL))) return hr;

return S_OK;}

HRESULT CMyD3DApplication::InitDeviceObjects(){ TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("teapot.x")); LoadXFile(strFile); // m_pD3DXMesh for teapot model

if (FAILED(m_pSkyBox->Create(m_pd3dDevice, _T("lobby_skybox.x")))) return D3DAPPERR_MEDIANOTFOUND;

// Restore the device-dependent objects m_pFont->InitDeviceObjects( m_pd3dDevice );

HRESULT hr; if (FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, "hlsl.fx", NULL, NULL, D3DXSHADER_DEBUG, NULL, &m_pEffect, NULL))) return hr;

return S_OK;}

Page 11: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 11

Example : CubeMap Example : CubeMap (( 계속계속 ))

• RestoreDeviceObjects()RestoreDeviceObjects()

HRESULT CMyD3DApplication::RestoreDeviceObjects(){ m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice ); m_pFont->RestoreDeviceObjects(); if( m_pEffect != NULL ) m_pEffect->OnResetDevice();

//Do all the basic setup FLOAT fAspect = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH(&m_matProject, D3DX_PI/3, fAspect, 0.5f, 100.0f); D3DXMatrixIdentity(&m_matWorld);

TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("LobbyCube.dds")); if (FAILED(D3DXCreateCubeTextureFromFile(m_pd3dDevice, strFile, &m_pCubeMap)))

return S_FALSE;

return S_OK;}

HRESULT CMyD3DApplication::RestoreDeviceObjects(){ m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice ); m_pFont->RestoreDeviceObjects(); if( m_pEffect != NULL ) m_pEffect->OnResetDevice();

//Do all the basic setup FLOAT fAspect = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH(&m_matProject, D3DX_PI/3, fAspect, 0.5f, 100.0f); D3DXMatrixIdentity(&m_matWorld);

TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("LobbyCube.dds")); if (FAILED(D3DXCreateCubeTextureFromFile(m_pd3dDevice, strFile, &m_pCubeMap)))

return S_FALSE;

return S_OK;}

Page 12: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 12

Example : CubeMap Example : CubeMap (( 계속계속 ))

• FrameMove()FrameMove()

HRESULT CMyD3DApplication::FrameMove(){ // Set the eye position so that the eye orbits the object float Time = (float)GetTickCount() / 5000.0f; m_vEyePos = D3DXVECTOR4(3.0 * sin(Time), 0.0, 3.0 * cos(Time), 0.0f);

// Make sure that the room isn't spinning... D3DXMatrixIdentity(&m_matWorld);

// Set the view matrix based on the position above. D3DXMatrixLookAtLH(&m_matView, &(D3DXVECTOR3)m_vEyePos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

return S_OK;}

HRESULT CMyD3DApplication::FrameMove(){ // Set the eye position so that the eye orbits the object float Time = (float)GetTickCount() / 5000.0f; m_vEyePos = D3DXVECTOR4(3.0 * sin(Time), 0.0, 3.0 * cos(Time), 0.0f);

// Make sure that the room isn't spinning... D3DXMatrixIdentity(&m_matWorld);

// Set the view matrix based on the position above. D3DXMatrixLookAtLH(&m_matView, &(D3DXVECTOR3)m_vEyePos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

return S_OK;}

Page 13: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 13

Example : CubeMap Example : CubeMap (( 계속계속 ))• Render()Render() / / RenderScene()RenderScene()

HRESULT CMyD3DApplication::Render(){ // Begin the scene if (SUCCEEDED(m_pd3dDevice->BeginScene())) { // Render the scene, including the teapot RenderScene(&m_matView, &m_matProject, TRUE);

// Output statistics m_pFont->DrawText(2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats); m_pFont->DrawText(2,20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats);

// End the scene. m_pd3dDevice->EndScene(); }

return S_OK;}

HRESULT CMyD3DApplication::RenderScene(CONST D3DXMATRIXA16 *pView, CONST D3DXMATRIXA16 *pProject, BOOL bRenderTeapot){ // Render the Skybox D3DXMATRIXA16 matWorld; D3DXMatrixScaling( &matWorld, 10.0f, 10.0f, 10.0f );

HRESULT CMyD3DApplication::Render(){ // Begin the scene if (SUCCEEDED(m_pd3dDevice->BeginScene())) { // Render the scene, including the teapot RenderScene(&m_matView, &m_matProject, TRUE);

// Output statistics m_pFont->DrawText(2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats); m_pFont->DrawText(2,20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats);

// End the scene. m_pd3dDevice->EndScene(); }

return S_OK;}

HRESULT CMyD3DApplication::RenderScene(CONST D3DXMATRIXA16 *pView, CONST D3DXMATRIXA16 *pProject, BOOL bRenderTeapot){ // Render the Skybox D3DXMATRIXA16 matWorld; D3DXMatrixScaling( &matWorld, 10.0f, 10.0f, 10.0f );

Page 14: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 14

Example : CubeMap Example : CubeMap (( 계속계속 ))• Render()Render() / / RenderScene()RenderScene()(( 계속계속 ))

…… D3DXMATRIXA16 matView(*pView); matView._41 = matView._42 = matView._43 = 0.0f;

m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); m_pd3dDevice->SetTransform( D3DTS_PROJECTION, pProject );

// m_pd3dDevice->SetTexture(0, m_pCubeMap); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); if ((m_d3dCaps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) == D3DPTADDRESSCAPS_MIRROR ) { m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); }

// Always pass Z-test, so we can avoid clearing color and depth buffers m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS ); m_pSkyBox->Render( m_pd3dDevice ); m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );

…… D3DXMATRIXA16 matView(*pView); matView._41 = matView._42 = matView._43 = 0.0f;

m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); m_pd3dDevice->SetTransform( D3DTS_PROJECTION, pProject );

// m_pd3dDevice->SetTexture(0, m_pCubeMap); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); if ((m_d3dCaps.TextureAddressCaps & D3DPTADDRESSCAPS_MIRROR) == D3DPTADDRESSCAPS_MIRROR ) { m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR); m_pd3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR); }

// Always pass Z-test, so we can avoid clearing color and depth buffers m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS ); m_pSkyBox->Render( m_pd3dDevice ); m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );

Page 15: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 15

Example : CubeMap Example : CubeMap (( 계속계속 )) // Render the environment-mapped ShinyTeapot if (bRenderTeapot) { // Rotate the object (just because we can...) D3DXMatrixRotationY(&m_matWorld, (float)GetTickCount() / 1000.0f);

D3DXMATRIX mWorldViewProj; D3DXMatrixMultiply(&mWorldViewProj,&m_matWorld, pView); D3DXMatrixMultiply(&mWorldViewProj, &mWorldViewProj, pProject); m_pEffect->SetMatrix( "matWorldViewProj", &mWorldViewProj ); m_pEffect->SetMatrix( "matWorld", &m_matWorld); m_pEffect->SetMatrix( "matView", pView); m_pEffect->SetVector( "vecEye", &m_vEyePos);

UINT nPasses, iPass; HRESULT hr; if (m_pEffect != NULL) { hr = m_pEffect->SetTexture("CubeMap", m_pCubeMap); m_pEffect->Begin( &nPasses, 0 ); for( iPass = 0; iPass < nPasses; iPass ++ ) { m_pEffect->Pass( iPass ); m_pD3DXMesh->DrawSubset( 0 ); } m_pEffect->End(); } } return S_OK;}

// Render the environment-mapped ShinyTeapot if (bRenderTeapot) { // Rotate the object (just because we can...) D3DXMatrixRotationY(&m_matWorld, (float)GetTickCount() / 1000.0f);

D3DXMATRIX mWorldViewProj; D3DXMatrixMultiply(&mWorldViewProj,&m_matWorld, pView); D3DXMatrixMultiply(&mWorldViewProj, &mWorldViewProj, pProject); m_pEffect->SetMatrix( "matWorldViewProj", &mWorldViewProj ); m_pEffect->SetMatrix( "matWorld", &m_matWorld); m_pEffect->SetMatrix( "matView", pView); m_pEffect->SetVector( "vecEye", &m_vEyePos);

UINT nPasses, iPass; HRESULT hr; if (m_pEffect != NULL) { hr = m_pEffect->SetTexture("CubeMap", m_pCubeMap); m_pEffect->Begin( &nPasses, 0 ); for( iPass = 0; iPass < nPasses; iPass ++ ) { m_pEffect->Pass( iPass ); m_pD3DXMesh->DrawSubset( 0 ); } m_pEffect->End(); } } return S_OK;}

Page 16: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 16

Example : CubeMap Example : CubeMap (( 계속계속 ))

float4x4 matWorldViewProj;float4x4 matWorld;float4x4 matView;float4 vecEye;

texture CubeMap;samplerCUBE CubeMapSampler = sampler_state{ Texture = <CubeMap>; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap;};

struct VS_OUTPUT{ float4 Pos : POSITION; float3 Reflect: TEXCOORD4; };

float4x4 matWorldViewProj;float4x4 matWorld;float4x4 matView;float4 vecEye;

texture CubeMap;samplerCUBE CubeMapSampler = sampler_state{ Texture = <CubeMap>; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap;};

struct VS_OUTPUT{ float4 Pos : POSITION; float3 Reflect: TEXCOORD4; };

• PS()PS() / / VS()VS() 코드코드

Page 17: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 17

Example : CubeMap Example : CubeMap (( 계속계속 ))

VS_OUTPUT VS(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL){ VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = mul(Pos, matWorldViewProj); // transform Vertices float3 Norm = normalize(mul(Normal, matWorld)); // 법선 벡터 변환 // get a vector toward the camera/eye -> V // 시선 벡터 = 월드 공간에서의 정점 좌표 – 눈의 좌표 float3 PosWorld = normalize(mul(Pos, matWorld)); float3 Incident = normalize(PosWorld - vecEye); // Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect = normalize(reflect(Incident, Norm)); // Out.Reflect = normalize(Incident - 2 * Norm * dot(Incident, Norm));

return Out;}

VS_OUTPUT VS(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL){ VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = mul(Pos, matWorldViewProj); // transform Vertices float3 Norm = normalize(mul(Normal, matWorld)); // 법선 벡터 변환 // get a vector toward the camera/eye -> V // 시선 벡터 = 월드 공간에서의 정점 좌표 – 눈의 좌표 float3 PosWorld = normalize(mul(Pos, matWorld)); float3 Incident = normalize(PosWorld - vecEye); // Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect = normalize(reflect(Incident, Norm)); // Out.Reflect = normalize(Incident - 2 * Norm * dot(Incident, Norm));

return Out;}

• PS()PS() / / VS()VS() 코드코드

Page 18: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 18

Example : CubeMap Example : CubeMap (( 계속계속 ))

• PS()PS() / / VS()VS() 코드코드

float4 PS(float3 Ref : TEXCOORD4) : COLOR{

return texCUBE(CubeMapSampler, Ref); }

technique Tshader{ pass P0 { Sampler[2] = (CubeMapSampler); // compile shaders VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_1_4 PS(); }}

float4 PS(float3 Ref : TEXCOORD4) : COLOR{

return texCUBE(CubeMapSampler, Ref); }

technique Tshader{ pass P0 { Sampler[2] = (CubeMapSampler); // compile shaders VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_1_4 PS(); }}

Page 19: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 19

굴절과 반사가 있는 환경 매핑굴절과 반사가 있는 환경 매핑• 환경 매핑에 굴절 효과 넣기환경 매핑에 굴절 효과 넣기

– 굴절굴절 (Refraction)(Refraction)

• 서로 다른 매개체를 통과할 때 서로 다른 매개체를 통과할 때 빛이 꺾이는 현상빛이 꺾이는 현상

• 면이 출렁이면 꺾이는 각도가 면이 출렁이면 꺾이는 각도가 달라짐달라짐

– 방법방법• 반사 계산식과 법선 벡터의 반사 계산식과 법선 벡터의

길이를 조작하여 근사적으로 계산길이를 조작하여 근사적으로 계산• 법선 벡터의 길이를 일부러 법선 벡터의 길이를 일부러 11

보다 작은 값으로 줄여보다 작은 값으로 줄여 벡터의 벡터의 방향을 의도적으로 변경했음방향을 의도적으로 변경했음 !!

• 법선 벡터 길이 법선 벡터 길이 0 : 0 : 굴절 벡터가 굴절 벡터가 시선 벡터와 같아짐시선 벡터와 같아짐 ..

• 법선 벡터가 길어질수록 굴절 법선 벡터가 길어질수록 굴절 벡터는 경계면 쪽으로 꺾이게 됨벡터는 경계면 쪽으로 꺾이게 됨

Page 20: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 20

Example : CubeMap2 Example : CubeMap2

• VS()VS() / / PS()PS() 코드코드

float4x4 matWorldViewProj;float4x4 matWorld;float4x4 matView;float4 vecEye;

texture CubeMap;samplerCUBE CubeMapSampler = sampler_state{ Texture = <CubeMap>; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap;};

struct VS_OUTPUT{ float4 Pos : POSITION;

float3 Reflect: TEXCOORD4; float3 Reflect2: TEXCOORD5;

};

float4x4 matWorldViewProj;float4x4 matWorld;float4x4 matView;float4 vecEye;

texture CubeMap;samplerCUBE CubeMapSampler = sampler_state{ Texture = <CubeMap>; MinFilter = Linear; MagFilter = Linear; AddressU = Wrap; AddressV = Wrap;};

struct VS_OUTPUT{ float4 Pos : POSITION;

float3 Reflect: TEXCOORD4; float3 Reflect2: TEXCOORD5;

};

Page 21: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 21

Example : CubeMap2 Example : CubeMap2 (( 계속계속 ))

• VS()VS() / / PS()PS() 코드 코드 (( 계속계속 ))

VS_OUTPUT VS(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL){ VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = mul(Pos, matWorldViewProj); // transform Position float3 Norm = normalize(mul(Normal, matWorld)); // get a vector toward the camera/eye -> V float3 PosWorld = normalize(mul(Pos, matWorld)); float3 Incident = normalize(PosWorld - vecEye); // Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect = normalize(reflect(Incident, Norm));

float3 ShortNorm = mul(Norm, 0.4); // 굴절 벡터를 구하기 위해 법선 벡터 크기를 줄임

// Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect2 = normalize(reflect(Incident, ShortNorm));

return Out;}

VS_OUTPUT VS(float4 Pos : POSITION, float2 Tex : TEXCOORD, float3 Normal : NORMAL){ VS_OUTPUT Out = (VS_OUTPUT)0; Out.Pos = mul(Pos, matWorldViewProj); // transform Position float3 Norm = normalize(mul(Normal, matWorld)); // get a vector toward the camera/eye -> V float3 PosWorld = normalize(mul(Pos, matWorld)); float3 Incident = normalize(PosWorld - vecEye); // Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect = normalize(reflect(Incident, Norm));

float3 ShortNorm = mul(Norm, 0.4); // 굴절 벡터를 구하기 위해 법선 벡터 크기를 줄임

// Reflection Vector for cube map: R = I - 2*N * (I.N) Out.Reflect2 = normalize(reflect(Incident, ShortNorm));

return Out;}

Page 22: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 22

Example : CubeMap2 Example : CubeMap2 (( 계속계속 ))

• VS()VS() / / PS()PS() 코드 코드 (( 계속계속 ))

float4 PS(float3 Ref : TEXCOORD4, float3 Ref2 : TEXCOORD5) : COLOR{ float4 tex1 = texCUBE(CubeMapSampler, Ref); // 반사 벡터에서 한 번 float4 tex2 = texCUBE(CubeMapSampler, Ref2); // 굴절 벡터에서 한 번 return tex2 * 0.5 + tex1; // 굴절 성분의 밝기를 좀 줄임 !}

technique TShader{ pass P0 { Sampler[2] = (CubeMapSampler); // compile shaders VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_1_4 PS(); }}

float4 PS(float3 Ref : TEXCOORD4, float3 Ref2 : TEXCOORD5) : COLOR{ float4 tex1 = texCUBE(CubeMapSampler, Ref); // 반사 벡터에서 한 번 float4 tex2 = texCUBE(CubeMapSampler, Ref2); // 굴절 벡터에서 한 번 return tex2 * 0.5 + tex1; // 굴절 성분의 밝기를 좀 줄임 !}

technique TShader{ pass P0 { Sampler[2] = (CubeMapSampler); // compile shaders VertexShader = compile vs_1_1 VS(); PixelShader = compile ps_1_4 PS(); }}

Page 23: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 23

동적 굴절 동적 굴절 & & 동적 반사 환경 매핑동적 반사 환경 매핑• 동적 큐브 맵동적 큐브 맵

– 미리 만들어 놓은 큐브 맵이 아닌 매 미리 만들어 놓은 큐브 맵이 아닌 매 프레임마다 새로 큐브 맵을 생성함프레임마다 새로 큐브 맵을 생성함 ..

– 코딩 방법코딩 방법• 주전자 주위를 날아다니는 비행기를 주전자 주위를 날아다니는 비행기를

하나 띄우고 하나 띄우고 ,,

• 그 비행기의 모습이 주전자 표면에 그 비행기의 모습이 주전자 표면에 반사되게 하여 확인 함 반사되게 하여 확인 함 !!

– 큐브 맵 동적 생성 방법 큐브 맵 동적 생성 방법• 주전자는 제외한 채로 주전자는 제외한 채로• 환경과 비행기가 날아가는 장면을 환경과 비행기가 날아가는 장면을

생성생성• 생성된 화면 생성된 화면 66 개를 큐브 맵에 저장 개를 큐브 맵에 저장• 다음 번 다음 번 render()render() 시에 이 큐브 시에 이 큐브

맵을 사용 맵을 사용

Page 24: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 24

Example : CubeMap3Example : CubeMap3

• CD3DApplicationCD3DApplication 구조체구조체

class CMyD3DApplication : public CD3DApplication{ D3DXMATRIXA16 m_matProject; D3DXMATRIXA16 m_matView; D3DXMATRIXA16 m_matWorld; CD3DFont* m_pFont; CD3DMesh* m_pSkyBox; // 환경 매핑을 그리기 위한 프레임워크 CD3DMesh* m_pAirplane; // 동적 환경 매핑을 그리기 위한 프레임워크 D3DXMATRIXA16 m_matAirplane; // 비행기 변환을 위한 행렬 ID3DXMesh* m_pD3DXMesh; // 주전자를 그리기 위한 메쉬 구조체 LPD3DXEFFECT m_pEffect; // 셰이더 코드 컴파일 결과를 넘겨받을 효과 구조체 LPDIRECT3DCUBETEXTURE9 m_pCubeMap; ID3DXRenderToEnvMap* m_pRenderToEnvMap; // 동적 환경 매핑 저장 구조체 D3DXVECTOR4 m_vEyePos; // 시선 벡터

protected: HRESULT RenderSceneIntoEnvMap(); // 환경 장면 그리기 함수 HRESULT RenderScene(CONST D3DXMATRIXA16* pView, CONST D3DXMATRIXA16* pProject, BOOL bRenderTeapot); ……

class CMyD3DApplication : public CD3DApplication{ D3DXMATRIXA16 m_matProject; D3DXMATRIXA16 m_matView; D3DXMATRIXA16 m_matWorld; CD3DFont* m_pFont; CD3DMesh* m_pSkyBox; // 환경 매핑을 그리기 위한 프레임워크 CD3DMesh* m_pAirplane; // 동적 환경 매핑을 그리기 위한 프레임워크 D3DXMATRIXA16 m_matAirplane; // 비행기 변환을 위한 행렬 ID3DXMesh* m_pD3DXMesh; // 주전자를 그리기 위한 메쉬 구조체 LPD3DXEFFECT m_pEffect; // 셰이더 코드 컴파일 결과를 넘겨받을 효과 구조체 LPDIRECT3DCUBETEXTURE9 m_pCubeMap; ID3DXRenderToEnvMap* m_pRenderToEnvMap; // 동적 환경 매핑 저장 구조체 D3DXVECTOR4 m_vEyePos; // 시선 벡터

protected: HRESULT RenderSceneIntoEnvMap(); // 환경 장면 그리기 함수 HRESULT RenderScene(CONST D3DXMATRIXA16* pView, CONST D3DXMATRIXA16* pProject, BOOL bRenderTeapot); ……

Page 25: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 25

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• OneTimeSceneInit()OneTimeSceneInit()

HRESULT CMyD3DApplication::OneTimeSceneInit(){ D3DXMatrixIdentity( &m_matWorld );

m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_pSkyBox = new CD3DMesh(); m_pAirplane = new CD3DMesh();

if( !m_pFont || !m_pSkyBox || !m_pAirplane ) return E_OUTOFMEMORY;

return S_OK;}

HRESULT CMyD3DApplication::OneTimeSceneInit(){ D3DXMatrixIdentity( &m_matWorld );

m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_pSkyBox = new CD3DMesh(); m_pAirplane = new CD3DMesh();

if( !m_pFont || !m_pSkyBox || !m_pAirplane ) return E_OUTOFMEMORY;

return S_OK;}

Page 26: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 26

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• InitDeviceObjects()HRESULT CMyD3DApplication::InitDeviceObjects(){ TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("teapot.x")); LoadXFile(strFile);

if (FAILED(m_pSkyBox->Create(m_pd3dDevice, _T("lobby_skybox.x")))) return D3DAPPERR_MEDIANOTFOUND; if (FAILED(m_pAirplane->Create(m_pd3dDevice, _T("airplane 2.x")))) return D3DAPPERR_MEDIANOTFOUND;

// Set mesh properties m_pAirplane->SetFVF(m_pd3dDevice, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1);

// Restore the device-dependent objects m_pFont->InitDeviceObjects( m_pd3dDevice );

HRESULT hr; if (FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, "hlsl.fx", NULL, NULL, 3DXSHADER_DEBUG, NULL, &m_pEffect, NULL))) return hr; return S_OK;}

HRESULT CMyD3DApplication::InitDeviceObjects(){ TCHAR strFile[160]; DXUtil_FindMediaFileCb(strFile, sizeof(strFile),_T("teapot.x")); LoadXFile(strFile);

if (FAILED(m_pSkyBox->Create(m_pd3dDevice, _T("lobby_skybox.x")))) return D3DAPPERR_MEDIANOTFOUND; if (FAILED(m_pAirplane->Create(m_pd3dDevice, _T("airplane 2.x")))) return D3DAPPERR_MEDIANOTFOUND;

// Set mesh properties m_pAirplane->SetFVF(m_pd3dDevice, D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1);

// Restore the device-dependent objects m_pFont->InitDeviceObjects( m_pd3dDevice );

HRESULT hr; if (FAILED(hr = D3DXCreateEffectFromFile(m_pd3dDevice, "hlsl.fx", NULL, NULL, 3DXSHADER_DEBUG, NULL, &m_pEffect, NULL))) return hr; return S_OK;}

Page 27: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 27

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• RestoreDeviceObjects()

HRESULT CMyD3DApplication::RestoreDeviceObjects(){ m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice ); m_pFont->RestoreDeviceObjects(); m_pAirplane->RestoreDeviceObjects( m_pd3dDevice ); if( m_pEffect != NULL ) m_pEffect->OnResetDevice();

// Do all the basic setup FLOAT fAspect = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH(&m_matProject, D3DX_PI/3, fAspect, 0.5f, 100.0f); D3DXMatrixIdentity(&m_matWorld);

// Create RenderToEnvMap object if (FAILED(D3DXCreateRenderToEnvMap(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, m_d3dsdBackBuffer.Format, TRUE, D3DFMT_D16, &m_pRenderToEnvMap))) { return E_FAIL; } ………

HRESULT CMyD3DApplication::RestoreDeviceObjects(){ m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice ); m_pFont->RestoreDeviceObjects(); m_pAirplane->RestoreDeviceObjects( m_pd3dDevice ); if( m_pEffect != NULL ) m_pEffect->OnResetDevice();

// Do all the basic setup FLOAT fAspect = (FLOAT)m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH(&m_matProject, D3DX_PI/3, fAspect, 0.5f, 100.0f); D3DXMatrixIdentity(&m_matWorld);

// Create RenderToEnvMap object if (FAILED(D3DXCreateRenderToEnvMap(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, m_d3dsdBackBuffer.Format, TRUE, D3DFMT_D16, &m_pRenderToEnvMap))) { return E_FAIL; } ………

Page 28: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 28

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• RestoreDeviceObjects()( 계속 )……… // Create the cubemap, with a format that matches the backbuffer if (m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) { if (FAILED(D3DXCreateCubeTexture(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap))) { if (FAILED(D3DXCreateCubeTexture(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, 0, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap))) { m_pCubeMap = NULL; } } }

return S_OK;}

……… // Create the cubemap, with a format that matches the backbuffer if (m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) { if (FAILED(D3DXCreateCubeTexture(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap))) { if (FAILED(D3DXCreateCubeTexture(m_pd3dDevice, CUBEMAP_RESOLUTION, 1, 0, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &m_pCubeMap))) { m_pCubeMap = NULL; } } }

return S_OK;}

Page 29: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 29

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• FrameMove()

HRESULT CMyD3DApplication::FrameMove(){ // Animate file object D3DXMATRIXA16 mat; D3DXMatrixScaling( &m_matAirplane, 0.2f, 0.2f, 0.2f ); D3DXMatrixTranslation( &mat, 0.0f, 2.0f, 0.0f ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat ); D3DXMatrixRotationX( &mat, -2.9f * m_fTime ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat ); D3DXMatrixRotationY( &mat, 1.055f * m_fTime ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat );

// Set the eye position so that the eye orbits the object float Time = (float)GetTickCount() / 5000.0f; m_vEyePos = D3DXVECTOR4(3.0f * sin(Time), 0.0f, 3.0f * cos(Time), 0.0f);

// Make sure that the room isn't spinning... D3DXMatrixIdentity(&m_matWorld);

………

HRESULT CMyD3DApplication::FrameMove(){ // Animate file object D3DXMATRIXA16 mat; D3DXMatrixScaling( &m_matAirplane, 0.2f, 0.2f, 0.2f ); D3DXMatrixTranslation( &mat, 0.0f, 2.0f, 0.0f ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat ); D3DXMatrixRotationX( &mat, -2.9f * m_fTime ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat ); D3DXMatrixRotationY( &mat, 1.055f * m_fTime ); D3DXMatrixMultiply( &m_matAirplane, &m_matAirplane, &mat );

// Set the eye position so that the eye orbits the object float Time = (float)GetTickCount() / 5000.0f; m_vEyePos = D3DXVECTOR4(3.0f * sin(Time), 0.0f, 3.0f * cos(Time), 0.0f);

// Make sure that the room isn't spinning... D3DXMatrixIdentity(&m_matWorld);

………

Page 30: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 30

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• FrameMove()( 계속 )

• RenderSceneIntoEnvMap()

……… // Set the view matrix based on the position above. D3DXMatrixLookAtLH(&m_matView, &(D3DXVECTOR3)m_vEyePos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

// Render the scene into the surfaces of the cubemap if (FAILED(RenderSceneIntoEnvMap())) return E_FAIL;

return S_OK;}

……… // Set the view matrix based on the position above. D3DXMatrixLookAtLH(&m_matView, &(D3DXVECTOR3)m_vEyePos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

// Render the scene into the surfaces of the cubemap if (FAILED(RenderSceneIntoEnvMap())) return E_FAIL;

return S_OK;}

HRESULT CMyD3DApplication::RenderSceneIntoEnvMap(){ HRESULT hr;

// Set the projection matrix for a field of view of 90 degrees D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI*0.5f, 1.0f, 0.5f, 1000.0f);………

HRESULT CMyD3DApplication::RenderSceneIntoEnvMap(){ HRESULT hr;

// Set the projection matrix for a field of view of 90 degrees D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI*0.5f, 1.0f, 0.5f, 1000.0f);………

Page 31: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 31

Example : CubeMap3 Example : CubeMap3 (( 계속계속 ))

• RenderSceneIntoEnvMap()( 계속 )

……… // 큐브 맵 뷰 벡터를 생성 ( 여기서는 현재의 큐 벡터를 사용 ) D3DXMATRIXA16 matViewDir( m_matView ); matViewDir._41 = 0.0f; matViewDir._42 = 0.0f; matViewDir._43 = 0.0f;

// 환경 맵의 6 개 방향 장면을 그리기 시작 if (m_pCubeMap) hr = m_pRenderToEnvMap->BeginCube( m_pCubeMap );

if (FAILED(hr)) return hr;

for (UINT i = 0; i < 6; i++) { m_pRenderToEnvMap->Face((D3DCUBEMAP_FACES)i, 0); // 면을 지정 // 현재 지정된 환경 큐브 맵 표면에 대해 뷰 변환을 실시 D3DXMATRIXA16 matView; matView = D3DUtil_GetCubeMapViewMatrix( (D3DCUBEMAP_FACES) i ); D3DXMatrixMultiply( &matView, &matViewDir, &matView ); // 장면을 그린다 .( 주전자는 그리지 않는다 .) RenderScene( &matView, &matProj, FALSE ); } m_pRenderToEnvMap->End(0); // 환경 맵에 6 개 장면 그리기가 끝났음을 알림 ! return S_OK;}

……… // 큐브 맵 뷰 벡터를 생성 ( 여기서는 현재의 큐 벡터를 사용 ) D3DXMATRIXA16 matViewDir( m_matView ); matViewDir._41 = 0.0f; matViewDir._42 = 0.0f; matViewDir._43 = 0.0f;

// 환경 맵의 6 개 방향 장면을 그리기 시작 if (m_pCubeMap) hr = m_pRenderToEnvMap->BeginCube( m_pCubeMap );

if (FAILED(hr)) return hr;

for (UINT i = 0; i < 6; i++) { m_pRenderToEnvMap->Face((D3DCUBEMAP_FACES)i, 0); // 면을 지정 // 현재 지정된 환경 큐브 맵 표면에 대해 뷰 변환을 실시 D3DXMATRIXA16 matView; matView = D3DUtil_GetCubeMapViewMatrix( (D3DCUBEMAP_FACES) i ); D3DXMatrixMultiply( &matView, &matViewDir, &matView ); // 장면을 그린다 .( 주전자는 그리지 않는다 .) RenderScene( &matView, &matProj, FALSE ); } m_pRenderToEnvMap->End(0); // 환경 맵에 6 개 장면 그리기가 끝났음을 알림 ! return S_OK;}

Page 32: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 32

동적 굴절 반사 동적 굴절 반사 & Bump & Bump 매핑매핑

• 범프 매핑과 굴절범프 매핑과 굴절 && 반사 매핑을 결합반사 매핑을 결합

Page 33: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 33

그림자 생성하기그림자 생성하기• 그림자그림자

– 실감나는 영상 효과실감나는 영상 효과

– 물체가 놓여 있는 위치에 대한 확실한 공간감을 제공물체가 놓여 있는 위치에 대한 확실한 공간감을 제공

• 그림자 생성 요소그림자 생성 요소– 광원광원 (light source) / (light source) / 그림자 유발 물체그림자 유발 물체 (occluder) / (occluder) / 그림자가 그림자가

드리워질 면드리워질 면 (receiver)(receiver)

• DX3DDX3D 의 그림자 생성 기법의 그림자 생성 기법– Stencil Buffer Stencil Buffer 이용한 그림자 이용한 그림자

볼륨 기술을 제공볼륨 기술을 제공

Page 34: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 34

예제 예제 : Shadow Volume: Shadow Volume

• DirectX9DirectX9 에서 제공하는 에서 제공하는 TTwo-sided Stencil Buffer wo-sided Stencil Buffer 사용사용

• Shadow VolumeShadow Volume– 빛이 차단되는 부분빛이 차단되는 부분을 어떻게 을 어떻게

알아낼 것인가알아낼 것인가 ??

– 빛 방향에서 바라본 물체의 빛 방향에서 바라본 물체의 실루엣 외곽선을 찾아내야실루엣 외곽선을 찾아내야 함 함 !!

– 실루엣 외곽선 실루엣 외곽선 : : 광원을 광원을 바라보고 있는 면과 그렇지 바라보고 있는 면과 그렇지 않은 면의 경계를 의미않은 면의 경계를 의미 !!

– 메쉬 구조에서 메쉬 구조에서 실루엣 실루엣 외곽선을 추출하는 외곽선을 추출하는 PreProcePreProcessingssing 과정을 거친 후 과정을 거친 후 그림자를 그림그림자를 그림 !!

Page 35: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 35

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))

• Silhouette Outline Silhouette Outline 추출하기추출하기

– 면 사이의 경계선에 “면 사이의 경계선에 “ degenerate quaddegenerate quad”” 들을 삽입한다들을 삽입한다 ..

– degenerate quaddegenerate quad

• 면 사이의 경계선을 없애고 그 자리에 끼어 들어가는 형태면 사이의 경계선을 없애고 그 자리에 끼어 들어가는 형태

• 이 사각형의 양쪽 변은 좌표가 같음이 사각형의 양쪽 변은 좌표가 같음 ..

• 그러나 양 변의 법선 벡터는 두 경계선의 법선 벡터로 구성그러나 양 변의 법선 벡터는 두 경계선의 법선 벡터로 구성

• by by 타카시 이마기레 타카시 이마기레 ((http://www.t-pot.comhttp://www.t-pot.com))

Page 36: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 36

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))• 실루엣 외곽선 추출하기 (degenerate quad 삽입 )

HRESULT CShadowVolume::Create(LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXMESH pSrcMesh){ HRESULT ret = S_OK; struct MESHVERTEX { D3DXVECTOR3 p, n; }; SHADOW_VOLUME_VERTEX *pVertices; WORD *pIndices; DWORD i, j, k, l, face; LPD3DXMESH pMesh;

if (FAILED(pSrcMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, D3DFVF_XYZ|D3DFVF_NORMAL, pd3dDevice, &pMesh))) return E_FAIL; DWORD dwNumFaces = pMesh->GetNumFaces();

m_dwNumFaces = 4*dwNumFaces; // 면 개수의 4 배 만큼 m_pVertices = new SHADOW_VOLUME_VERTEX[3*m_dwNumFaces]; // 정점 개수의 3 배 만큼

pMesh->LockVertexBuffer(0L, (LPVOID*)&pVertices ); // 원본 정점 버퍼 포인터 pMesh->LockIndexBuffer (0L, (LPVOID*)&pIndices ); // 원본 인덱스 버퍼 포인터 D3DXVECTOR3 *vNormal = new D3DXVECTOR3[dwNumFaces];// 법선 벡터 저장 공간 할당 if (NULL == vNormal) { // 메모리 부족 시 에러 처리 m_dwNumFaces = 0; ret = E_OUTOFMEMORY; goto end; }

HRESULT CShadowVolume::Create(LPDIRECT3DDEVICE9 pd3dDevice, LPD3DXMESH pSrcMesh){ HRESULT ret = S_OK; struct MESHVERTEX { D3DXVECTOR3 p, n; }; SHADOW_VOLUME_VERTEX *pVertices; WORD *pIndices; DWORD i, j, k, l, face; LPD3DXMESH pMesh;

if (FAILED(pSrcMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, D3DFVF_XYZ|D3DFVF_NORMAL, pd3dDevice, &pMesh))) return E_FAIL; DWORD dwNumFaces = pMesh->GetNumFaces();

m_dwNumFaces = 4*dwNumFaces; // 면 개수의 4 배 만큼 m_pVertices = new SHADOW_VOLUME_VERTEX[3*m_dwNumFaces]; // 정점 개수의 3 배 만큼

pMesh->LockVertexBuffer(0L, (LPVOID*)&pVertices ); // 원본 정점 버퍼 포인터 pMesh->LockIndexBuffer (0L, (LPVOID*)&pIndices ); // 원본 인덱스 버퍼 포인터 D3DXVECTOR3 *vNormal = new D3DXVECTOR3[dwNumFaces];// 법선 벡터 저장 공간 할당 if (NULL == vNormal) { // 메모리 부족 시 에러 처리 m_dwNumFaces = 0; ret = E_OUTOFMEMORY; goto end; }

Page 37: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 37

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))• 실루엣 외곽선 추출하기 (degenerate quad 삽입 )( 계속 )

……… // 모든 면에 대해 면 법선 벡터를 계산한다 . for (i = 0; i < dwNumFaces; i++) { D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p; D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p; D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;

// 면 법선 벡터를 계산 D3DXVECTOR3 vCross1(v1-v0); D3DXVECTOR3 vCross2(v2-v1); D3DXVec3Cross( &vNormal[i], &vCross1, &vCross2 );

// store a face m_pVertices[3*i+0].p = v0; m_pVertices[3*i+1].p = v1; m_pVertices[3*i+2].p = v2; m_pVertices[3*i+0].n = vNormal[i]; m_pVertices[3*i+1].n = vNormal[i]; m_pVertices[3*i+2].n = vNormal[i]; }………

……… // 모든 면에 대해 면 법선 벡터를 계산한다 . for (i = 0; i < dwNumFaces; i++) { D3DXVECTOR3 v0 = pVertices[pIndices[3*i+0]].p; D3DXVECTOR3 v1 = pVertices[pIndices[3*i+1]].p; D3DXVECTOR3 v2 = pVertices[pIndices[3*i+2]].p;

// 면 법선 벡터를 계산 D3DXVECTOR3 vCross1(v1-v0); D3DXVECTOR3 vCross2(v2-v1); D3DXVec3Cross( &vNormal[i], &vCross1, &vCross2 );

// store a face m_pVertices[3*i+0].p = v0; m_pVertices[3*i+1].p = v1; m_pVertices[3*i+2].p = v2; m_pVertices[3*i+0].n = vNormal[i]; m_pVertices[3*i+1].n = vNormal[i]; m_pVertices[3*i+2].n = vNormal[i]; }………

Page 38: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 38

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))• 실루엣 외곽선 추출하기 (degenerate quad 삽입 )( 계속 )

……… // 각 면의 세 변에 대해서 face = dwNumFaces; for ( i=0; i<dwNumFaces; i++ ) { for( j=i+1; j<dwNumFaces; j++ ) { DWORD id[2][2]; // checklist DWORD cnt=0;

for (k=0; k < 3; k++) { for (l=0; l < 3; l++) { D3DXVECTOR3 dv; D3DXVec3Subtract( &dv, &pVertices[pIndices[3*i+k]].p, &pVertices[pIndices[3*j+l]].p); // 서로 다른 두 면에 있는 두 정점들이 하나의 변을 형성하면 변 공유이므로 // checklist 에 넣고 counter 를 1 증가 시킨다 . if ( D3DXVec3LengthSq( &dv ) < 0.001f ) { // cnt counts until two? 정점 2 개를 공유하면 변을 공유하는 것임 ! id[cnt][0] = 3*i+k; id[cnt][1] = 3*j+l; cnt++; } } }………

……… // 각 면의 세 변에 대해서 face = dwNumFaces; for ( i=0; i<dwNumFaces; i++ ) { for( j=i+1; j<dwNumFaces; j++ ) { DWORD id[2][2]; // checklist DWORD cnt=0;

for (k=0; k < 3; k++) { for (l=0; l < 3; l++) { D3DXVECTOR3 dv; D3DXVec3Subtract( &dv, &pVertices[pIndices[3*i+k]].p, &pVertices[pIndices[3*j+l]].p); // 서로 다른 두 면에 있는 두 정점들이 하나의 변을 형성하면 변 공유이므로 // checklist 에 넣고 counter 를 1 증가 시킨다 . if ( D3DXVec3LengthSq( &dv ) < 0.001f ) { // cnt counts until two? 정점 2 개를 공유하면 변을 공유하는 것임 ! id[cnt][0] = 3*i+k; id[cnt][1] = 3*j+l; cnt++; } } }………

Page 39: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 39

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))• 실루엣 외곽선 추출하기 (degenerate quad 삽입 )( 계속 )

……… // if two times two vertices from two faces share one edge ? if (2 == cnt) { // if one face has a different direction than the other face ? if (id[1][0]-id[0][0]!=1) { // adjust direction of face DWORD tmp = id[0][0]; id[0][0] = id[1][0]; id[1][0] = tmp; // swap id[0][0] and id[1][0] tmp = id[0][1]; id[0][1] = id[1][1]; id[1][1] = tmp; // swap id[0][1] and id[1][1] } // insert degenerated quadrilateral // the face normals are used for the vertex normals m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p; m_pVertices[3*face+2].p = pVertices[pIndices[id[0][1]]].p; m_pVertices[3*face+1].p = pVertices[pIndices[id[0][0]]].p; m_pVertices[3*face+0].n = vNormal[i]; m_pVertices[3*face+2].n = vNormal[j]; m_pVertices[3*face+1].n = vNormal[i]; face++;………

……… // if two times two vertices from two faces share one edge ? if (2 == cnt) { // if one face has a different direction than the other face ? if (id[1][0]-id[0][0]!=1) { // adjust direction of face DWORD tmp = id[0][0]; id[0][0] = id[1][0]; id[1][0] = tmp; // swap id[0][0] and id[1][0] tmp = id[0][1]; id[0][1] = id[1][1]; id[1][1] = tmp; // swap id[0][1] and id[1][1] } // insert degenerated quadrilateral // the face normals are used for the vertex normals m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p; m_pVertices[3*face+2].p = pVertices[pIndices[id[0][1]]].p; m_pVertices[3*face+1].p = pVertices[pIndices[id[0][0]]].p; m_pVertices[3*face+0].n = vNormal[i]; m_pVertices[3*face+2].n = vNormal[j]; m_pVertices[3*face+1].n = vNormal[i]; face++;………

Page 40: Part 3 DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting

3 DirectX 9 Programming Conventions제 장 40

예제 예제 : Shadow Volume : Shadow Volume (( 계속계속 ))• 실루엣 외곽선 추출하기 (degenerate quad 삽입 )( 계속 )

……… m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p; m_pVertices[3*face+2].p = pVertices[pIndices[id[1][1]]].p; m_pVertices[3*face+1].p = pVertices[pIndices[id[0][1]]].p; m_pVertices[3*face+0].n = vNormal[i]; m_pVertices[3*face+2].n = vNormal[j]; m_pVertices[3*face+1].n = vNormal[j]; face++; } } } assert(face == m_dwNumFaces); delete[] vNormal;end: // unlock buffers pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer();

pMesh->Release();

return ret;}

……… m_pVertices[3*face+0].p = pVertices[pIndices[id[1][0]]].p; m_pVertices[3*face+2].p = pVertices[pIndices[id[1][1]]].p; m_pVertices[3*face+1].p = pVertices[pIndices[id[0][1]]].p; m_pVertices[3*face+0].n = vNormal[i]; m_pVertices[3*face+2].n = vNormal[j]; m_pVertices[3*face+1].n = vNormal[j]; face++; } } } assert(face == m_dwNumFaces); delete[] vNormal;end: // unlock buffers pMesh->UnlockVertexBuffer(); pMesh->UnlockIndexBuffer();

pMesh->Release();

return ret;}