这个例子是在之前的例子基础上 ,把之前d3dx10math数学库换成了最新的d3dxmath。优点就不说了。先上效果图
全部代码。以及效果文件
文件结构
全部代码:
按照上图的文件顺序
#pragma once #include <D3DX10math.h> #include <xnamath.h> class XCamera { public: XCamera() { m_positionX = 0.0f; m_positionY = 0.0f; m_positionZ = 0.0f; m_rotationX = 0.0f; m_rotationY = 0.0f; m_rotationZ = 0.0f; } void setPosition(float x,float y,float z) { m_positionX = x; m_positionY = y; m_positionZ = z; } void setRotation(float x,float y,float z) { m_rotationX = x; m_rotationY = y; m_rotationZ = z; } D3DXVECTOR3 getPosition() { return D3DXVECTOR3(m_positionX, m_positionY, m_positionZ); } D3DXVECTOR3 getRotation() { return D3DXVECTOR3(m_rotationX, m_rotationY, m_rotationZ); } void render(XMMATRIX& viewMatrix) { XMVECTOR up, position, lookAt; float yaw, pitch, roll; XMMATRIX rotationMatrix; // 设置up向量为(0,1,0). up=XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); // 设置摄像机的位置. position=XMVectorSet(m_positionX, m_positionY,m_positionZ, 0.0f); // 设置摄像机lookat的方向. //lookAt=XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); lookAt=XMVector3Normalize(position); lookAt=lookAt*(-1); // 得到弧度单位的欧拉旋转 yaw (Y axis), pitch (X axis), 以及 roll (Z axis) . // 1 = PI/180 = 0.0174532925 pitch = m_rotationX * 0.0174532925f; yaw = m_rotationY * 0.0174532925f; roll = m_rotationZ * 0.0174532925f; // 得到旋转矩阵. rotationMatrix=XMMatrixRotationRollPitchYaw(pitch,yaw,roll); // 变换lookat和up向量,一般view能够在原点被正确旋转. lookAt=XMVector3TransformCoord(lookAt,rotationMatrix); up=XMVector3TransformCoord(up,rotationMatrix); // 平移旋转后的摄像机位置. lookAt = position + lookAt; // 创建观察矩阵. viewMatrix=XMMatrixLookAtLH( position, lookAt, up); } void getViewMatrix(XMMATRIX& viewMatrix) { render(viewMatrix); } private: float m_positionX, m_positionY, m_positionZ;//摄像机在世界坐标系中的位置 float m_rotationX, m_rotationY, m_rotationZ;//摄像机的欧拉旋转角度 };
#pragma once #pragma comment(lib, "dxgi.lib") #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "d3dx11.lib") #pragma comment(lib, "d3dx10.lib") #include <dxgi.h> #include <d3dcommon.h> #include <d3d11.h> #include <d3dx11.h> #include <d3dcompiler.h> #include <d3dx10math.h> #include <xnamath.h> XMMATRIX m_projectionMatrix; //投影矩阵 XMMATRIX m_worldMatrix;//世界坐标系矩阵 XMMATRIX m_orthoMatrix;//正交投影矩阵 class XD3Device { public: XD3Device(); //3D设备所有初始化 bool init(int, int, bool, HWND, bool, float, float); //关闭设备 void close(); //开始渲染设备 void begin(float, float, float, float); //显示到前景 void end(); public: bool m_vsync_enabled; //是否启用垂直同步 IDXGISwapChain* m_swapChain; //交换链对象 ID3D11Device* m_device; //设备对象 ID3D11DeviceContext* m_deviceContext; //设备上下文对象 ID3D11RenderTargetView* m_renderTargetView; //渲染目标视图 ID3D11Texture2D* m_depthStencilBuffer; //深度模板缓冲 ID3D11DepthStencilState* m_depthStencilState; //深度磨成状态 ID3D11DepthStencilView* m_depthStencilView; //深度目标视图 ID3D11RasterizerState* m_rasterState; //光栅化状态 public: void getWordMatrix(XMMATRIX& world){world=m_worldMatrix;} void getProjMatrix(XMMATRIX& proj){proj=m_projectionMatrix;} }; void XD3Device::begin(float red, float green, float blue, float alpha) { float color[]={red,green,blue,alpha}; //清除后缓冲. m_deviceContext->ClearRenderTargetView(m_renderTargetView, color); //清除深度缓冲. m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); } void XD3Device::end() { //渲染完成后,把后缓冲内容present到前缓冲 if(m_vsync_enabled) { // 锁定屏幕刷新率. m_swapChain->Present(1, 0); } else { // 尽可能快的present后缓冲. m_swapChain->Present(0, 0); } } void XD3Device::close() { // 释放交换链资源前,先设置为窗口模式,否则可能会产生异常. if(m_swapChain) { m_swapChain->SetFullscreenState(false, NULL); } if(m_rasterState) { m_rasterState->Release(); m_rasterState = 0; } if(m_depthStencilView) { m_depthStencilView->Release(); m_depthStencilView = 0; } if(m_depthStencilState) { m_depthStencilState->Release(); m_depthStencilState = 0; } if(m_depthStencilBuffer) { m_depthStencilBuffer->Release(); m_depthStencilBuffer = 0; } if(m_renderTargetView) { m_renderTargetView->Release(); m_renderTargetView = 0; } if(m_deviceContext) { m_deviceContext->Release(); m_deviceContext = 0; } if(m_device) { m_device->Release(); m_device = 0; } if(m_swapChain) { m_swapChain->Release(); m_swapChain = 0; } } XD3Device::XD3Device() { m_swapChain = 0; m_device = 0; m_deviceContext = 0; m_renderTargetView = 0; m_depthStencilBuffer = 0; m_depthStencilState = 0; m_depthStencilView = 0; m_rasterState = 0; } //Initialize函数包含完成D3D设置的所有代码。 bool XD3Device::init(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear) { HRESULT result; //IDXGIFactory* factory; //IDXGIAdapter* adapter; //IDXGIOutput* adapterOutput; //unsigned int numModes, stringLength; //DXGI_MODE_DESC* displayModeList; //DXGI_ADAPTER_DESC adapterDesc; //int error; DXGI_SWAP_CHAIN_DESC swapChainDesc; //D3D_FEATURE_LEVEL featureLevel; ID3D11Texture2D* backBufferPtr; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; D3D11_VIEWPORT viewport; float fieldOfView, screenAspect; // 保存垂直同步设置 m_vsync_enabled = vsync; // 初始化交换链描述 ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); //MessageBox(hwnd, L"Could 2", L"Error", MB_OK); // 用1个后缓冲 swapChainDesc.BufferCount = 1; //帧缓冲的大小和应用程序窗口大小相等. swapChainDesc.BufferDesc.Width = screenWidth; swapChainDesc.BufferDesc.Height = screenHeight; // 后缓冲的surface的格式为DXGI_FORMAT_R8G8B8A8_UNORM. // surface的每个像素用4个无符号的8bit[映射到0-1]来表示。NORM表示归一化。 swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 如果使用垂直同步,设置后缓冲的刷新率。. //刷新率就是一秒钟把后缓冲内容在屏幕上画出的次数。 //如果开启垂直同步,则锁定刷新率,则fps是固定的 if(m_vsync_enabled) { swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } else { swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; } // 设置后缓冲的用途 // 我们的渲染目标缓冲为后缓冲。 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 后缓冲输出的窗口句柄. swapChainDesc.OutputWindow = hwnd; // 不使用多重采样 swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; // 设置全屏或者窗口模式. if(fullscreen) { swapChainDesc.Windowed = false; } else { swapChainDesc.Windowed = true; } //MessageBox(hwnd, L"Could 1", L"Error", MB_OK); // 设定扫描线ordering以及缩放为unspecified. swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // 后缓冲内容呈现到屏幕后,放弃其内容 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //不设置标志 swapChainDesc.Flags = 0; // 设置feature level为D3D11 // 如果显卡不支持D3D11,我们能够通过设置这个参数,使用D3D10,或者9. //featureLevel = D3D_FEATURE_LEVEL_10_1; D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); // 创建交换链,设备以及设备上下文. result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext); //MessageBox(hwnd, L"Could 1", L"Error", MB_OK); if(FAILED(result)) { return false; } // 得到交换链中的后缓冲指针. result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr); if(FAILED(result)) { return false; } // 用后缓冲创建渲染目标视图. result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView); if(FAILED(result)) { return false; } //释放后缓冲.(引用计数减1) backBufferPtr->Release(); backBufferPtr = 0; // 初始化深度缓冲描述. ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); //设置深度缓冲描述 depthBufferDesc.Width = screenWidth; depthBufferDesc.Height = screenHeight; depthBufferDesc.MipLevels = 1;//对于深度缓冲为1 depthBufferDesc.ArraySize = 1;//对于深度缓冲为1,对于纹理,这2个参数有更多用途 depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.SampleDesc.Quality = 0; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthBufferDesc.CPUAccessFlags = 0; depthBufferDesc.MiscFlags = 0; // 创建深度缓冲. result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); if(FAILED(result)) { return false; } // 初始化深度模版状态描述. ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); // 设置深度模版状态描述. depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;//D3D11_DEPTH_WRITE_MASK_ZERO禁止写深度缓冲 depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; // 对于front face 像素使用的模版操作操作. depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 对于back face像素使用的模版操作模式. depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // 创建深度模版状态,使其生效 result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); if(FAILED(result)) { return false; } // 设置深度模版状态. m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); // 初始化深度模版视图. ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); // 设置深度模版视图描述. depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; // 创建深度模版视图. result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); if(FAILED(result)) { return false; } // 绑定渲染目标视图和深度缓冲到渲染管线. m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); // 设置光栅化描述,指定多边形如何被渲染. rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; // 创建光栅化状态 result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState); if(FAILED(result)) { return false; } //设置光栅化状态,使其生效 m_deviceContext->RSSetState(m_rasterState); // 设置视口,显示全部后缓冲内容 viewport.Width = (float)screenWidth; viewport.Height = (float)screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; // 创建视口 m_deviceContext->RSSetViewports(1, &viewport); // 设置透视投影矩阵 fieldOfView = (float)D3DX_PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; // 创建透视投影矩阵. m_projectionMatrix=XMMatrixPerspectiveFovLH( fieldOfView, screenAspect, screenNear, screenDepth); //初始化world矩阵为单位矩阵. //该矩阵实现局部坐标到世界坐标的转换 m_worldMatrix=XMMatrixIdentity(); // 创建正交投影矩阵,主要用来实施2D渲染. m_orthoMatrix=XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); return true; }
#pragma once #include <windows.h> #include "XD3Device.h" #include "XCamera.h" #include "XModel.h" #include "XShader.h" ///////////// // GLOBALS // ///////////// const bool FULL_SCREEN = false; //是否全屏 const bool VSYNC_ENABLED = true; //是否垂直同步 const float SCREEN_DEPTH = 1000.0f; //深度,远点 const float SCREEN_NEAR = 0.1f; //深度,近点 class XGraphics { public: XGraphics():x_d3d(0),x_camera(0),x_model(0),x_shader(0){} bool init(int, int, HWND); //初始化渲染设备 void close(); bool frame(); private: bool render(); private: XD3Device *x_d3d;//3D设备 XCamera *x_camera;//摄像机 XModel *x_model;//模型 XShader *x_shader;//渲染器 HWND hwnd; }; bool XGraphics:: init(int screenWidth, int screenHeight, HWND hwnd) { //先清空 close(); //初始化设备 this->hwnd=hwnd; x_d3d=new XD3Device; bool hr=x_d3d->init(screenWidth,screenHeight,VSYNC_ENABLED,hwnd,FULL_SCREEN,SCREEN_DEPTH,SCREEN_NEAR); if(!hr) { MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK); return false; } //初始化摄像机 x_camera=new XCamera; x_camera->setPosition(3.0f,3.0f,-10.0f); //初始化模型 x_model=new XModel; x_model->init(x_d3d->m_device); //初始化Shader x_shader=new XShader; x_shader->init(x_d3d->m_device,hwnd); return true; } void XGraphics::close() { if(x_d3d) { x_d3d->close(); delete x_d3d; x_d3d=0; } if(x_camera) { delete x_camera; x_camera=NULL; } if(x_shader) { x_shader->close(); delete x_shader; x_shader=NULL; } if(x_model) { x_model->close(); delete x_model; x_model=NULL; } } bool XGraphics::frame() { bool hr=render(); return hr; } bool XGraphics::render() { XMMATRIX viewMatrix, projectionMatrix, worldMatrix; x_d3d->begin(0.0f,0.0f,0.5f,1.0f);//蓝色 //世界矩阵 x_d3d->getWordMatrix(worldMatrix); //观察矩阵 x_camera->getViewMatrix(viewMatrix); //投影矩阵 x_d3d->getProjMatrix(projectionMatrix); //模型加入管线 x_model->render(x_d3d->m_deviceContext); //开始渲染 x_shader->render(x_d3d->m_deviceContext,x_model->m_indexCount,worldMatrix,viewMatrix,projectionMatrix); //结束 x_d3d->end(); return true; }
#pragma once class XInput { public: void init(); void keyDown(unsigned int); void keyUp(unsigned int); bool isKeyDown(unsigned int); private: bool x_keys[256]; }; void XInput::init() { int i; // 初始所有的键都是非按下状态. for(i=0; i<256; i++) { x_keys[i] = false; } return; } void XInput::keyDown(unsigned int input) { //键被按下. x_keys[input] = true; return; } void XInput::keyUp(unsigned int input) { //键被按下. x_keys[input] = false; return; } bool XInput::isKeyDown(unsigned int key) { // 判断键是否被按下? return x_keys[key]; }
#pragma once #include <D3D11.h> //定义一些常用颜色 const XMFLOAT4 WHITE(1.0f, 1.0f, 1.0f, 1.0f); const XMFLOAT4 BLACK(0.0f, 0.0f, 0.0f, 1.0f); const XMFLOAT4 RED(1.0f, 0.0f, 0.0f, 1.0f); const XMFLOAT4 GREEN(0.0f, 1.0f, 0.0f, 1.0f); const XMFLOAT4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); const XMFLOAT4 YELLOW(1.0f, 1.0f, 0.0f, 1.0f); const XMFLOAT4 CYAN(0.0f, 1.0f, 1.0f, 1.0f); //蓝绿色 const XMFLOAT4 MAGENTA(1.0f, 0.0f, 1.0f, 1.0f); //洋红色 const XMFLOAT4 BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f); const XMFLOAT4 LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f, 1.0f); const XMFLOAT4 DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f, 1.0f); const XMFLOAT4 DARKBROWN(0.45f, 0.39f, 0.34f, 1.0f); class XModel { private:struct SimpleVertex { XMFLOAT3 Pos; XMFLOAT4 Color; }; public://顶点缓冲和顶点索引缓冲 ID3D11Buffer *m_vertexBuffer, *m_indexBuffer; int m_vertexCount, m_indexCount; public: XModel():m_vertexCount(0),m_indexCount(0){}; virtual void init(ID3D11Device*); virtual void close(); virtual void render(ID3D11DeviceContext*); }; void XModel::init(ID3D11Device* device) { unsigned long* indices; D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; D3D11_SUBRESOURCE_DATA vertexData, indexData; //首先,我们创建2个临时缓冲存放顶点和索引数据,以便后面使用。. // 设置顶点缓冲大小为3,一个三角形. m_vertexCount = 8; // 设置索引缓冲大小. m_indexCount = 36; //6面*2三角形*3个点 // 创建顶点临时缓冲. SimpleVertex vertices[] = { {XMFLOAT3(-1.0f, -1.0f, -1.0f),WHITE}, {XMFLOAT3(-1.0f, 1.0f, -1.0f),BLACK}, {XMFLOAT3(1.0f, 1.0f, -1.0f),RED}, {XMFLOAT3(1.0f, -1.0f, -1.0f),GREEN}, {XMFLOAT3(-1.0f, -1.0f, 1.0f),BLUE}, {XMFLOAT3(-1.0f, 1.0f, 1.0f),YELLOW}, {XMFLOAT3(1.0f, 1.0f, 1.0f),CYAN}, {XMFLOAT3(1.0f, -1.0f, 1.0f),MAGENTA}, }; // 创建索引缓冲. indices = new unsigned long[m_indexCount]; // 设置索引缓冲数据. indices[0] = 0; // 前面 indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; indices[6] = 4; // 后面 indices[7] = 6; indices[8] = 5; indices[9] = 4; indices[10] = 7; indices[11] = 6; indices[12] = 4; // 左面 indices[13] = 5; indices[14] = 1; indices[15] = 4; indices[16] = 1; indices[17] = 0; indices[18] = 3; //右面 indices[19] = 2; indices[20] = 6; indices[21] = 3; indices[22] = 6; indices[23] = 7; indices[24] = 1; // 上面 indices[25] = 5; indices[26] = 6; indices[27] = 1; indices[28] = 6; indices[29] = 2; indices[30] = 4; // 下面 indices[31] = 0; indices[32] = 3; indices[33] = 4; indices[34] = 3; indices[35] = 7; // 设置顶点缓冲描述 vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(SimpleVertex) * m_vertexCount; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; // 指向保存顶点数据的临时缓冲. vertexData.pSysMem = vertices; vertexData.SysMemPitch = 0; vertexData.SysMemSlicePitch = 0; // 创建顶点缓冲. device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); // 设置索引缓冲描述. indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; indexBufferDesc.StructureByteStride = 0; // 指向存临时索引缓冲. indexData.pSysMem = indices; indexData.SysMemPitch = 0; indexData.SysMemSlicePitch = 0; // 创建索引缓冲. device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); delete [] indices; indices = 0; } void XModel::close() { // 释放顶点缓冲. if(m_indexBuffer) { m_indexBuffer->Release(); m_indexBuffer = 0; } // 释放索引缓冲 if(m_vertexBuffer) { m_vertexBuffer->Release(); m_vertexBuffer = 0; } } void XModel::render(ID3D11DeviceContext* deviceContext) { unsigned int stride; unsigned int offset; // 设置顶点缓冲跨度和偏移. stride = sizeof(SimpleVertex); offset = 0; //在input assemberl阶段绑定顶点缓冲,以便能够被渲染 deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset); //在input assemberl阶段绑定索引缓冲,以便能够被渲染 deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); // 设置体元语义,渲染三角形列表. deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); }
#pragma once #include <d3d11.h> #include <d3dx11.h> #include <d3dcompiler.h> #include <xnamath.h> #include <fstream> using namespace std; //常量缓冲区 struct ConstantBuffer { XMMATRIX mWorld; XMMATRIX mView; XMMATRIX mProjection; }; class XShader { public: XShader(); HRESULT init(ID3D11Device*, HWND);//初始化 void close(); //关闭 HRESULT render(ID3D11DeviceContext* , int , XMMATRIX& , XMMATRIX &, XMMATRIX &);//渲染 private: HRESULT InitializeShader(ID3D11Device*, HWND, WCHAR*); void ShutdownShader(); void OutputShaderErrorMessage(ID3D10Blob*, HWND, WCHAR*); HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut ); HRESULT SetShaderParameters(ID3D11DeviceContext*, XMMATRIX&, XMMATRIX&, XMMATRIX&); void RenderShader(ID3D11DeviceContext*, int); ID3D11VertexShader* m_vertexShader; ID3D11PixelShader* m_pixelShader; ID3D11InputLayout* m_layout; ID3D11Buffer* m_matrixBuffer; }; XShader::XShader() { m_vertexShader = 0; m_pixelShader = 0; m_layout = 0; m_matrixBuffer = 0; } HRESULT XShader::init(ID3D11Device* device, HWND hwnd) { HRESULT result; // 初始化vs 和ps. result = InitializeShader(device, hwnd, L"shader.fx"); return result; } void XShader::close() { // 释放shader资源. ShutdownShader(); return; } HRESULT XShader::render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX &worldMatrix, XMMATRIX& viewMatrix, XMMATRIX& projectionMatrix) { // 设置shader常量缓冲区 SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix); // 用shader渲染指定缓冲顶点 RenderShader(deviceContext, indexCount); return S_OK; } HRESULT XShader::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut ) { HRESULT hr = S_OK; DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3DCOMPILE_DEBUG; #endif ID3DBlob* pErrorBlob; hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel, dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL ); if( FAILED(hr) ) { if( pErrorBlob != NULL ) OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() ); if( pErrorBlob ) pErrorBlob->Release(); return hr; } if( pErrorBlob ) pErrorBlob->Release(); return S_OK; } HRESULT XShader::InitializeShader(ID3D11Device* device, HWND hwnd, WCHAR* Filename) { HRESULT hr=S_OK; // Compile the vertex shader ID3DBlob* pVSBlob = NULL; hr = CompileShaderFromFile( Filename, "VS", "vs_4_0", &pVSBlob ); if( FAILED( hr ) ) { MessageBox( NULL, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the vertex shader hr = device->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_vertexShader ); if( FAILED( hr ) ) { pVSBlob->Release(); return hr; } // Compile the pixel shader ID3DBlob* pPSBlob = NULL; hr = CompileShaderFromFile( Filename, "PS", "ps_4_0", &pPSBlob ); if( FAILED( hr ) ) { MessageBox( NULL, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the pixel shader hr = device->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pixelShader ); pPSBlob->Release(); if( FAILED( hr ) ) return hr; // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = device->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_layout ); pVSBlob->Release(); if( FAILED( hr ) ) return hr; // Create the constant buffer D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = device->CreateBuffer( &bd, NULL, &m_matrixBuffer ); if( FAILED( hr ) ) return hr; return S_OK; } void XShader::ShutdownShader() { // 释放常量缓冲 if(m_matrixBuffer) { m_matrixBuffer->Release(); m_matrixBuffer = 0; } //释放顶点布局 if(m_layout) { m_layout->Release(); m_layout = 0; } // 释放ps . if(m_pixelShader) { m_pixelShader->Release(); m_pixelShader = 0; } // 释放vs if(m_vertexShader) { m_vertexShader->Release(); m_vertexShader = 0; } return; } void XShader::OutputShaderErrorMessage(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename) { char* compileErrors; unsigned long bufferSize, i; ofstream fout; // 得到错误信息buffer指针. compileErrors = (char*)(errorMessage->GetBufferPointer()); // 得到buffer的长度. bufferSize = errorMessage->GetBufferSize(); // 打开一个文件写错误信息. fout.open("shader-error.txt"); // 输出错误信心. for(i=0; i<bufferSize; i++) { fout << compileErrors[i]; } // 关闭文件 fout.close(); // 释放错误消息. errorMessage->Release(); errorMessage = 0; //弹出错误提示. MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK); return; } HRESULT XShader::SetShaderParameters(ID3D11DeviceContext* deviceContext, XMMATRIX &worldMatrix, XMMATRIX &viewMatrix, XMMATRIX &projectionMatrix) { // // Update variables // ConstantBuffer cb; cb.mWorld = XMMatrixTranspose( worldMatrix); cb.mView = XMMatrixTranspose( viewMatrix ); cb.mProjection = XMMatrixTranspose( projectionMatrix ); deviceContext->UpdateSubresource( m_matrixBuffer, 0, NULL, &cb, 0, 0 ); deviceContext->VSSetConstantBuffers( 0, 1, &m_matrixBuffer ); return true; } void XShader::RenderShader(ID3D11DeviceContext* deviceContext, int indexCount) { // 绑定顶点布局. deviceContext->IASetInputLayout(m_layout); // 设置渲染使用vs和ps. deviceContext->VSSetShader(m_vertexShader, NULL, 0); deviceContext->PSSetShader(m_pixelShader, NULL, 0); // 渲染图形 deviceContext->DrawIndexed(indexCount, 0, 0); return; }
#pragma once //定义该宏能够减少windows头文件的大小,使编译器不编译一些不必要的文件,加快编译时间 #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include "XGraphics.h" #include "XInput.h" //退出 static bool Xexit=false; //全屏 static bool fullScreen=false; class XWindow { private: //窗口类名字 LPCWSTR m_applicationName; //实例句柄 HINSTANCE m_hinstance; //窗口句柄 HWND m_hwnd; int xwidth,xheight; //按键类 XInput * x_input; //图形类 XGraphics * x_graphics; private: //初始化窗口 void initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName); //关闭窗口 void closeWindows(); //消息循环 void runWindows(); public: //初始化全局 virtual void init(); //渲染 virtual bool frame(); //退出 virtual void close(); //消息函数 LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM); }; //消息循环回调函数 static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static XWindow * appXWindow=NULL; void XWindow::close() { if(x_input) { delete x_input; x_input=NULL; } if(x_graphics) { x_graphics->close(); delete x_graphics; x_graphics=NULL; } } void XWindow::init() { xwidth=500; xheight=400; x_input=new XInput; x_graphics=new XGraphics; //创建窗口 initWindows(xwidth,xheight,L"Engine"); //初始化键盘 x_input->init(); //初始化渲染 x_graphics->init(xwidth,xheight,m_hwnd); //消息循环 runWindows(); //关闭窗口 closeWindows(); } bool XWindow::frame() { //判断是否按下ESC键 if(x_input->isKeyDown(VK_ESCAPE)) return false; //开始渲染 return x_graphics->frame(); } void XWindow::initWindows(int& screenWidth, int& screenHeight,LPCWSTR m_applicationName) { WNDCLASSEX wc; DEVMODE dmScreenSettings; int posX, posY; this->m_applicationName=m_applicationName; // 得到应用程序实例句柄 m_hinstance = GetModuleHandle(NULL); appXWindow=this; // 设置窗口类参数. wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = WndProc; //指定回调函数 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = m_hinstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hIconSm = wc.hIcon; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //默认黑色窗口黑色背景 wc.lpszMenuName = NULL; wc.lpszClassName = m_applicationName; wc.cbSize = sizeof(WNDCLASSEX); // 注册窗口类 RegisterClassEx(&wc); // 根据是否全屏设置不同的分辨率. if(fullScreen) { // 得到windows桌面分辨率 screenWidth = GetSystemMetrics(SM_CXSCREEN); screenHeight = GetSystemMetrics(SM_CYSCREEN); //全屏模式下,设置窗口大小为windows桌面分辨率. memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); dmScreenSettings.dmSize = sizeof(dmScreenSettings); dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth; dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight; dmScreenSettings.dmBitsPerPel = 32; dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; // 临时设置显示设备为全屏模式,注意:应用程序退出时候,将恢复系统默认设置。 ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN); // 设置窗口的左上角坐标位置为(0,0). posX = posY = 0; } else { // 窗口左上角坐标位置,posX, posY posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2; posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2; } // 全屏和窗口使用不同的参数. if( fullScreen) { m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); } else { m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName, WS_OVERLAPPEDWINDOW, posX, posY, screenWidth, screenHeight, NULL, NULL, m_hinstance, NULL); } // 显示窗口并设置其为焦点. ShowWindow(m_hwnd, SW_SHOW); SetForegroundWindow(m_hwnd); SetFocus(m_hwnd); // 隐藏鼠标. //ShowCursor(false); } void XWindow::runWindows() { MSG msg; // 初始化消息结构. ZeroMemory(&msg, sizeof(MSG)); // 循环进行消息处理 while(!Xexit) { // 处理windows消息. if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 接收到WM_QUIT消息,退出程序. if(msg.message == WM_QUIT) { Xexit=true; } else { //渲染 Xexit=!frame(); } } return; } LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam) { switch(umessage) { // 窗口销毁消息. case WM_DESTROY: case WM_CLOSE: { PostQuitMessage(0); return 0; } break; //MessageHandle过程处理其它所有消息. default: { return appXWindow->MessageHandler(hwnd, umessage, wparam, lparam); } break; } } LRESULT CALLBACK XWindow::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam) { switch(umsg) { // 检测按键消息. case WM_KEYDOWN: x_input->keyDown(wparam); break; case WM_KEYUP: x_input->keyUp(wparam); break; //任何其它消息发送到windows缺省处理. case WM_SIZE: //防止窗口大小改变渲染变形 x_graphics->init(LOWORD(lparam),HIWORD(lparam),hwnd); break; default: { return DefWindowProc(hwnd, umsg, wparam, lparam); } } return 0; } void XWindow::closeWindows() { //显示光标. //ShowCursor(true); // 恢复默认显示设置. if(fullScreen) { ChangeDisplaySettings(NULL, 0); } //释放窗口句柄. DestroyWindow(m_hwnd); m_hwnd = NULL; // 释放应用程序实例. UnregisterClass(m_applicationName, m_hinstance); m_hinstance = NULL; appXWindow=NULL; return; }
#include "XWindow.h" #include <d3dcompiler.h> //入口 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pScmdline, int iCmdshow) { XWindow *xwindow=new XWindow; xwindow->init(); //初始化 xwindow->close(); delete xwindow; return 0; }
//-------------------------------------------------------------------------------------- // File: Tutorial04.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- cbuffer ConstantBuffer { matrix World; matrix View; matrix Projection; } //-------------------------------------------------------------------------------------- struct VS_OUTPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR ) { VS_OUTPUT output = (VS_OUTPUT)0; output.Pos = mul( Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Color = Color; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( VS_OUTPUT input ) : SV_Target { return input.Color; }