1 / 40

Part 3 DirectX Graphics Core Programming

Part 3 DirectX Graphics Core Programming. Chap 9. Shader Programming using High Level Shader Language DirectX9 에서부터 지원되는 HLSL 을 사용하여 Per-Pixel Lighting 을 구현 Chapter 10. Using Advanced Shader Effect Cube Environment Mapping Effect Realtime Shadowing Effect Chapter 11. X File

holtz
Download Presentation

Part 3 DirectX Graphics Core Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Part 3DirectX Graphics Core Programming Chap 9. Shader Programming using High Level Shader Language DirectX9에서부터 지원되는 HLSL을 사용하여 Per-Pixel Lighting을 구현 Chapter 10. Using Advanced Shader Effect Cube Environment Mapping Effect Realtime Shadowing Effect Chapter 11. X File X 파일에 저장된 기하 정보의 이용 Chapter 12. Handling *.md3 Files HLSL Shader와 *.md3 파일을 이용한 캐릭터 엔진 구현

  2. Chapter 10Using Advanced Shader Effect 숙명여자대학교 이과대학 정보과학부 멀티미디어과학전공 조교수 이종우 bigrain@sookmyung.ac.kr

  3. Contents • Cube Map을 만들고 호출하는 방법 • 동적인 굴절과 반사 매핑 처리 방법 • 그림자와 그림자 부피 효과 제 3 장 DirectX 9 Programming Conventions

  4. Using Cube Map • Reflection Mapping • 빛이 반사된 표면을 처리하는 기법  반사 매핑, 환경 매핑 • 반사 표면을 처리하는 기법 • 방법 1 • 빛의 물리적 성질에 대한 모델링을 한 후 • 물체로부터 반사된 secondary light에 대한 ray tracing을 실시 • 방법 2 • 미리 만들어둔 주위 환경을 물체 표면에 입혀서 • 반사가 일어난 것 같은 효과를 내는 기법 • 여기서 “미리 만들어둔 주위 환경”을 큐브 환경 맵 또는 큐브 맵이라고 함 제 3 장 DirectX 9 Programming Conventions

  5. Using Cube Map (계속) • Cube Map 생성하기 • 큐브 맵을 입힐 물체가 들어갈 자리에 물체 대신 카메라를 놓고 여섯 방향으로 렌더링을 하거나 사진을 찍는다. • 이 6장의 그림들은 시야각 90도의 정사각형 모양  그래야 큐브에 입혔을 때 이음매가 잘 연결될 것임! 제 3 장 DirectX 9 Programming Conventions

  6. Using Cube Map (계속) • Cube Map 사용하기 • R = I – 2 * (I  N) * N 제 3 장 DirectX 9 Programming Conventions

  7. Example : CubeMap • 환경 매핑을 이용하여 크롬 재질의 반짝거리는 주전자를 그리는 예 • VS가 각 정점에서의 시선 벡터와 반사 벡터를 계산 • VS가 이를 PS에게 전달 • PS는 이를 이용해 큐브 맵에서 데이터를 꺼내와 결과물로 내보냄 제 3 장 DirectX 9 Programming Conventions

  8. Example : CubeMap (계속) • CD3DApplication클래스 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(); }; 제 3 장 DirectX 9 Programming Conventions

  9. Example : CubeMap (계속) • 생성자 & 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; } 제 3 장 DirectX 9 Programming Conventions

  10. Example : CubeMap (계속) • 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; } 제 3 장 DirectX 9 Programming Conventions

  11. Example : CubeMap (계속) • 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; } 제 3 장 DirectX 9 Programming Conventions

  12. Example : CubeMap (계속) • 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; } 제 3 장 DirectX 9 Programming Conventions

  13. Example : CubeMap (계속) • Render() / 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 ); 제 3 장 DirectX 9 Programming Conventions

  14. Example : CubeMap (계속) • Render() / 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 ); 제 3 장 DirectX 9 Programming Conventions

  15. 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; } 제 3 장 DirectX 9 Programming Conventions

  16. PS() / VS()코드 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; }; 제 3 장 DirectX 9 Programming Conventions

  17. PS() / VS()코드 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; } 제 3 장 DirectX 9 Programming Conventions

  18. PS() / VS()코드 Example : CubeMap (계속) 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(); } } 제 3 장 DirectX 9 Programming Conventions

  19. 굴절과 반사가 있는 환경 매핑 • 환경 매핑에 굴절 효과 넣기 • 굴절(Refraction) • 서로 다른 매개체를 통과할 때 빛이 꺾이는 현상 • 면이 출렁이면 꺾이는 각도가 달라짐 • 방법 • 반사 계산식과 법선 벡터의 길이를 조작하여 근사적으로 계산 • 법선 벡터의 길이를 일부러 1보다 작은 값으로 줄여 벡터의 방향을 의도적으로 변경했음! • 법선 벡터 길이 0 : 굴절 벡터가 시선 벡터와 같아짐. • 법선 벡터가 길어질수록 굴절 벡터는 경계면 쪽으로 꺾이게 됨 제 3 장 DirectX 9 Programming Conventions

  20. Example : CubeMap2 • VS() / 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; }; 제 3 장 DirectX 9 Programming Conventions

  21. Example : CubeMap2 (계속) • VS() / 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; } 제 3 장 DirectX 9 Programming Conventions

  22. Example : CubeMap2 (계속) • VS() / 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(); } } 제 3 장 DirectX 9 Programming Conventions

  23. 동적 굴절 & 동적 반사 환경 매핑 • 동적 큐브 맵 • 미리 만들어 놓은 큐브 맵이 아닌 매 프레임마다 새로 큐브 맵을 생성함. • 코딩 방법 • 주전자 주위를 날아다니는 비행기를 하나 띄우고, • 그 비행기의 모습이 주전자 표면에 반사되게 하여 확인 함! • 큐브 맵 동적 생성 방법 • 주전자는 제외한 채로 • 환경과 비행기가 날아가는 장면을 생성 • 생성된 화면 6개를 큐브 맵에 저장 • 다음 번 render()시에 이 큐브 맵을 사용 제 3 장 DirectX 9 Programming Conventions

  24. Example : CubeMap3 • CD3DApplication구조체 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); …… 제 3 장 DirectX 9 Programming Conventions

  25. Example : CubeMap3 (계속) • 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; } 제 3 장 DirectX 9 Programming Conventions

  26. 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; } 제 3 장 DirectX 9 Programming Conventions

  27. 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; } ……… 제 3 장 DirectX 9 Programming Conventions

  28. 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; } 제 3 장 DirectX 9 Programming Conventions

  29. 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); ……… 제 3 장 DirectX 9 Programming Conventions

  30. 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; } 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); ……… 제 3 장 DirectX 9 Programming Conventions

  31. 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; } 제 3 장 DirectX 9 Programming Conventions

  32. 동적 굴절 반사 & Bump 매핑 • 범프 매핑과 굴절&반사 매핑을 결합 제 3 장 DirectX 9 Programming Conventions

  33. 그림자 생성하기 • 그림자 • 실감나는 영상 효과 • 물체가 놓여 있는 위치에 대한 확실한 공간감을 제공 • 그림자 생성 요소 • 광원(light source) / 그림자 유발 물체(occluder) / 그림자가 드리워질 면(receiver) • DX3D의 그림자 생성 기법 • Stencil Buffer 이용한 그림자 볼륨 기술을 제공 제 3 장 DirectX 9 Programming Conventions

  34. 예제 : Shadow Volume • DirectX9에서 제공하는 Two-sided Stencil Buffer 사용 • Shadow Volume • 빛이 차단되는 부분을 어떻게 알아낼 것인가? • 빛 방향에서 바라본 물체의 실루엣 외곽선을 찾아내야 함! • 실루엣 외곽선 : 광원을 바라보고 있는 면과 그렇지 않은 면의 경계를 의미! • 메쉬 구조에서 실루엣 외곽선을 추출하는 PreProcessing과정을 거친 후 그림자를 그림! 제 3 장 DirectX 9 Programming Conventions

  35. 예제 : Shadow Volume (계속) • Silhouette Outline 추출하기 • 면 사이의 경계선에 “degenerate quad”들을 삽입한다. • degenerate quad • 면 사이의 경계선을 없애고 그 자리에 끼어 들어가는 형태 • 이 사각형의 양쪽 변은 좌표가 같음. • 그러나 양 변의 법선 벡터는 두 경계선의 법선 벡터로 구성 • by 타카시 이마기레 (http://www.t-pot.com) 제 3 장 DirectX 9 Programming Conventions

  36. 예제 : 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; } 제 3 장 DirectX 9 Programming Conventions

  37. 예제 : 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]; } ……… 제 3 장 DirectX 9 Programming Conventions

  38. 예제 : 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++; } } } ……… 제 3 장 DirectX 9 Programming Conventions

  39. 예제 : 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++; ……… 제 3 장 DirectX 9 Programming Conventions

  40. 예제 : 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; } 제 3 장 DirectX 9 Programming Conventions

More Related