Direct 3D Direct 3D 프로그래밍의 흐름 Direct3D8 객체 생성 Direct3D8 객체 사용 Direct3DCreate8() CreateDevice() Direct3D8 객체 사용 Clear() BeginScene() Rendering 내용 정의 EndScene() Present() Direct3D8 객체 제거 pd3dDevice->Release(); pD3D->Release();
Direct 3D Direct3D8 객체 생성 Direct3DCreate8 함수를 이용하여 Idirect3D8인터페이스 생성 LPDIRECT3D8 pD3D = NULL; // Create the D3D object. if( NULL == ( pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) ) return E_FAIL; D3D_SDK_VERSION : 사용자의 버전 확인을 위함 에러가 없다면 이 함수는 Idirect8인터페이스의 핸들을 리턴함.
Direct 3D Direct3D8 Device 생성 IDirect3D8::CreateDevice() 함수를 이용하여 원하는 비디오 디스플레이를 나타내는 디바이스를 생성함. 함수원형 HRESULT CreateDevice UINT Adapter, DDEVTYPE DeviceType, HWND hFocusWindow, DWORD behaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, Idirect#DDevice8** ppReturnedDeviceInterface
Direct 3D 장치 생성 Parameter // Create the D3DDevice if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice ) ) ) Parameter D3DADAPTER_DEFAULT - 기본 어댑터로 장치를 생성 (하나의 그래픽 카드) D3DDEVTYPE_HAL – 하드웨어 장치를 사용 hWnd – 현재 윈도우 핸들 D3DCREATE_SOFTWARE_VERTEXPROCESSING – 소프트웨어를 통한 정점처리 &d3dpp(D3DPRESENT_PARAMETERS) – 장치를 생성시 사용할 옵션 설정 &pd3DDevice(LPDIRECT3DDEVICE8) – 생성된 장치
Direct 3D d3dpp(D3DPRESENT_PARAMETERS) 작성 //GetAdapterDisplayMode()함수를 이용하여 DisplayMode정보를 받아옴 D3DDISPLAYMODE d3ddm; pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ); //작성할 구조체를 초기화 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); //true를 적용하여 윈도우 모드를 선택 d3dpp.Windowed = TRUE; //2차원 표면내용을 1차원표면으로 flip하는 방법을 적용시킴 //가장 효율적인 방법 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //DisplayMode의 포멧방식을 적용시킨다. d3dpp.BackBufferFormat = d3ddm.Format;
Direct 3D 장치 타입 (DeviceType) Reference Device HAL Device (Hardware abstraction layer) 하드웨어를 이용한 연출 (하드웨어를 가지고 그림) 렌더링 속도 빠름 플래그 : D3DDEVTYPE_HAL 세트 Reference Device 하드웨어와 소프트웨어를 이용한 연출 (하드웨어로 부족할때) 렌더링 속도 중간 플레그 : D3DDEVTYPE_REF Pluggable Software Device 소프트웨어를 이용한 연출 렌도링 속도 느림 플레그 : D3DDEVTYPE_SW 정점처리 (behaviorFlags) D3DCREATE_HARDWARE_VERTEXPROCESSING nVida그래픽카드에서 사용할 수 있는 하드웨어 변형과 조명을 사용한다. D3DCREATE_SOFTWARE_VERTEXPROCESSING 소프트웨어 변형과 조명을 사용한다.
Direct 3D 렌더링 하기 (Rendering) 실행코드 Clear() // Clear the scene pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 0.0f, 0 ); pd3dDevice->BeginScene(); …랜더링 내용 정의… pd3dDevice->EndScene(); // Output the scene pd3dDevice->Present( NULL, NULL, NULL, NULL ); Clear() 첫번째 인자에 0을 설정하고, 두번째 인자에 NULL을 설정 함으로써 rendering target을 덮는 하나의 사각형을 사용한다. 세번째 인자는 버퍼(render target, 깊이버퍼, 스텐실버퍼)중 rendering target만을 사용한다. 나머지 세개의 인자는 render target, 깊이 버퍼, 그리고 스텐실 버퍼를 위한 지울 값을 반영하기 위해 설정한다. 현재 render target만을 사용하였으므로 파란색으로 rendering target을 지웠으며 나머지 값은 무시된다.
Direct 3D BeginScene() EndScene() Present() 3D배경에 어떤 폴리곤들을 실제로 출력하기 전에 먼저 BeginScene()함수를 사용해서 3D 랜더링 모드로 진입해야 함 EndScene() BeginScene() 함수를 호출하면 반드시 EndScene()함수를 호출해야 한다. 또한 이 작업을 거친 후에 출력된 최종 그래픽은 디바이스에 저장이 된다. Present() 렌더링된 장면을 화면에 display하는 작업 대부분의 경우에 NULL로 설정되어야만 한다 첫번째 인자는 source 사각형이다. 두번째 인자는 destination 사각형이다. 이 단계에 샘플 코드는 이 두 인자에 NULL을 설정함으로써 전체 백버퍼(준비버퍼)를 프론트버퍼(출력버퍼)로 present한다. 세번째 인자는 이 presentation을 위한 destination 윈도우를 설정한다. 이 인자가 NULL로 설정되었기 때문에 D3DPRESENT_PARAMETERS 의 hWndDeviceWindow 맴버가 사용된다. 네번째 인자는 DirtyRegion 인자이다.
Direct 3D 장치 제거 실행코드 if( pd3dDevice != NULL ) pd3dDevice->Release(); if( pD3D != NULL ) pD3D->Release(); 프로그램을 종료하기 전에 생성한 모든 디바이스와 오브젝트를 제거해야 한다. Release()함수를 이용하여 IDirect3DDevice를 제거하였다.
Direct 3D DirectXGraphics의 공통화일 공통화일의 장점 공통화일의 예 DirectX SDK의 DXSDK\samples\C++\Common 디렉토리에 포함된 C++ 소스와 헤더 파일들로서 예제 프로그램들의 전체적인 프레임워크를 구성 공통화일의 장점 일반적인 Direct3D사용법보다 개발에 더 집중할 수 있다. 공통적으로 쓰이고 검증된 프레임 워크이므로 디버깅 타임이 줄어든다. 공통화일에서 제공하는 윈도우 모드를 사용하면 디버깅이 훨씬 간편하다 공통화일 기반으로 자신만의 코드를 만들 수 있다. 공통화일의 예 d3dapp.cpp 이 파일 안에서 샘플 프로그램의 어플리케이션 인터페이스를 볼 수 있다. d3dutil.cpp and dxutil.cpp DirectX의 객체들을 사용하는데 필요한 단축 매크로들과 함수들을 제공한다. d3dfont.cpp 텍스쳐 기반의 폰트를 제공한다. 텍스트를 디스플레이 할 때 사용된다. DirectX 위저드를 사용하여 d3dapp.cpp를 상속받은 CMyD3DApplication을 사용하여 장치생성 및 렌더링을 쉽게 할 수 있다.
Direct 3D VC++ Direct X 메뉴 new -> Projects DirectX 9 AppWizard Projects name 설정 -> Direct Music 제거 후 Next -> Triangle 체크 후 Next -> DirectInput keyboard device 체크 후 Finish
Direct 3D D3Dapp.h화일에서 제공하는 공용 인터페이스 (black: window, blue: device) virtual HRESULT OneTimeSceneInit() {return S_OK; } 어플리케이션이 시작될 때 처음 한번만 초기화가 필요한 변수(기하정보를 로드하거나, 초기에 계산되어야 할 값)들은 여기서 초기화 되어야 한다. virtual HRESULT InitDeviceObjects() {return S_OK; } 애플리케이션을 시작할때 호출된다. virtual HRESULT InvalidateDeviceObjects() {return S_OK; } 사용자에 의해 윈도우 사이즈가 변하거나 디바이스가 바뀔때 호출되며, 이어서 RestoreDeviceObjects()메소드가 호출되며, 윈도우 시작시에는 호출되지 않는다. virtual HRESULT RestoreDeviceObjects() {return S_OK; } 윈도우 시작시 호출되며 디바이스나 윈도우 사이즈가 변경되었을때 InvalidateDeviceObject()에 이어 호출된다. virtual HRESULT DeleteDeviceObjects() {return S_OK; } 애플리케이션이 종료될때 호출된다. virtual HRESULT Render() {return S_OK; } 렌더링을 담당하는 함수이며 매 프레임마다 한번씩 호출된다. virtual HRESULT FrameMove() {return S_OK; } 애니메이션에 사용되며 매 프레임마다 한번씩 호출된다. virtual HRESULT FinalCleanup() {return S_OK; } 기하정보에 쓰인 메모리를 제거하고, 파일객체들을 제거한다.
Direct 3D 사용할 CUSTOMVERTEX 구조체 생성 생성된 코드 struct CUSTOMVERTEX { D3DXVECTOR3 position; // vertex position D3DXVECTOR3 normal; // vertex normal }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL) 아래와 같은 정점포맷 플래그를 사용하여 정점구조체의 요소들에 대한 정보를 작성할 수 있다. D3DFVF_XYZRHW는 월드, 뷰, 프로젝션 뷰를 사용하여 변환하지 않음을 의미한다. D3DFVF_XYZ은 Direct3D가 변환을 수행하도록 요청함을 의미한다. D3DFVF_DIFFUSE는 정점 포맷이 확산(diffuse) 색 요소를 포함하고 있음을 나타낸다. D3DFVF_NORMAL은 법선 벡터(normal vector) 요소를 포함함을 나타내며 빛의 반사에 영향을 준다. D3DFVF_TEX1은 텍스쳐를 사용하며 텍스쳐 좌표 쌍을 포함한다
Direct 3D 정점버퍼 생성 (vertex buffer) 생성된 코드 HRESULT hr; // Create the vertex buffer if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 3*2*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &m_pVB, NULL ) ) ) return DXTRACE_ERR( "CreateVertexBuffer", hr ); // Fill the vertex buffer with 2 triangles CUSTOMVERTEX* pVertices; if( FAILED( hr = m_pVB->Lock( 0, 0, (VOID**)&pVertices, 0 ) ) ) return DXTRACE_ERR( "Lock", hr ); //////정점 삽입 m_pVB->Unlock();
Direct 3D 정점버퍼 생성 (vertex buffer) CreateVertexBuffer() 첫번째 인자는 정점의 크기정보를 가지며 두번째 인자는 사용자에 의해 정의된 정점의 어법을 나타내며 세번째 인자는 정점의 구조에 대한 플래그 값들로 이루어진 정보이며 네번째 인자는 정점을 위한 메모리의 위치를 명시하며 다섯번째 인자는 정점버퍼 인터페이스에 대한 포인터이다. m_pVB->Lock() 첫번째 인자는 잠그기 위한 정점 정보의 오프셋이며 두번째 인자는 잠그기 위한 정점 정보의 바이트 크기이며 세번째 인자는 한 포인터로 정점 정보를 채운 구조체의 포인터이며 네번째 인자는 정보를 잠그는 방법을 정점 버퍼에게 전달한다
Direct 3D 정점버퍼 생성 (vertex buffer) 생성된 코드 // Front triangle (clockwise) pVertices[0].position = D3DXVECTOR3( -1.0f, -1.0f, 0.0f ); pVertices[0].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[1].position = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[1].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[2].position = D3DXVECTOR3( 1.0f, -1.0f, 0.0f ); pVertices[2].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); // Back triangle pVertices[3].position = D3DXVECTOR3( -1.0f, -1.0f, 0.0f ); pVertices[3].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[4].position = D3DXVECTOR3( 1.0f, -1.0f, 0.0f ); pVertices[4].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[5].position = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[5].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
Direct 3D 재질 (RestoreDevideObjects() 안) 생성된 코드 재질 D3DMATERIAL9 mtrl; D3DUtil_InitMaterial(mtrl, 1.0f, 0.0f, 0.0f); //반사할 색상을 mtrl에 설정 M_pd3dDevice->SetMaterial( &mtrl); m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE); m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,TRUE); m_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x000F0F0F); 재질 기본적으로 재질 값이 설정되어 있지 않음으로 재질 값을 설정해 주어야 한다. D3DUtil_InitMaterail의 뒤 3개의 인자는 각각 RGB를 나타내며 각색을 얼마나 반사할 것인지를 설정한다. 현재 빨간색을 반사한다 SetRenderState는 디더링(색을 섞음)을 선택하지 않았으며 빛 반사를 선택하지 않았으며 Z버퍼를 사용하며 주변광을 설정하여 준다.
Direct 3D 뷰 메트릭스(view matrix) 월드 매트릭스(world matrix) 생성된 코드 월드 매트릭스 D3DXMATRIX matIdentiy; D3DMatrixIdentity(&matIdentity); // 기본 값 M_pd3dDevice->SetTransform( D3DTS_WORLD, &matIdentity); 월드 매트릭스 물체의 위치 및 회전량을 설정한다 현재 코드는 기본값을 할당함으로써 가운데 위치하며 회전되지 않았음을 의미한다. 뷰 메트릭스(view matrix) D3DXMATRIX matView; D3DXVECTOR3 vFromPt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f ); D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); // 카메라의 위 방향 값 D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec ); M_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); 뷰 메트릭스 뷰 메트릭스는 3차원 가상공간을 바라보는 카메라를 의미하며 현재 코드는 vFromPt 벡터 (바라보는 카메라) 가 앞쪽에 위치하며 vLookatPt 벡터 (바라보는 대상) 가 정 가운데를 나타내며 vUpVec 벡터 (카메라의 회전) 가 카메라가 똑바로 서있음을 의미한다
Direct 3D 프로젝션(투영) 매트릭스(projection matrix) 생성된 코드 투영 매트릭스 D3DXMATRIX matProj; Float fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f); M_pd3dDevice->SetTransform(D3DTS_View, &matView); 투영 매트릭스 Microsoft Direct3D 디바이스를 현재의 투영으로 지정합니다 D3DXMatrixPerspectiveFovLH() 첫번째 인자는 지정할 행렬을 의미하며 두번째 인자는 시야를 의미(멀리있는 것은 작게 보이고 가까이 있는 것은 크게 보이는데 그것을 계산할 각도)하며 세번째 인자는 화면을 나타낼 가로 / 세로의 비를 나타내며 m_d3dsdBackBuffer를 통하여 얻어 왔다 네번째 와 다섯번재는 실제 화면에 나타낼 거리를 나타내는 것으로 네번째 인자는 가까운 클리핑 면을 나타내며 다섯번재 인자는 먼 클리핑 면을 나타낸다. 현재 상태는 45도의 각도로 가까운 곳이 시선에서 1떨어진 곳부터 100 떨어진 곳까지 랜더링 하여 화면에 뿌려줌을 의미한다.
Direct 3D 빛(light) 생성된 코드 빛 D3DLIGHT9 light; D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, -1.0f, -1.0f, 2.0f ); m_pd3dDevice->SetLight( 0, &light ); m_pd3dDevice->LightEnable( 0, TRUE ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE); 빛 빛의 방향 및 빛의 종류를 설정한다. 현재 코드상태는 빛을 방향성의 빛을 X축 -1 Y축 -1 Z축 2의 방향으로 빛을 비춘다.
Direct 3D 애니메이션(FrameMove) 생성된 코드 UpdateInput( &m_UserInput ); // Update the world state according to user input D3DXMATRIX matWorld; D3DXMATRIX matRotY; D3DXMATRIX matRotX; if( m_UserInput.bRotateLeft && !m_UserInput.bRotateRight ) m_fWorldRotY += m_fElapsedTime; else if( m_UserInput.bRotateRight && !m_UserInput.bRotateLeft ) m_fWorldRotY -= m_fElapsedTime; if( m_UserInput.bRotateUp && !m_UserInput.bRotateDown ) m_fWorldRotX += m_fElapsedTime; else if( m_UserInput.bRotateDown && !m_UserInput.bRotateUp ) m_fWorldRotX -= m_fElapsedTime; D3DXMatrixRotationX( &matRotX, m_fWorldRotX ); D3DXMatrixRotationY( &matRotY, m_fWorldRotY ); D3DXMatrixMultiply( &matWorld, &matRotX, &matRotY ); m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); FrameMove 애니메이션 에 의한 변화를 계산한다 현재 코드상태는 각 프레임 마다 사용자가 어떤키를 누르고 있는지 확인후 그 키에따라 사물(WORLD)을 회전변환을 나타내고 있다
Direct 3D 랜더링 생성된 코드 m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ); if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) ); m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ); // Render stats and help text RenderText(); // End the scene. m_pd3dDevice->EndScene(); } 렌더링은 실제 3차원 가상공간 및 오브젝트를 계산하여 화면에 맵핑한다. 현재 코드상태는 화면을 파란색으로 초기화를하며 m_pVB에 정의된 정점을 TRIANGLELIST형식으로 2개의 삼각형을 그린다 SetSTreamSource() – 정점버퍼를 디바이스의 데이터 스트림에 연결한다. SetFVF() - 정점의 구조를 제시한다. DrawPrimitive() – 화면의 그릴 형식을 선언하며, 어디서(0)부터 몇 개(2)를 그릴 것인지 명시한다.
Direct 3D 실습1 Visual C++ 환경설정 코딩 현재 생성된 코드를 이용하여 원하는 사진을 사각형에 뿌려줌 원하는 그림파일을 다운받는다. 그림파일을 현재 프로젝트 폴더에 저장한다. Visual C++ 환경설정 메뉴 Tools-> Options -> Directories에 Include 폴더 (C:\DXSDK\INCLUDE) 와 libraries 폴더C:\DXSDK\LIB) 지정하고 최상위로 올려줌 코딩 프로젝트이름.h 파일에 CUSTOMVERTEX를 다음과 같이 수정한다 struct CUSTOMVERTEX { D3DXVECTOR3 position; // vertex position D3DXVECTOR3 normal; // vertex normal float tu,tv; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) 그림을 삽입하기 위하여 택스쳐 맵핑 좌표계를 정의할 수 있도록 D3DFVF_TEX1 플래그를 삽입하고 float형식의 좌표를 저장할 수 있도록 구조체를 정의한다
Direct 3D 코딩 프로젝트이름.h 파일에 CMyD3DApplication의 멤버변수로 다음과 같이 추가한다 LPDIRECT3DTEXTURE9 g_pTexture1; 프로젝트이름.cpp 파일에 InitDeviceObjects() 메소드에 다음과 같은 코드를 삽입한다 if( FAILED( D3DXCreateTextureFromFile( m_pd3dDevice, “그림화일이름", &g_pTexture1 ) ) ) { return E_FAIL; }
코딩 InitDeviceObjects() 메소드에 정점설정을 다음과 같이 변경한다 (두 개의 삼각형으로 사각형 생성, 시계방향으로) pVertices[0].position = D3DXVECTOR3( -1.0f, 1.0f, 0.0f ); pVertices[0].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[0].tu = 0; pVertices[0].tv = 0; pVertices[1].position = D3DXVECTOR3( 1.0f, 1.0f, 0.0f ); pVertices[1].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[1].tu = 1; pVertices[1].tv = 0; pVertices[2].position = D3DXVECTOR3( 1.0f, -1.0f, 0.0f ); pVertices[2].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[2].tu = 1; pVertices[2].tv = 1; pVertices[3].position = D3DXVECTOR3( -1.0f, 1.0f, 0.0f ); pVertices[3].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[3].tu = 0; pVertices[3].tv = 0; pVertices[4].position = D3DXVECTOR3( 1.0f, -1.0f, 0.0f ); pVertices[4].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[4].tu = 1; pVertices[4].tv = 1; pVertices[5].position = D3DXVECTOR3( -1.0f, -1.0f, 0.0f ); pVertices[5].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[5].tu = 0; pVertices[5].tv = 1;
Direct 3D 코딩 프로젝트이름.cpp에 Render()에 BeginScene()함수 밑에 다음과 같이 추가한다 프로젝트이름.cpp에 RestoreDeviceObjects()메소드에 D3DUtil_InitMaterial()함수를 하얀색으로 바꾸어 준다 D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f); 프로젝트이름.cpp에 Render()에 BeginScene()함수 밑에 다음과 같이 추가한다 m_pd3dDevice->SetTexture(0, g_pTexture1); 텍스쳐 설정은 이미 RestoreDeviceObjects()에 정의되어 있다. 프로그램 종료시를 위하여 DeleteDeviceObjects()에 다음과 같은 코드를 삽입하여 텍스쳐 자원을 해제한다 SAFE_RELEASE(g_pTexture1);
Direct 3D 정점, nomal, 텍스쳐 좌표 입력방법 정점은 일반 X축과 Y축을 중심으로 뒤쪽이 Z의 증가이며 앞쪽이 Z의 감소이다 nomal은 점의 nomal벡터로서 삼각형의 수직인 방향을 나타낸다. 앞의 코드는 정면을 바라보고 있으므로 Z축의 음(-)의 방향이 nomal벡터이다 텍스쳐 좌표는 사각형을 그렸을 경우 다음과 같다 텍스쳐 좌표를 다음과 같이 하였을 경우 네개의 그림이 매핑된다. 0, 0 1, 0 0, 1 1, 1 0, 0 2, 0 0, 2 2, 2
Direct 3D 실습2 정육면체 만들기 코드 InitDeviceObjects()메소드에 다음과 같이 수정한다. 정육면체는 총 6개의 사각형이므로 12개의 삼각형을 그려야 한다. 코드 InitDeviceObjects()메소드에 다음과 같이 수정한다. if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer ( 3*2*6*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_MANAGED, &m_pVB, NULL ) ) ) return DXTRACE_ERR( "CreateVertexBuffer", hr ); Render()메소드에 다음과 같이 수정한다. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 12 );
코드 정점을 다음과 같이 수정한다. pVertices[0].position = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); pVertices[0].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[0].tu = 0; pVertices[0].tv = 0; pVertices[1].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f ); pVertices[1].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[1].tu = 1; pVertices[1].tv = 0; pVertices[2].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f ); pVertices[2].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[2].tu = 1; pVertices[2].tv = 1; pVertices[3].position = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); pVertices[3].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[3].tu = 0; pVertices[3].tv = 0; pVertices[4].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f ); pVertices[4].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[4].tu = 1; pVertices[4].tv = 1; pVertices[5].position = D3DXVECTOR3( -1.0f, -1.0f, -1.0f ); pVertices[5].normal = D3DXVECTOR3( 0.0f, 0.0f, -1.0f ); pVertices[5].tu = 0; pVertices[5].tv = 1; pVertices[6].position = D3DXVECTOR3( 1.0f, 1.0f, 1.0f ); pVertices[6].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[6].tu = 1; pVertices[6].tv = 0; pVertices[7].position = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); pVertices[7].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[7].tu = 0; pVertices[7].tv = 0; pVertices[8].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f ); pVertices[8].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[8].tu = 1; pVertices[8].tv = 1; pVertices[9].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f ); pVertices[9].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[9].tu = 1; pVertices[9].tv = 1; pVertices[10].position = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); pVertices[10].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[10].tu = 0; pVertices[10].tv = 0; pVertices[11].position = D3DXVECTOR3( -1.0f, -1.0f, 1.0f ); pVertices[11].normal = D3DXVECTOR3( 0.0f, 0.0f, 1.0f ); pVertices[11].tu = 0; pVertices[11].tv = 1; pVertices[12].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f ); pVertices[12].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[12].tu = 0; pVertices[12].tv = 0; pVertices[13].position = D3DXVECTOR3( 1.0f, 1.0f, 1.0f ); pVertices[13].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[13].tu = 1; pVertices[13].tv = 0; pVertices[14].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f ); pVertices[14].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[14].tu = 1; pVertices[14].tv = 1; pVertices[15].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f ); pVertices[15].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[15].tu = 0; pVertices[15].tv = 0; pVertices[16].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f ); pVertices[16].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[16].tu = 1; pVertices[16].tv = 1; pVertices[17].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f ); pVertices[17].normal = D3DXVECTOR3( 1.0f, 0.0f, 0.0f ); pVertices[17].tu = 0; pVertices[17].tv = 1; pVertices[18].position = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); pVertices[18].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[18].tu = 1; pVertices[18].tv = 0; pVertices[19].position = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); pVertices[19].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[19].tu = 0; pVertices[19].tv = 0; pVertices[20].position = D3DXVECTOR3( -1.0f, -1.0f, 1.0f ); pVertices[20].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[20].tu = 1; pVertices[20].tv = 1; pVertices[21].position = D3DXVECTOR3( -1.0f, -1.0f, 1.0f ); pVertices[21].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[21].tu = 1; pVertices[21].tv = 1; pVertices[22].position = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); pVertices[22].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[22].tu = 0; pVertices[22].tv = 0; pVertices[23].position = D3DXVECTOR3( -1.0f, -1.0f, -1.0f ); pVertices[23].normal = D3DXVECTOR3( -1.0f, 0.0f, 0.0f ); pVertices[23].tu = 0; pVertices[23].tv = 1; pVertices[24].position = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); pVertices[24].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[24].tu = 0; pVertices[24].tv = 0; pVertices[25].position = D3DXVECTOR3( 1.0f, 1.0f, 1.0f ); pVertices[25].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[25].tu = 1; pVertices[25].tv = 0; pVertices[26].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f ); pVertices[26].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[26].tu = 1; pVertices[26].tv = 1; pVertices[27].position = D3DXVECTOR3( -1.0f, 1.0f, 1.0f ); pVertices[27].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[27].tu = 0; pVertices[27].tv = 0; pVertices[28].position = D3DXVECTOR3( 1.0f, 1.0f, -1.0f ); pVertices[28].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[28].tu = 1; pVertices[28].tv = 1; pVertices[29].position = D3DXVECTOR3( -1.0f, 1.0f, -1.0f ); pVertices[29].normal = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); pVertices[29].tu = 0; pVertices[29].tv = 1; pVertices[30].position = D3DXVECTOR3( 1.0f, -1.0f, 1.0f ); pVertices[30].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[30].tu = 1; pVertices[30].tv = 0; pVertices[31].position = D3DXVECTOR3( -1.0f, -1.0f, 1.0f ); pVertices[31].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[31].tu = 0; pVertices[31].tv = 0; pVertices[32].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f ); pVertices[32].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[32].tu = 1; pVertices[32].tv = 1; pVertices[33].position = D3DXVECTOR3( 1.0f, -1.0f, -1.0f ); pVertices[33].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[33].tu = 1; pVertices[33].tv = 1; pVertices[34].position = D3DXVECTOR3( -1.0f, -1.0f, 1.0f ); pVertices[34].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[34].tu = 0; pVertices[34].tv = 0; pVertices[35].position = D3DXVECTOR3( -1.0f, -1.0f, -1.0f ); pVertices[35].normal = D3DXVECTOR3( 0.0f, -1.0f, 0.0f ); pVertices[35].tu = 0; pVertices[35].tv = 1;
Direct 3D 실습3 .x 파일 로드 프로젝트이름.h에 있는 CUSTOMVERTEX를 수정 struct CUSTOMVERTEX { D3DXVECTOR3 position; // vertex position D3DXVECTOR3 normal; // vertex normal float tu, tv; DWORD diffuse; }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1) 프로젝트이름.h에 CMyD3DApplication의 멤버 변수로 아래의 코드 추가 LPD3DXMESH m_pMesh; D3DMATERIAL9 *m_pMeshMaterials; DWORD m_NumMaterials; LPDIRECT3DTEXTURE9 g_pTexture1;
Direct 3D 프로젝트이름.cpp의 InitDeviceObjects()함수에 다음 코드 추가 LPD3DXBUFFER pD3DXMtrlBuffer; if(FAILED(D3DXLoadMeshFromX("c:\\DXSDK\\Samples\\Media\\tiny.x", D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, &pD3DXMtrlBuffer, &m_NumMaterials, &m_pMesh))) return FALSE; D3DXMATERIAL *d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer(); m_pMeshMaterials = new D3DMATERIAL9[m_NumMaterials]; for(unsigned long MatCount = 0 ; MatCount < m_NumMaterials ; MatCount++) { m_pMeshMaterials[MatCount] = d3dxMaterials[MatCount].MatD3D; m_pMeshMaterials[MatCount].Ambient = m_pMeshMaterials[MatCount].Diffuse; } pD3DXMtrlBuffer->Release();
Direct 3D 앞에서의 코드 아래에 다음코드 추가 RestoreDeviceObjects()함수에서 다음의 코드를 수정 if( FAILED( D3DXCreateTextureFromFile( m_pd3dDevice, "c:\\DXSDK\\Samples\\Media\\Tiny_skin.bmp", &g_pTexture1 ) ) ) { return E_FAIL; } RestoreDeviceObjects()함수에서 다음의 코드를 수정 D3DXVECTOR3 vFromPt = D3DXVECTOR3( 0.0f, 0.0f, -1000.0f ); D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 1000.0f );
Direct 3D Render()에서 다음 코드를 주석처리 하고 다음의 코드를 삽입 //m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(CUSTOMVERTEX) ); //m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); //m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ); 다음의 코드를 삽입 m_pd3dDevice->SetTexture(0, g_pTexture1); for(DWORD MatCount = 0 ; MatCount < m_NumMaterials ; MatCount++) { m_pMesh->DrawSubset(MatCount); }
Direct 3D DeleteDeviceObjects()함수에 다음코드 추가 SAFE_RELEASE(g_pTexture1); if(m_pMesh) { m_pMesh->Release(); m_pMesh = NULL; } if(m_pMeshMaterials) delete m_pMeshMaterials; m_pMeshMaterials = NULL;