This tutorial is part of a Collection: 02. DirectX 10 - Braynzar Soft Tutorials
rate up
0
rate down
1261
views
bookmark
10. Transformations

Heres a more exciting lesson on transformations! We will show you how to do translating, scaling, and rotating!

There are no files for this tutorial
This is a quick lesson on transformations. We will also show you how to draw multiple objects on the screen. Transformations in Direct3D use a 4x4 Matrix. Thats because they use 4 dimensions, 3 spacial, x, y, z, and 1 change, which is represented by the letter w. w is usually equal to a one(1) or a zero(0). I don't want to get into too much math, so if you don't know much about matrices, you should learn a little more if this gets confusing. When you want to transform an object, you take its 3D vector, v=[x, y, z], add in the w so it can be multiplied by a 4x4 Matrix, so it looks like v=[x, y, z, 1]. you set w to one because that means it will be transformed. Then you multiply v by the 4x4 Matrix which we will call M. the outcome of vM will be v'. vM=v'. [M11,M12,M13,M14] v'[x', y', z', 1]=v[x, y, z, 1] x M[M21,M22,M23,M24] [M31,M32,M33,M34] [M41,M42,M43,M44] x'=(x*M11) + (y*M21) + (z*M31) + (1*M41) y'=(x*M12) + (y*M22) + (z*M32) + (1*M42) z'=(x*M13) + (y*M23) + (z*M33) + (1*M43) Scaling Matrices will scale the size of an object in 3D space. Direct3D has functions that will compute transformations for us. the Scaling Matrix can be computed with the following method. D3DXMATRIX *D3DXMatrixScaling( D3DXMATRIX* pOut, // Pointer to recieve computed matrix FLOAT sx, // x=axis scale FLOAT sy, // y-axis scale FLOAT sz // z-axis scale ); The 4x4 scaling matrix looks like this. [S1, 0, 0, 0] S = [ 0,S2, 0, 0] [ 0, 0,S3, 0] [ 0, 0, 0, 1] Rotation Matrices are used to rotate an object in 3D space. There are 3 different matrices for rotating around each of the x, y, and z-axis's. Here are the three methods to create each of the rotation matrices, and what the 4x4 translation matrix looks like. Where r is the angle in radians. [ 1, 0, 0, 0] Rx = [ 0, cos(r),sin(r), 0] [ 0,-sin(r),cos(r), 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationX( D3DXMATRIX* pOut, // Pointer to returned matrix FLOAT Angle // Rotation angle in radians ); [cos(r), 0,-sin(r), 0] Ry = [ 0, 1, 0, 0] [sin(r), 0, cos(r), 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationY( D3DXMATRIX* pOut, // Pointer to store result in FLOAT Angle // Rotation angle in radians ); [ cos(r),sin(r), 0, 0] Rz = [-sin(r),cos(r), 0, 0] [ 0, 0, 1, 0] [ 0, 0, 0, 1] D3DXMATRIX *D3DXMatrixRotationZ( D3DXMATRIX* pOut, // Pointer to store resulting matrix in FLOAT Angle // Rotation angle in radians ); Translation Formations are used to move an object in 3D space. If you wanted to take and object positioned at [1,2,0] and move it over on the x-axis 3 units, the outcome would look like [4,2,0]. Below is how the Translation matrix looks and what the function to create it is. mx is the units translated on the x-axis, my is the units translated on the y=axis, and mz is the units translated on the z-axis. [ 1, 0, 0, 0] T = [ 0, 1, 0, 0] [ 0, 0, 1, 0] [mx,my,mz, 1] D3DXMATRIX *D3DXMatrixTranslation( D3DXMATRIX* pOut, // Pointer to matrix to store result in FLOAT x, // Units translated on the x-axis FLOAT y, // Units translated on the y-axis FLOAT z // Units translated on the z-axis ); We can combine multiple transformation matrices into one matrice. We do this by multiplying each one together. We have to do it in order to get the desired outcome. We have a scaling matrix called 'S', a rotation matrix called 'R', and a translation matrix called 'T'. our outcome is 'O'. O = S * R * T. Thats the order we must do it in. If we were to put the translation matrix first, 0 = T * S * R, our object would be rotating around where it was originally, not where it is now. It would create more of an orbit effect instead of a spinning effect. These declare the matrices and float we will be using to transform our cubes. D3DXMATRIX Rotation; D3DXMATRIX Scale; D3DXMATRIX Translation; D3DXMATRIX Transformations; float rot = 0.01f; Go down to the InitializeDirect3dApp function and you can see we have changed the position of our camera. We are still looking at the "center" of our scene, but the position of the camera has moved back and up, to give us a nice view of our transforming cubes. D3DXVECTOR3 Position( 0.0f, 10.0f, -15.0f ); The next new thing is in the initScene function, where we have added some vertices to our vertice array. There are 8 vertices here, one for each corner. Without an index buffer, we would have to declare 36 vertices, 3 for each triangle. Vertex vertices[] = { //first cube {D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXCOLOR (1.0f, 0.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, +1.0f, -1.0f), D3DXCOLOR (0.0f, 1.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, +1.0f, -1.0f), D3DXCOLOR (0.0f, 0.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, -1.0f, -1.0f), D3DXCOLOR (1.0f, 1.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, -1.0f, +1.0f), D3DXCOLOR (0.0f, 1.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, +1.0f, +1.0f), D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, +1.0f, +1.0f), D3DXCOLOR (1.0f, 0.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, -1.0f, +1.0f), D3DXCOLOR (1.0f, 0.0f, 0.0f, 1.0f)}, }; Next we need to update our vertex buffer description and tell it the new size of our vertex buffer. bd.ByteWidth = sizeof( Vertex ) * 8; More indices. DWORD indices[] = { // front face 0, 1, 2, 0, 2, 3, // back face 4, 6, 5, 4, 7, 6, // left face 4, 5, 1, 4, 1, 0, // right face 3, 2, 6, 3, 6, 7, // top face 1, 5, 6, 1, 6, 2, // bottom face 4, 0, 3, 4, 3, 7 }; Update the indice buffer description to hold all the indices we just defined. ibd.ByteWidth = sizeof(DWORD) * 12 * 3; Now we can jump down to the drawScene function, Where we will be doing the transformations. First line we have here is declaring and initializing the vector our cubes will spin around. We have set the second parameter to 1.0f because that is the Y axis, which is the axis we will be spinning around. D3DXVECTOR3 rotaxis(0.0f, 1.0f, 0.0f); Now we create the rotation matrix. The first parameter here is the returned rotation matrix. The second is a pointer to our vector which describes the axis we will be spinning around. The third is the angle we will be spinning in radians. D3DXMatrixRotationAxis(&Rotation, &rotaxis, rot); Now we define our Translation matrix. The first parameter is the returned translation matrix. The second, third and fourth parameters are the position( x, y, and z) we will be translating to. D3DXMatrixTranslation( &Translation, 0.0f, 0.0f, 4.0f ); Now we put the rotation and translation together to create our transformations matrix. Remember that the order in which you multiply matrices changes the outcome. For example, what we are doing here is translating, THEN rotating, creating an "orbit" effect. If we were to rotate, THEN translate, we would just be spinning in one spot, which would be the spot we translated to. The next line is just adding .0005 to the rot variable to keep the cubes spinning. Transformations = Translation * Rotation; rot += .0005f; Now we set the WVP matrix by multiplying the World, Transformations, View, and Projection matrices. The line after this one in the code will set the World matrix in the effect file. WVP = World * Transformations * View * Projection; The first line here is creating a new Rotation matrix, basically the same as the one above but in revers (-rot). The line after that is creating our scaling matrix, the first parameter is the returned Scale matrix, the next three are the x, y, and z axis we want to scale. After that we set the Transformations matrix again, by multiplying the rotation and scale matrices, Then we set the World matrix again, and again reset the World matrix in the effect file to the World matrix we just defined. After that we draw another cube, this one will follow the transformations created after the last World matrix was set. Notice we can just use the same vertex and index buffer as the first cube. D3DXMatrixRotationAxis(&Rotation, &rotaxis, -rot); D3DXMatrixScaling( &Scale, 1.3f, 1.3f, 1.3f ); Transformations = Rotation * Scale; WVP = World * Transformations * View * Projection; fxWVPvar->SetMatrix((float*)&WVP); //draw second cube for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } There it is! We can now rotate, translate, scale, and draw multiple objects in our scene! From now on we will be doing more fun things, such as lighting, textures, blending, and other fun things! Here's the final code: main.cpp #include <Windows.h> #include <d3d10.h> #include <d3dx10.h> #include <string> #pragma comment(lib, "D3D10.lib") #pragma comment(lib, "d3dx10d.lib") LPCTSTR WndClassName = L"firstwindow"; HWND hwnd = NULL; const int Width = 800; const int Height = 600; bool InitializeWindow(HINSTANCE hInstance, int ShowWnd, int width, int height, bool windowed); HRESULT hr; ID3D10Device* d3dDevice; IDXGISwapChain* SwapChain; ID3D10RenderTargetView* RenderTargetView; ID3D10Effect* FX; ID3D10InputLayout* VertexLayout; ID3D10Buffer* VertexBuffer; ID3D10Buffer* IndexBuffer; ID3D10EffectTechnique* Technique; ID3D10DepthStencilView* DepthStencilView; ID3D10Texture2D* DepthStencilBuffer; ID3D10EffectMatrixVariable* fxWVPvar; D3DXMATRIX WVP; D3DXMATRIX World; D3DXMATRIX View; D3DXMATRIX Projection; D3DXVECTOR3 Position; D3DXVECTOR3 Target; D3DXVECTOR3 Up; ////////////////////////////////new/////////////////////////////////////////////////// D3DXMATRIX Rotation; D3DXMATRIX Scale; D3DXMATRIX Translation; D3DXMATRIX Transformations; float rot = 0.01f; ////////////////////////////////new/////////////////////////////////////////////////// bool InitializeDirect3dApp(HINSTANCE hInstance); bool InitScene(); void DrawScene(); bool ReleaseObjects(); int messageloop(); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); struct Vertex { D3DXVECTOR3 pos; D3DXCOLOR color; }; int WINAPI WinMain(HINSTANCE hInstance, //Main windows function HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true)) { MessageBox(0, L"Window Initialization - Failed", L"Error", MB_OK); return 0; } if(!InitializeDirect3dApp(hInstance)) { MessageBox(0, L"Direct3D Initialization - Failed", L"Error", MB_OK); return 0; } if(!InitScene()) { MessageBox(0, L"Scene Initialization - Failed", L"Error", MB_OK); return 0; } messageloop(); if(!ReleaseObjects()) { MessageBox(0, L"Object Releasing - Failed", L"Error", MB_OK); return 0; } return 0; } bool InitializeWindow(HINSTANCE hInstance, int ShowWnd, int width, int height, bool windowed) { typedef struct _WNDCLASS { UINT cbSize; UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HANDLE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCTSTR lpszMenuName; LPCTSTR lpszClassName; } WNDCLASS; WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = NULL; wc.cbWndExtra = NULL; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2); wc.lpszMenuName = NULL; wc.lpszClassName = WndClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx(&wc)) { MessageBox(NULL, L"Error registering class", L"Error", MB_OK | MB_ICONERROR); return 1; } hwnd = CreateWindowEx( NULL, WndClassName, L"Window Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, hInstance, NULL ); if (!hwnd) { MessageBox(NULL, L"Error creating window", L"Error", MB_OK | MB_ICONERROR); return 1; } ShowWindow(hwnd, ShowWnd); UpdateWindow(hwnd); return true; } bool InitializeDirect3dApp(HINSTANCE hInstance) { UINT createDeviceFlags = 0; D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE, }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC scd; scd.BufferDesc.Width = Width; scd.BufferDesc.Height = Height; scd.BufferDesc.RefreshRate.Numerator = 60; scd.BufferDesc.RefreshRate.Denominator = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //no multisampling scd.SampleDesc.Count = 1; scd.SampleDesc.Quality = 0; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 1; scd.OutputWindow = hwnd; scd.Windowed = true; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Flags = 0; D3D10CreateDeviceAndSwapChain(0, D3D10_DRIVER_TYPE_HARDWARE, 0, 0, D3D10_SDK_VERSION, &scd, &SwapChain, &d3dDevice); ID3D10Texture2D* backBuffer; SwapChain->GetBuffer(0, _uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)); d3dDevice->CreateRenderTargetView(backBuffer, 0, &RenderTargetView); backBuffer->Release(); D3D10_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.Width = Width; depthStencilDesc.Height = Height; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilDesc.SampleDesc.Count = 1; depthStencilDesc.SampleDesc.Quality = 0; depthStencilDesc.Usage = D3D10_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; d3dDevice->CreateTexture2D(&depthStencilDesc, NULL, &DepthStencilBuffer); d3dDevice->CreateDepthStencilView(DepthStencilBuffer, NULL, &DepthStencilView); d3dDevice->OMSetRenderTargets(1, &RenderTargetView, DepthStencilView); // Setup the viewport D3D10_VIEWPORT vp; vp.Width = Width; vp.Height = Height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; d3dDevice->RSSetViewports( 1, &vp ); D3DXMatrixIdentity( &World ); ////////////////////new////////////////////////////////////////////////////////////////////// Position = D3DXVECTOR3( 0.0f, 3.0f, -7.0f ); ////////////////////new////////////////////////////////////////////////////////////////////// Target = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); Up = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &View, &Position, &Target, &Up ); return true; } bool InitScene() { ////////////////////new////////////////////////////////////////////////////////////////////// Vertex vertices[] = { //first cube {D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXCOLOR (1.0f, 0.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, +1.0f, -1.0f), D3DXCOLOR (0.0f, 1.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, +1.0f, -1.0f), D3DXCOLOR (0.0f, 0.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, -1.0f, -1.0f), D3DXCOLOR (1.0f, 1.0f, 0.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, -1.0f, +1.0f), D3DXCOLOR (0.0f, 1.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(-1.0f, +1.0f, +1.0f), D3DXCOLOR (1.0f, 1.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, +1.0f, +1.0f), D3DXCOLOR (1.0f, 0.0f, 1.0f, 1.0f)}, {D3DXVECTOR3(+1.0f, -1.0f, +1.0f), D3DXCOLOR (1.0f, 0.0f, 0.0f, 1.0f)}, }; ////////////////////new////////////////////////////////////////////////////////////////////// D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_IMMUTABLE; ////////////////////new////////////////////////////////////////////////////////////////////// bd.ByteWidth = sizeof( Vertex ) * 8; ////////////////////new////////////////////////////////////////////////////////////////////// bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; d3dDevice->CreateBuffer( &bd, &InitData, &VertexBuffer ); ////////////////////new////////////////////////////////////////////////////////////////////// DWORD indices[] = { // front face 0, 1, 2, 0, 2, 3, // back face 4, 6, 5, 4, 7, 6, // left face 4, 5, 1, 4, 1, 0, // right face 3, 2, 6, 3, 6, 7, // top face 1, 5, 6, 1, 6, 2, // bottom face 4, 0, 3, 4, 3, 7 }; ////////////////////new////////////////////////////////////////////////////////////////////// D3D10_BUFFER_DESC ibd; ibd.Usage = D3D10_USAGE_IMMUTABLE; ////////////////////new////////////////////////////////////////////////////////////////////// ibd.ByteWidth = sizeof(DWORD) * 12 * 3; ////////////////////new////////////////////////////////////////////////////////////////////// ibd.BindFlags = D3D10_BIND_INDEX_BUFFER; ibd.CPUAccessFlags = 0; ibd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = indices; d3dDevice->CreateBuffer(&ibd, &iinitData, &IndexBuffer); UINT stride = sizeof( Vertex ); UINT offset = 0; d3dDevice->IASetVertexBuffers( 0, 1, &VertexBuffer, &stride, &offset ); d3dDevice->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); D3D10_INPUT_ELEMENT_DESC layout[] = { {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0} }; ID3D10Blob* compilationErrors = 0; HRESULT hr = 0; hr = D3DX10CreateEffectFromFile( L"vertex.fx", NULL, NULL, "fx_4_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, d3dDevice, NULL, NULL, &FX, &compilationErrors, NULL ); if(FAILED(hr)) { MessageBoxA(0, (char*)compilationErrors->GetBufferPointer(), 0, 0); compilationErrors->Release(); return false; } Technique = FX->GetTechniqueByName( "Tech" ); fxWVPvar = FX->GetVariableByName("WVP")->AsMatrix(); D3D10_PASS_DESC PassDesc; Technique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); d3dDevice->CreateInputLayout( layout, 2, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &VertexLayout ); d3dDevice->IASetInputLayout( VertexLayout ); d3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); return true; } bool ReleaseObjects() { if( d3dDevice ) d3dDevice->ClearState(); if( VertexBuffer ) VertexBuffer->Release(); if( IndexBuffer ) IndexBuffer->Release(); if( VertexLayout ) VertexLayout->Release(); if( FX ) FX->Release(); if( RenderTargetView ) RenderTargetView->Release(); if( SwapChain ) SwapChain->Release(); if( d3dDevice ) d3dDevice->Release(); return true; } void DrawScene() { //Draw Scene Here D3DXCOLOR bgColor( 0.0f, 0.0f, 0.0f, 1.0f); d3dDevice->ClearRenderTargetView( RenderTargetView, bgColor ); d3dDevice->ClearDepthStencilView(DepthStencilView, D3D10_CLEAR_DEPTH|D3D10_CLEAR_STENCIL, 1.0f, 0); D3DXMatrixPerspectiveFovLH(&Projection, 0.4f*3.14f, Width/Height, 1.0f, 1000.0f); ////////////////////new////////////////////////////////////////////////////////////////////// D3DXVECTOR3 rotaxis(0.0f, 1.0f, 0.0f); D3DXMatrixRotationAxis(&Rotation, &rotaxis, rot); D3DXMatrixTranslation( &Translation, 0.0f, 0.0f, 4.0f ); Transformations =Translation * Rotation; rot += .0005f; WVP = World * Transformations * View * Projection; ////////////////////new////////////////////////////////////////////////////////////////////// fxWVPvar->SetMatrix((float*)&WVP); D3D10_TECHNIQUE_DESC techDesc; Technique->GetDesc( &techDesc ); //draw first cube for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } ////////////////////new////////////////////////////////////////////////////////////////////// D3DXMatrixRotationAxis(&Rotation, &rotaxis, -rot); D3DXMatrixScaling( &Scale, 1.3f, 1.3f, 1.3f ); Transformations = Rotation * Scale; WVP = World * Transformations * View * Projection; fxWVPvar->SetMatrix((float*)&WVP); //draw second cube for( UINT p = 0; p < techDesc.Passes; ++p ) { Technique->GetPassByIndex( p )->Apply( 0 ); d3dDevice->DrawIndexed(36, 0, 0); } ////////////////////new////////////////////////////////////////////////////////////////////// SwapChain->Present( 0, 0 ); } int messageloop(){ MSG msg; ZeroMemory(&msg, sizeof(MSG)); while(true) { BOOL PeekMessageL( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg ); if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else{ // run game code DrawScene(); } } return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_KEYDOWN: if( wParam == VK_ESCAPE ){ if(MessageBox(0, L"Are you sure you want to exit?", L"Really?", MB_YESNO | MB_ICONQUESTION) == IDYES) DestroyWindow(hwnd); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, msg, wParam, lParam); } vertex.fx cbuffer cbPerObject { float4x4 WVP; }; struct VS_OUTPUT //output structure for vertex shader { float4 Pos : SV_POSITION; float4 Color : COLOR0; }; // Vertex Shader VS_OUTPUT VS(float4 inPos : POSITION, float4 inColor : COLOR) { VS_OUTPUT output = (VS_OUTPUT)0; output.Pos = mul(inPos, WVP); output.Color = inColor; return output; //send color and position to pixel shader } // Pixel Shader float4 PS(VS_OUTPUT input) : SV_Target { return input.Color; // Set the color of the pixel to what we defined for the vertex. } technique10 Tech { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }