// include the basic windows header file #include #include #include #pragma comment (lib, "d3d11.lib") #include #pragma comment (lib, "d3dcompiler.lib") #include #include namespace dx = DirectX; #include // to usd std::size #include // to use std::sin and std::cos #include "Timer.h" // to use timer Timer timer; #include #include /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ // global declarations Microsoft::WRL::ComPtr swapchain; // the pointer to the swap chain interface Microsoft::WRL::ComPtr dev; // the pointer to our Direct3D device interface Microsoft::WRL::ComPtr devcon; // the pointer to our Direct3D device context /************************************ * 1.2 DefineRenderTargetView ************************************/ Microsoft::WRL::ComPtr pBackBuffer; // 定义Targe View Microsoft::WRL::ComPtr targetView; /************************************ * 1.3 DefineDepthStencilView ************************************/ // Define depth stencil buffer Microsoft::WRL::ComPtr pDepthStencilState; // Define depth stencil texture Microsoft::WRL::ComPtr depthStencilTexture; // Define depth stencil view Microsoft::WRL::ComPtr pDSView; /************************************ * 2.3 DefineVertexBuffer ************************************/ // Define vertex buffer Microsoft::WRL::ComPtr pVertexBuffer; // Create buffer description struct Vertex { float x; float y; float z; float r; float g; float b; }; // create vertex buffer (8 vertices for one cube) const Vertex vertices[] = { // left bottom back { -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f }, // right bottom back { 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f }, // left top back { -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f }, // right top back { 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f }, // left bottom front { -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // right bottom front { 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f }, // left top front { -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, // right top front { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, }; /************************************ * 2.4 DefineIndexBuffer ************************************/ // Define index buffer Microsoft::WRL::ComPtr pIndexBuffer; // Create index buffer const unsigned short indices[] = { // back surface 0, 2, 1, 2, 3, 1, // right surface 1, 3, 5, 3, 7, 5, // top surface 2, 6, 3, 3, 6, 7, // front surface 4, 5, 7, 4, 7, 6, // left surface 0, 4, 2, 2, 4, 6, // bottom surface 0, 1, 4, 1, 5, 4, }; /************************************ * 2.5 DefineTransConstBuffer ************************************/ // Define transformation constant buffer Microsoft::WRL::ComPtr pTransConstBuffer; // Create transformation constant buffer struct struct TransConstBuffer { dx::XMMATRIX transform; }; // create constant buffer const float heightWidthRatio = 0.3f / 0.4f; float angle = 0.0f; TransConstBuffer tcb = { // transpose the matrix to change from row_major to column_major dx::XMMatrixTranspose( // rotate Z axis dx::XMMatrixRotationZ(-angle) // rotate X axis * dx::XMMatrixRotationX(-angle) // scaling //* dx::XMMatrixScaling(heightWidthRatio, 1.0f, 1.0f) // translation * dx::XMMatrixTranslation(0.0f, 0.0f, 4.0f) // projection * dx::XMMatrixPerspectiveLH(1.0f, heightWidthRatio, 0.1f, 10.0f) ) }; /************************************ * 2.6 DefineColorConstBuffer ************************************/ // Define color constant buffer Microsoft::WRL::ComPtr pColorConstBuffer; // Create constant buffer for color struct ColorConstantBuffer { struct { float r; float g; float b; float a; } face_colors[6]; }; const ColorConstantBuffer ccb = { { { 1.0f, 0.0f, 1.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 1.0f }, } }; /************************************ * 2.7 DefineVertexShader ************************************/ // Define Vertex Shader Microsoft::WRL::ComPtr pCompiledVertexBlob; Microsoft::WRL::ComPtr pVertexShader; /************************************ * 2.8 DefinePixelShader ************************************/ // Define Pixel Shader Microsoft::WRL::ComPtr pCompiledPixelBlob; Microsoft::WRL::ComPtr pPixelShader; /************************************ * 2.9 DefineInputLayout ************************************/ // Define input layout ID3D11InputLayout* pInputLayout; /************************************ * 2.13 DefineSampler ************************************/ Microsoft::WRL::ComPtr pSampler; /************************************ * Texture ************************************/ static IWICImagingFactory* wicFactory; /************************************ * 2.3 DefineVertexBuffer ************************************/ void DefineVertexBuffer() { D3D11_BUFFER_DESC bd = {}; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.Usage = D3D11_USAGE_DEFAULT; bd.CPUAccessFlags = 0u; bd.MiscFlags = 0u; bd.ByteWidth = sizeof(vertices); bd.StructureByteStride = sizeof(Vertex); D3D11_SUBRESOURCE_DATA sd = {}; sd.pSysMem = vertices; // Create vertex buffer dev->CreateBuffer(&bd, &sd, &pVertexBuffer); // Bind vertex buffer to pipeline const UINT stride = sizeof(Vertex); const UINT offset = 0u; devcon->IASetVertexBuffers(0u, 1u, pVertexBuffer.GetAddressOf(), &stride, &offset); } /************************************ * 2.4 DefineIndexBuffer ************************************/ void DefineIndexBuffer() { D3D11_BUFFER_DESC ibd = {}; ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; ibd.Usage = D3D11_USAGE_DEFAULT; ibd.CPUAccessFlags = 0u; ibd.MiscFlags = 0u; ibd.ByteWidth = sizeof(indices); ibd.StructureByteStride = sizeof(unsigned short); D3D11_SUBRESOURCE_DATA isd = {}; isd.pSysMem = indices; // Create index buffer dev->CreateBuffer(&ibd, &isd, &pIndexBuffer); // Bind index buffer to pipeline devcon->IASetIndexBuffer(pIndexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0u); } /************************************ * 2.5 DefineTransConstBuffer ************************************/ void DefineTransConstBuffer(float angle, float z) { tcb = { // transpose the matrix to change from row_major to column_major dx::XMMatrixTranspose( // rotate Z axis dx::XMMatrixRotationZ(-angle) // rotate X axis * dx::XMMatrixRotationX(-angle) // scaling //* dx::XMMatrixScaling(heightWidthRatio, 1.0f, 1.0f) // translation * dx::XMMatrixTranslation(0.0f, 0.0f, z) // projection * dx::XMMatrixPerspectiveLH(1.0f, heightWidthRatio, 0.5f, 10.0f) ) }; D3D11_BUFFER_DESC cbd = {}; cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbd.Usage = D3D11_USAGE_DYNAMIC; cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; cbd.MiscFlags = 0u; cbd.ByteWidth = sizeof(tcb); cbd.StructureByteStride = 0u; D3D11_SUBRESOURCE_DATA csd = {}; csd.pSysMem = &tcb; // Create constant buffer dev->CreateBuffer(&cbd, &csd, &pTransConstBuffer); // Bind constant buffer to vertex buffer devcon->VSSetConstantBuffers(0u, 1u, pTransConstBuffer.GetAddressOf()); } /************************************ * 2.6 DefineColorConstBuffer ************************************/ void DefineColorConstBuffer() { D3D11_BUFFER_DESC ccbd = {}; ccbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; ccbd.Usage = D3D11_USAGE_DEFAULT; ccbd.CPUAccessFlags = 0u; ccbd.MiscFlags = 0u; ccbd.ByteWidth = sizeof(ccb); ccbd.StructureByteStride = 0u; D3D11_SUBRESOURCE_DATA ccsd = {}; ccsd.pSysMem = &ccb; dev->CreateBuffer(&ccbd, &ccsd, &pColorConstBuffer); // Bind constant buffer to vertex devcon->PSSetConstantBuffers(0u, 1u, pColorConstBuffer.GetAddressOf()); } /************************************ * 2.7 DefineVertexShader ************************************/ void DefineVertexShader() { // Load pixel shader file into BLOB, and create COM object of vertex shader D3DReadFileToBlob(L"VertexShader.cso", &pCompiledVertexBlob); dev->CreateVertexShader(pCompiledVertexBlob->GetBufferPointer(), pCompiledVertexBlob->GetBufferSize(), nullptr, &pVertexShader); // bind vertex shader devcon->VSSetShader(pVertexShader.Get(), nullptr, 0u); } /************************************ * 2.8 DefinePixelShader ************************************/ void DefinePixelShader() { // Load vertex shader file into BLOB, and create COM object of pixel shader D3DReadFileToBlob(L"PixelShader.cso", &pCompiledPixelBlob); dev->CreatePixelShader(pCompiledPixelBlob->GetBufferPointer(), pCompiledPixelBlob->GetBufferSize(), nullptr, &pPixelShader); // bind pixel shader devcon->PSSetShader(pPixelShader.Get(), nullptr, 0u); } /************************************ * 2.9 DefineInputLayout ************************************/ void DefineInputLayout() { // Create input elements description, choosing whatever need to send to GPU const D3D11_INPUT_ELEMENT_DESC ied[] = { //{ "Position",0,DXGI_FORMAT_R32G32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 }, { "Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 }, //{ "Color",0,DXGI_FORMAT_R32G32B32_FLOAT,0,8,D3D11_INPUT_PER_VERTEX_DATA,0 }, //{ "Color",0,DXGI_FORMAT_R32G32B32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0 }, }; // Create input layout, using the description Defined above dev->CreateInputLayout ( ied, (UINT)std::size(ied), pCompiledVertexBlob->GetBufferPointer(), pCompiledVertexBlob->GetBufferSize(), &pInputLayout ); // Bind layout to pipeline // bind vertex layout devcon->IASetInputLayout(pInputLayout); } /************************************ * 2.10 DefinePrimitiveTopology ************************************/ void DefinePrimitiveTopology() { // Set the primitive type to use // Set primitive topology to triangle list (groups of 3 vertices) devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); } /************************************ * 2.11 DefineViewPorts ************************************/ void DefineViewPorts() { // 指定View Port D3D11_VIEWPORT viewport; ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); // 控制View port的位置 viewport.TopLeftX = 0; viewport.TopLeftY = 0; viewport.Width = 800; viewport.Height = 600; viewport.MinDepth = 0; viewport.MaxDepth = 1; devcon->RSSetViewports(1, &viewport); } /************************************ * 2.12 DrawPrimitive ************************************/ void DrawPrimitive() { // Draw the triangle. // devcon->Draw((UINT)sizeof(vertices), 0u); devcon->DrawIndexed((UINT)std::size(indices), 0u, 0u); } /************************************ * 2.13 DefineSampler ************************************/ void DefineSampler() { D3D11_SAMPLER_DESC samplerDesc = {}; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; dev->CreateSamplerState(&samplerDesc, &pSampler); devcon->PSSetSamplers(0, 1, pSampler.GetAddressOf()); } void drawSingleTriangle(float angle, float z) { /************************************ * 2.3 DefineVertexBuffer ************************************/ DefineVertexBuffer(); /************************************ * 2.4 DefineIndexBuffer ************************************/ DefineIndexBuffer(); /************************************ * 2.5 DefineTransConstBuffer ************************************/ DefineTransConstBuffer(angle, z); /************************************ * 2.6 DefineColorConstBuffer ************************************/ DefineColorConstBuffer(); /************************************ * 2.7 DefineVertexShader ************************************/ DefineVertexShader(); /************************************ * 2.8 DefinePixelShader ************************************/ DefinePixelShader(); /************************************ * 2.9 DefineInputLayout ************************************/ DefineInputLayout(); /************************************ * 2.10 DefinePrimitiveTopology ************************************/ DefinePrimitiveTopology(); /************************************ * 2.11 DefineViewPorts ************************************/ DefineViewPorts(); /************************************ * 2.12 DrawPrimitive ************************************/ DrawPrimitive(); /************************************ * 2.13 DefineSampler ************************************/ DefineSampler(); } void drawTriangle() { drawSingleTriangle(timer.Peek(), 4.0f); //drawSingleTriangle(-timer.Peek(), 4.5f); } /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ void CreateDeviceAndSwapChain(HWND hWnd) { // create a struct to hold information about the swap chain DXGI_SWAP_CHAIN_DESC scd; // clear out the struct for use ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); // fill the swap chain description struct scd.BufferCount = 1; // one back buffer scd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // use 32-bit color scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used scd.OutputWindow = hWnd; // the window to be used scd.SampleDesc.Count = 1; // how many multisamples scd.Windowed = TRUE; // windowed/full-screen mode // create a device, device context and swap chain using the information in the scd struct D3D11CreateDeviceAndSwapChain(NULL, // IDXGIAdapter *pAdapter - Let DXGI take care of what adapter to use (default adapter) D3D_DRIVER_TYPE_HARDWARE, // D3D_DRIVER_TYPE DriverType - hardware or software, or others NULL, // HMODULE Software NULL, // UINT Flags NULL, // D3D_FEATURE_LEVEL *pFeatureLevels NULL, // UINT FeatureLevels D3D11_SDK_VERSION, // UINT SDKVersion &scd, // DXGI_SWAP_CHAIN_DESC *pSwapChainDesc &swapchain, // IDXGISwapChain **ppSwapChain &dev, // ID3D11Device **ppDevice NULL, // D3D_FEATURE_LEVEL *FeatureLevel &devcon); // ID3D11DeviceContext **ppImmediateContext } /************************************ * 1.2 DefineRenderTargetView ************************************/ void DefineRenderTargetView() { // 从SwapChain中取得back buffer swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // 根据back buffer,创建新的View Target dev->CreateRenderTargetView(pBackBuffer.Get(), NULL, &targetView); } /************************************ * 1.3 DefineDepthStencilView ************************************/ void DefineDepthStencilView() { // Create depth stencil state D3D11_DEPTH_STENCIL_DESC depthStencilDesc = {}; depthStencilDesc.DepthEnable = TRUE; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; // Create depth stencil state dev->CreateDepthStencilState(&depthStencilDesc, &pDepthStencilState); // bind depth state devcon->OMSetDepthStencilState(pDepthStencilState.Get(), 1u); // Create the depth stencil texture D3D11_TEXTURE2D_DESC depthStencilTextureDesc = {}; depthStencilTextureDesc.Width = 800; depthStencilTextureDesc.Height = 600; depthStencilTextureDesc.MipLevels = 1u; depthStencilTextureDesc.ArraySize = 1u; depthStencilTextureDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilTextureDesc.SampleDesc.Count = 1u; depthStencilTextureDesc.SampleDesc.Quality = 0u; depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; // Create texture dev->CreateTexture2D(&depthStencilTextureDesc, nullptr, &depthStencilTexture); // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {}; depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0u; dev->CreateDepthStencilView(depthStencilTexture.Get(), &depthStencilViewDesc, &pDSView); } /************************************ * 1.4 DefineRenderTarget ************************************/ void DefineRenderTarget() { // 将渲染目标设置成我们新创建的View Target //devcon->OMSetRenderTargets(1u, targetView.GetAddressOf(), NULL); devcon->OMSetRenderTargets(1u, targetView.GetAddressOf(), pDSView.Get()); } // this function initializes and prepares Direct3D for use void InitD3D(HWND hWnd) { /************************************ * 1.1 CreateDeviceAndSwapChain ************************************/ CreateDeviceAndSwapChain(hWnd); /************************************ * 1.2 DefineRenderTargetView ************************************/ DefineRenderTargetView(); /************************************ * 1.3 DefineDepthStencilView ************************************/ DefineDepthStencilView(); /************************************ * 1.4 DefineRenderTarget ************************************/ DefineRenderTarget(); } // this is the function used to render a single frame void RenderFrame(void) { /************************************ * 2.1 ClearRenderTargetView ************************************/ // clear the back buffer to a deep blue const float color[] = { 0.0f, 0.2f, 0.4f, 1.0f }; devcon->ClearRenderTargetView(targetView.Get(), color); /************************************ * 2.2 ClearDepthStencilView ************************************/ // clear the depth stencil view devcon->ClearDepthStencilView(pDSView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0u); /************************************ * 2.3 - 2.12 Repeat graphic objects ************************************/ // do 3D rendering on the back buffer here drawTriangle(); /************************************ * 3 DrawPrimitive ************************************/ // switch the back buffer and the front buffer // 切换显示,将back buffer的内容交换到front buffer swapchain->Present(0, 0); } /************************************ * get the dxgi format equivilent of a wic format ************************************/ DXGI_FORMAT GetDXGIFormatFromWICFormat(WICPixelFormatGUID& wicFormatGUID) { if (wicFormatGUID == GUID_WICPixelFormat128bppRGBAFloat) return DXGI_FORMAT_R32G32B32A32_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBAHalf) return DXGI_FORMAT_R16G16B16A16_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBA) return DXGI_FORMAT_R16G16B16A16_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA) return DXGI_FORMAT_R8G8B8A8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGRA) return DXGI_FORMAT_B8G8R8A8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGR) return DXGI_FORMAT_B8G8R8X8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA1010102XR) return DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBA1010102) return DXGI_FORMAT_R10G10B10A2_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGRA5551) return DXGI_FORMAT_B5G5R5A1_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGR565) return DXGI_FORMAT_B5G6R5_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat32bppGrayFloat) return DXGI_FORMAT_R32_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat16bppGrayHalf) return DXGI_FORMAT_R16_FLOAT; else if (wicFormatGUID == GUID_WICPixelFormat16bppGray) return DXGI_FORMAT_R16_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat8bppGray) return DXGI_FORMAT_R8_UNORM; else if (wicFormatGUID == GUID_WICPixelFormat8bppAlpha) return DXGI_FORMAT_A8_UNORM; else return DXGI_FORMAT_UNKNOWN; } /************************************ * get a dxgi compatible wic format from another wic format ************************************/ WICPixelFormatGUID GetConvertToWICFormat(WICPixelFormatGUID& wicFormatGUID) { if (wicFormatGUID == GUID_WICPixelFormatBlackWhite) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat1bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat2bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat4bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat8bppIndexed) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat2bppGray) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat4bppGray) return GUID_WICPixelFormat8bppGray; else if (wicFormatGUID == GUID_WICPixelFormat16bppGrayFixedPoint) return GUID_WICPixelFormat16bppGrayHalf; else if (wicFormatGUID == GUID_WICPixelFormat32bppGrayFixedPoint) return GUID_WICPixelFormat32bppGrayFloat; else if (wicFormatGUID == GUID_WICPixelFormat16bppBGR555) return GUID_WICPixelFormat16bppBGRA5551; else if (wicFormatGUID == GUID_WICPixelFormat32bppBGR101010) return GUID_WICPixelFormat32bppRGBA1010102; else if (wicFormatGUID == GUID_WICPixelFormat24bppBGR) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat24bppRGB) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat32bppPBGRA) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat32bppPRGBA) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGB) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppBGR) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppBGRA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPRGBA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPBGRA) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGBFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat48bppBGRFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBAFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppBGRAFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBFixedPoint) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGBHalf) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat48bppRGBHalf) return GUID_WICPixelFormat64bppRGBAHalf; else if (wicFormatGUID == GUID_WICPixelFormat128bppPRGBAFloat) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBFloat) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBAFixedPoint) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat128bppRGBFixedPoint) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat32bppRGBE) return GUID_WICPixelFormat128bppRGBAFloat; else if (wicFormatGUID == GUID_WICPixelFormat32bppCMYK) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppCMYK) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat40bppCMYKAlpha) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat80bppCMYKAlpha) return GUID_WICPixelFormat64bppRGBA; #if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE) else if (wicFormatGUID == GUID_WICPixelFormat32bppRGB) return GUID_WICPixelFormat32bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppRGB) return GUID_WICPixelFormat64bppRGBA; else if (wicFormatGUID == GUID_WICPixelFormat64bppPRGBAHalf) return GUID_WICPixelFormat64bppRGBAHalf; #endif else return GUID_WICPixelFormatDontCare; } /************************************ * get the number of bits per pixel for a dxgi format ************************************/ int GetDXGIFormatBitsPerPixel(DXGI_FORMAT& dxgiFormat) { if (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT) return 128; else if (dxgiFormat == DXGI_FORMAT_R16G16B16A16_FLOAT) return 64; else if (dxgiFormat == DXGI_FORMAT_R16G16B16A16_UNORM) return 64; else if (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B8G8R8A8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B8G8R8X8_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_R10G10B10A2_UNORM) return 32; else if (dxgiFormat == DXGI_FORMAT_B5G5R5A1_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_B5G6R5_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_R32_FLOAT) return 32; else if (dxgiFormat == DXGI_FORMAT_R16_FLOAT) return 16; else if (dxgiFormat == DXGI_FORMAT_R16_UNORM) return 16; else if (dxgiFormat == DXGI_FORMAT_R8_UNORM) return 8; else if (dxgiFormat == DXGI_FORMAT_A8_UNORM) return 8; } /************************************ * Texture 01 * Load the data from the image file * and decrypt it to a bitmap format * compatible with DXGI formats (rgba) ************************************/ void LoadImageFromFile(BYTE** imageData, LPCWSTR filename, int& bytesPerRow) { // reset decoder, frame and converter since these will be different for each image we load IWICBitmapDecoder* wicDecoder = NULL; IWICBitmapFrameDecode* wicFrame = NULL; IWICFormatConverter* wicConverter = NULL; HRESULT hr; /************************************ * 1 Initialize the COM library ************************************/ if (wicFactory == nullptr) { hr = CoInitialize(wicFactory); } /************************************ * 2 Create WIC Factory ************************************/ hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&wicFactory)); /************************************ * 3 Create the Bitmap Decoder ************************************/ hr = wicFactory->CreateDecoderFromFilename( filename, // Image we want to load in NULL, // This is a vendor ID, we do not prefer a specific one so set to null GENERIC_READ, // We want to read from this file WICDecodeMetadataCacheOnLoad, // We will cache the metadata right away, rather than when needed, which might be unknown &wicDecoder // the wic decoder to be created) ); /************************************ * 4 Grab the first frame in the image ************************************/ hr = wicDecoder->GetFrame(0, &wicFrame); /************************************ * 5 Get WIC Pixel Format From Frame ************************************/ WICPixelFormatGUID pixelFormat; hr = wicFrame->GetPixelFormat(&pixelFormat); /************************************ * 6 Get Size of the image ************************************/ UINT textureWidth, textureHeight; hr = wicFrame->GetSize(&textureWidth, &textureHeight); /************************************ * 7 Get Compatible DXGI Format ************************************/ // convert wic pixel format to dxgi pixel format DXGI_FORMAT dxgiFormat = GetDXGIFormatFromWICFormat(pixelFormat); /************************************ * 8 Convert image to DXGI format if necessary ************************************/ bool imageConverted = false; // if the format of the image is not a supported dxgi format, try to convert it if (dxgiFormat == DXGI_FORMAT_UNKNOWN) { // get a dxgi compatible wic format from the current image format WICPixelFormatGUID convertToPixelFormat = GetConvertToWICFormat(pixelFormat); // return if no dxgi compatible format was found //if (convertToPixelFormat == GUID_WICPixelFormatDontCare) return 0; // set the dxgi format dxgiFormat = GetDXGIFormatFromWICFormat(convertToPixelFormat); // create the format converter hr = wicFactory->CreateFormatConverter(&wicConverter); //if (FAILED(hr)) return 0; // make sure we can convert to the dxgi compatible format BOOL canConvert = FALSE; hr = wicConverter->CanConvert(pixelFormat, convertToPixelFormat, &canConvert); //if (FAILED(hr) || !canConvert) return 0; // do the conversion (wicConverter will contain the converted image) hr = wicConverter->Initialize(wicFrame, convertToPixelFormat, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); //if (FAILED(hr)) return 0; // this is so we know to get the image data from the wicConverter (otherwise we will get from wicFrame) imageConverted = true; } /************************************ * 9 Get image size information ************************************/ int bitsPerPixel = GetDXGIFormatBitsPerPixel(dxgiFormat); // number of bits per pixel bytesPerRow = (textureWidth * bitsPerPixel) / 8; // number of bytes in each row of the image data int imageSize = bytesPerRow * textureHeight; // total image size in bytes /************************************ * 10 Get the pixel data (CopyPixel) ************************************/ // allocate enough memory for the raw image data, and set imageData to point to that memory *imageData = (BYTE*)malloc(imageSize); // copy (decoded) raw image data into the newly allocated memory (imageData) if (imageConverted) { // if image format needed to be converted, the wic converter will contain the converted image hr = wicConverter->CopyPixels(0, bytesPerRow, imageSize, *imageData); //if (FAILED(hr)) return 0; } else { // no need to convert, just copy data from the wic frame hr = wicFrame->CopyPixels(0, bytesPerRow, imageSize, *imageData); //if (FAILED(hr)) return 0; } /************************************ * 11 Create Texture Resource ************************************/ // create texture resource D3D11_TEXTURE2D_DESC textureDesc = {}; textureDesc.Width = textureWidth; textureDesc.Height = textureHeight; textureDesc.MipLevels = 1; textureDesc.ArraySize = 1; textureDesc.Format = dxgiFormat; textureDesc.SampleDesc.Count = 1; textureDesc.SampleDesc.Quality = 0; textureDesc.Usage = D3D11_USAGE_DEFAULT; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; textureDesc.CPUAccessFlags = 0; textureDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA sd = {}; sd.pSysMem = *imageData; // s.GetBufferPtr(); sd.SysMemPitch = bytesPerRow; // s.GetWidth() * sizeof(Surface::Color); sd.SysMemSlicePitch = bytesPerRow * textureHeight; // wrl::ComPtr pTexture; ID3D11Texture2D* pTexture2D = nullptr; hr = dev->CreateTexture2D(&textureDesc, &sd, &pTexture2D); /************************************ * 12 Create the resource view on the texture ************************************/ ID3D11ShaderResourceView* pTextureView = nullptr; if (hr == S_OK) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; srvDesc.Format = textureDesc.Format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; hr = dev->CreateShaderResourceView(pTexture2D, &srvDesc, &pTextureView); } /************************************ * 13 Bind shader resource view to pipeline ************************************/ devcon->PSSetShaderResources(0, 1, &pTextureView); int i = 0; } // this is the function that cleans up Direct3D and COM void CleanD3D() { // close and release all existing COM objects // changed to use smart pointer, do NOT need to manually release // pPixelShader->Release(); // pCompiledPixelBlob->Release(); // pVertexShader->Release(); // pCompiledVertexBlob->Release(); // pVertexBuffer->Release(); // pInputLayout->Release(); // swapchain->Release(); // targetView->Release(); // dev->Release(); // devcon->Release(); } // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // the handle for the window, filled by a function HWND hWnd; // this struct holds information for the window class WNDCLASSEX wc; // clear out the window class for use ZeroMemory(&wc, sizeof(WNDCLASSEX)); // fill in the struct with the needed information wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)COLOR_WINDOW; wc.lpszClassName = "WindowClass"; // register the window class RegisterClassEx(&wc); // create rectangle for client area RECT wr = { 0, 0, 800, 600 }; // set the size only, but not the position AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size // create the window and use the result as the handle hWnd = CreateWindowEx(NULL, "WindowClass", // name of the window class "Our First Windowed Program", // title of the window WS_OVERLAPPEDWINDOW, // window style 300, // x-position of the window 200, // y-position of the window 800, // width of the window 600, // height of the window NULL, // we have no parent window, NULL NULL, // we aren't using menus, NULL hInstance, // application handle NULL); // used with multiple windows, NULL // display the window on the screen ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D InitD3D(hWnd); // test texture load std::string imageFile = "oasis.ico"; std::wstring wsImageFile = std::wstring(imageFile.begin(), imageFile.end()); BYTE* imageData; int bytesPerRow = 8; LoadImageFromFile(&imageData, wsImageFile.c_str(), bytesPerRow); // enter the main loop: // this struct holds Windows event messages MSG msg; // wait for the next message in the queue, store the result in 'msg' while (true) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // translate keystroke messages into the right format TranslateMessage(&msg); // send the message to the WindowProc function DispatchMessage(&msg); // check if message to quit if (msg.message == WM_QUIT) { break; } } else { RenderFrame(); } } // clean up DirectX and COM CleanD3D(); // return this part of the WM_QUIT message to Windows return msg.wParam; } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { // sort through and find what code to run for the message given switch (message) { // this message is read when the window is closed case WM_DESTROY: { // close the application entirely PostQuitMessage(0); return 0; } break; } // Handle any messages the switch statement didn't return DefWindowProc(hWnd, message, wParam, lParam); }