/////////////////////////////////////////////////////////////////////////////////////////////////// /// CelShadeApp::CelShadeD3D /// /// @brief /// Render a cel-shading demo using Direct3D /// @return /// N/A /////////////////////////////////////////////////////////////////////////////////////////////////// void CelShadeApp::CelShadeD3D() { ID3D11DeviceContext* pContext = m_pDxData->pD3D11Context; ID3D11Device* pDevice = m_pDxData->pD3D11Device; D3DX11_IMAGE_LOAD_INFO imageLoadInfo; memset( &imageLoadInfo, 0, sizeof(D3DX11_IMAGE_LOAD_INFO) ); imageLoadInfo.BindFlags = D3D11_BIND_SHADER_RESOURCE; imageLoadInfo.Format = DXGI_FORMAT_R8G8B8A8_UNORM; DxTextureCreateInfo shadeTexInfo; memset(&shadeTexInfo, 0, sizeof(DxTextureCreateInfo)); shadeTexInfo.flags.RenderTarget = TRUE; shadeTexInfo.flags.ShaderInput = TRUE; shadeTexInfo.format = DXGI_FORMAT_R8G8B8A8_UNORM; shadeTexInfo.width = m_screenWidth; shadeTexInfo.height = m_screenHeight; DxTexture* pShadeTex = DxTexture::Create(pDevice, &shadeTexInfo); DxTextureCreateInfo edgeTexInfo; memset(&edgeTexInfo, 0, sizeof(DxTextureCreateInfo)); edgeTexInfo.flags.RenderTarget = TRUE; edgeTexInfo.flags.ShaderInput = TRUE; edgeTexInfo.format = DXGI_FORMAT_R8G8B8A8_UNORM; edgeTexInfo.width = m_screenWidth; edgeTexInfo.height = m_screenHeight; DxTexture* pEdgeTex = DxTexture::Create(pDevice, &edgeTexInfo); // Samplers ///////////////////////////////////////////////////////////////////////////// // SamplerState PointSampler : register(s0); D3D11_SAMPLER_DESC pointSamplerDesc; memset(&pointSamplerDesc, 0, sizeof(D3D11_SAMPLER_DESC)); pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; pointSamplerDesc.MinLOD = -FLT_MAX; pointSamplerDesc.MaxLOD = FLT_MAX; pointSamplerDesc.MipLODBias = 0.0f; pointSamplerDesc.MaxAnisotropy = 16; ID3D11SamplerState* pPointSampler = NULL; pDevice->CreateSamplerState(&pointSamplerDesc, &pPointSampler); // UINT numVertices = 0, numIndices = 0; VertexPTN* pVB = NULL; UINT* pIB = NULL; ImportPly("Content/dragon_vrip_res3.ply", numVertices, &pVB, numIndices, &pIB); //ImportPly("Content/bun_zipper_res4.ply", numVertices, &pVB, numIndices, &pIB); DxMeshCreateInfo meshCreateInfo = {0}; meshCreateInfo.indexCount = numIndices; meshCreateInfo.pIndexArray = pIB; meshCreateInfo.indexFormat = DXGI_FORMAT_R32_UINT; meshCreateInfo.pVertexArray = pVB; meshCreateInfo.vertexCount = numVertices; meshCreateInfo.vertexElementSize = sizeof(VertexPTN); DxMesh* pMesh = DxMesh::Create(pDevice, &meshCreateInfo); Plane p; DxMeshCreateInfo planeMeshInfo; memset(&planeMeshInfo, 0, sizeof(planeMeshInfo)); planeMeshInfo.pVertexArray = p.GetVB(); planeMeshInfo.vertexCount = p.NumVertices(); planeMeshInfo.vertexElementSize = sizeof(VertexPTN); DxMesh* pPlaneMesh = DxMesh::Create(pDevice, &planeMeshInfo); Cube c; DxMeshCreateInfo cubeMeshInfo; memset(&cubeMeshInfo, 0, sizeof(cubeMeshInfo)); cubeMeshInfo.pVertexArray = c.GetVB(); cubeMeshInfo.vertexCount = c.NumVertices(); cubeMeshInfo.vertexElementSize = sizeof(VertexPT); DxMesh* pCubeMesh = DxMesh::Create(pDevice, &cubeMeshInfo); D3D11_SUBRESOURCE_DATA cbInitData; memset(&cbInitData, 0, sizeof(D3D11_SUBRESOURCE_DATA)); // Camera Buffer CameraBufferData cameraData; memset(&cameraData, 0, sizeof(CameraBufferData)); DxBufferCreateInfo cameraBufferCreateInfo = {0}; cameraBufferCreateInfo.flags.cpuWriteable = TRUE; cameraBufferCreateInfo.elemSizeBytes = sizeof(CameraBufferData); cameraBufferCreateInfo.pInitialData = &cameraData; DxBuffer* pCameraBuffer = DxBuffer::Create(pDevice, &cameraBufferCreateInfo); // Shaders //////////////////////////////////////////////////////////////////////////////////// m_pPosTexTriVS = DxShader::CreateFromFile(pDevice, "PosTexTri", "Content/shaders/CelShade.hlsl", PosTexVertexDesc, PosTexElements); m_pPosTexNormVS = DxShader::CreateFromFile(pDevice, "PosTexNorm", "Content/shaders/CelShade.hlsl", PosTexNormVertexDesc, PosTexNormElements); m_pCelShadePS = DxShader::CreateFromFile(pDevice, "CelShade", "Content/shaders/CelShade.hlsl"); DxShader* pDetectEdges = DxShader::CreateFromFile(pDevice, "DetectEdges", "Content/shaders/CelShade.hlsl"); DxShader* pApplyTexPS = DxShader::CreateFromFile(pDevice, "ApplyTex", "Content/shaders/CelShade.hlsl"); DxShader* pCubeVS = DxShader::CreateFromFile(pDevice, "PosTex", "Content/shaders/CelShade.hlsl", PosTexVertexDesc, PosTexElements); DxShader* pCubePS = DxShader::CreateFromFile(pDevice, "CubePS", "Content/shaders/CelShade.hlsl"); //////////////////////////////////////////////////////////////////////////////////////// pContext->ClearState(); // SET RENDER STATE FLOAT clearColor[4]; clearColor[0] = 0.2f; clearColor[1] = 0.2f; clearColor[2] = 0.2f; clearColor[3] = 1.0f; D3D11_RASTERIZER_DESC shadeDesc; shadeDesc.FillMode = D3D11_FILL_SOLID; shadeDesc.CullMode = D3D11_CULL_BACK; shadeDesc.FrontCounterClockwise = FALSE; shadeDesc.DepthBias = 0; shadeDesc.DepthBiasClamp = 0.0f; shadeDesc.SlopeScaledDepthBias = 0; shadeDesc.DepthClipEnable = false; shadeDesc.ScissorEnable = false; shadeDesc.MultisampleEnable = false; shadeDesc.AntialiasedLineEnable = false; ID3D11RasterizerState* pShadeRS = NULL; pDevice->CreateRasterizerState(&shadeDesc, &pShadeRS); pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_pWindow->Show(); BOOL quit = false; FLOAT yRotationAngle = 0.0f; while (!quit) { ProcessUpdates(); BeginFrame(); CameraBufferData* pCameraData = NULL; // new frame, clear state pContext->ClearState(); pContext->RSSetViewports(1, &m_pDxData->viewport); pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); pContext->RSSetState(pShadeRS); pContext->PSSetSamplers(0, 1, &pPointSampler); pContext->OMSetRenderTargets(1, &m_pDxData->pAppRenderTargetView, m_pDxData->pAppDepthStencilTex->GetDepthStencilView()); pContext->ClearRenderTargetView(m_pDxData->pAppRenderTargetView, clearColor); pContext->ClearDepthStencilView(m_pDxData->pAppDepthStencilTex->GetDepthStencilView(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0, 0); ///// Draw Mesh /////////////////////////////////////////////////////////////////////////// FLOAT viewRotationY = (GetMousePos().x - (m_screenWidth / 2.0f)) /(m_screenWidth / 2.0f); viewRotationY *= (3.14159f / 4.0f); FLOAT viewRotationZ = (GetMousePos().y - (m_screenHeight / 2.0f)) /(m_screenHeight / 2.0f); viewRotationZ *= (3.14159f / 4.0f); pCameraData = reinterpret_cast<CameraBufferData*>(pCameraBuffer->Map(pContext)); pCameraData->worldMatrix = XMMatrixScaling(25, 25, 25) * XMMatrixRotationY(yRotationAngle) * XMMatrixTranslation(m_pCamera->Position().x, m_pCamera->Position().y, m_pCamera->Position().z) ; // translate world +6 in Z to position camera -9 from world origin pCameraData->viewMatrix = m_pCamera->W2C(); pCameraData->projectionMatrix = m_pCamera->C2S(); pCameraBuffer->Unmap(pContext); pCameraBuffer->BindVS(pContext, 0); pMesh->Bind(pContext); m_pPosTexNormVS->Bind(pContext); m_pCelShadePS->Bind(pContext); pMesh->Draw(pContext); ///// Detect Edges /////////////////////////////////////////////////////////////////////////// ///// Draw Light Position //////////////////////////////////////////////////////////////////// //yRotationAngle = 0; pCameraData = reinterpret_cast<CameraBufferData*>(pCameraBuffer->Map(pContext)); pCameraData->worldMatrix = XMMatrixScaling(1, 1, 1); // XMMatrixRotationY(yRotationAngle); // XMMatrixTranslation(-10, 10, 10); // translate world +6 in Z to position camera -9 from world origin pCameraData->viewMatrix = XMMatrixTranslation(0, 0, 10) * m_pCamera->W2C(); pCameraData->projectionMatrix = m_pCamera->C2S(); pCameraBuffer->Unmap(pContext); pCameraBuffer->BindVS(pContext, 0); pCubeVS->Bind(pContext); pCubePS->Bind(pContext); pCubeMesh->Bind(pContext); pCubeMesh->Draw(pContext); ///// Draw UI //////////////////////////////////////////////////////////////////////////////// ///@todo Consider moving the following UI drawing to Draw2D() m_pUI->Begin(); // Draw UI stuff m_pUI->RenderRect(); m_pUI->RenderText(); m_pUI->End(); /// Blend UI onto final image DrawUI(); m_pDxData->pDXGISwapChain->Present(0,0); EndFrame(); Sleep(50); yRotationAngle += 3.14159f / 60.0f; } // Shader Resource Views pCameraBuffer->Destroy(); // Shaders m_pCelShadePS->Destroy(); m_pCelShadePS = NULL; m_pPosTexTriVS->Destroy(); m_pPosTexTriVS = NULL; m_pPosTexNormVS->Destroy(); m_pPosTexNormVS = NULL; pApplyTexPS->Destroy(); pApplyTexPS = NULL; pPlaneMesh->Destroy(); pPlaneMesh = NULL; // Samplers pPointSampler->Release(); // Rasterizer State pShadeRS->Release(); m_pDxData->pD3D11Context->ClearState(); m_pDxData->pD3D11Context->Flush(); }
/////////////////////////////////////////////////////////////////////////////////////////////////// /// IvyApp::InitDX /// /// @brief /// /// @return /// N/A /////////////////////////////////////////////////////////////////////////////////////////////////// bool IvyApp::InitDX() { bool success = true; m_pDxData = new IvyAppDxData(); memset(&m_pDxData->viewport, 0, sizeof(D3D11_VIEWPORT)); EnumerateAdapters(); DxEnumDisplayDevices(); // Create Swap Chain & Device DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = BufferCount; sd.BufferDesc.Width = m_screenWidth; sd.BufferDesc.Height = m_screenHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = m_pWindow->GetHwnd(); sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; D3D_FEATURE_LEVEL FeatureLevelsRequested[2]; FeatureLevelsRequested[0] = D3D_FEATURE_LEVEL_11_0; FeatureLevelsRequested[1] = D3D_FEATURE_LEVEL_10_1; UINT numLevelsRequested = 2; D3D_FEATURE_LEVEL FeatureLevelsSupported; if( DxFAIL (D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, FeatureLevelsRequested, numLevelsRequested, D3D11_SDK_VERSION, &sd, &m_pDxData->pDXGISwapChain, &m_pDxData->pD3D11Device, &FeatureLevelsSupported, &m_pDxData->pD3D11Context ))) { success = false; } if (success) { ID3D11Texture2D* pBackBuffer = NULL; // Get a pointer to the back buffer if (DxFAIL(m_pDxData->pDXGISwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer))) { success = false; } else { // Create a render-target view m_pDxData->pD3D11Device->CreateRenderTargetView(pBackBuffer, NULL, &m_pDxData->pAppRenderTargetView ); pBackBuffer->Release(); } } HRESULT hr = S_OK; if (success) { DxTextureCreateInfo depthStencilCreateInfo; memset(&depthStencilCreateInfo, 0, sizeof(DxTextureCreateInfo)); depthStencilCreateInfo.flags.DepthStencil = TRUE; depthStencilCreateInfo.flags.ShaderInput = TRUE; depthStencilCreateInfo.format = DXGI_FORMAT_D24_UNORM_S8_UINT; ///@todo texture doesnt read format currently depthStencilCreateInfo.width = m_screenWidth; depthStencilCreateInfo.height = m_screenHeight; m_pDxData->pAppDepthStencilTex = DxTexture::Create(m_pDxData->pD3D11Device, &depthStencilCreateInfo); } // Setup viewport m_pDxData->viewport.Width = static_cast<FLOAT>(m_screenWidth); m_pDxData->viewport.Height = static_cast<FLOAT>(m_screenHeight); m_pDxData->viewport.MinDepth = 0.0f; m_pDxData->viewport.MaxDepth = 1.0f; m_pDxData->viewport.TopLeftX = 0; m_pDxData->viewport.TopLeftY = 0; // Create UI ///@todo Move UI creation up into IvyApp once the creation of IvyUI exists m_pUI = DxUI::Create(); m_pUIData = new IvyDxUIData(); m_pUIData->pUserInterfaceVS = DxShader::CreateFromFile(m_pDxData->pD3D11Device, "PosTexTri", L"Content/shaders/DxUI.hlsl", PosTexVertexDesc, PosTexElements); m_pUIData->pUserInterfacePS = DxShader::CreateFromFile(m_pDxData->pD3D11Device, "ApplyTex", L"Content/shaders/DxUI.hlsl"); CameraBufferData cameraData; memset(&cameraData, 0, sizeof(CameraBufferData)); DxBufferCreateInfo cameraBufferCreateInfo = {0}; cameraBufferCreateInfo.flags.cpuWriteable = TRUE; cameraBufferCreateInfo.elemSizeBytes = sizeof(CameraBufferData); cameraBufferCreateInfo.pInitialData = &cameraData; m_pUIData->pUserInterfaceCameraBuf = DxBuffer::Create(m_pDxData->pD3D11Device, &cameraBufferCreateInfo); Plane p; DxMeshCreateInfo planeMeshInfo; memset(&planeMeshInfo, 0, sizeof(planeMeshInfo)); planeMeshInfo.pVertexArray = p.GetVB(); planeMeshInfo.vertexCount = p.NumVertices(); planeMeshInfo.vertexElementSize = sizeof(VertexPTN); m_pUIData->pUserInterfaceQuad = DxMesh::Create(m_pDxData->pD3D11Device, &planeMeshInfo); m_pUIData->pUserInterfaceOverlay = m_pUI->CreateSharedTextureOverlay(m_pDxData->pD3D11Device); if (DxFAIL(m_pUIData->pUserInterfaceOverlay->QueryInterface(__uuidof(IDXGIKeyedMutex), (LPVOID*) &m_pUIData->pUserInterfaceMutexD3D))) { success = false; } D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.Texture2D.MipLevels = 1; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; m_pDxData->pD3D11Device->CreateShaderResourceView(m_pUIData->pUserInterfaceOverlay, &srvDesc, &m_pUIData->pUserInterfaceSRV); D3D11_BLEND_DESC uiBlendDesc; memset(&uiBlendDesc, 0, sizeof(D3D11_BLEND_DESC)); uiBlendDesc.AlphaToCoverageEnable = FALSE; uiBlendDesc.IndependentBlendEnable = FALSE; uiBlendDesc.RenderTarget[0].BlendEnable = TRUE; uiBlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; uiBlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; uiBlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; uiBlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; uiBlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; uiBlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; uiBlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; ID3D11BlendState* pUIBlendState = NULL; m_pDxData->pD3D11Device->CreateBlendState(&uiBlendDesc, &m_pUIData->pUserInterfaceBlendState); return success; }