// This code contains NVIDIA Confidential Information and is disclosed to you // under a form of NVIDIA software license agreement provided separately to you. // // Notice // NVIDIA Corporation and its licensors retain all intellectual property and // proprietary rights in and to this software and related documentation and // any modifications thereto. Any use, reproduction, disclosure, or // distribution of this software and related documentation without an express // license agreement from NVIDIA Corporation is strictly prohibited. // // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. // // Information and code furnished is believed to be accurate and reliable. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright (c) 2008-2017 NVIDIA Corporation. All rights reserved. #include "Renderer.h" #include "RenderUtils.h" #include "UIHelpers.h" #include "SampleProfiler.h" #include "PxRenderBuffer.h" #include #include "SimpleScene.h" #include "GlobalSettings.h" #include "Light.h" #include "AppMainWindow.h" #include "PxVec2.h" const float CAMERA_CLIP_NEAR = 1.0f; const float CAMERA_CLIP_FAR = 1000.00f; const float CLEAR_SCENE_COLOR[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; const int RenderTarget_Size = 512; const float SelectionTexture_InitData = -1; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Renderer /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Renderer* g_Renderer = nullptr; Renderer* Renderer::Inst() { return g_Renderer; } Renderer::Renderer() : m_cameraCB(nullptr) , m_worldCB(nullptr) , m_objectCB(nullptr) , m_opaqueRenderDSState(nullptr) , m_transparencyRenderDSState(nullptr) , m_opaqueRenderNoDepthDSState(nullptr) , m_DSTexture(nullptr) , m_DSView(nullptr) , m_DSTextureSRV(nullptr) , m_selectionRenderTargetTexture(nullptr) , m_selectionRenderTargetView(nullptr) , m_selectionRenderTargetSRV(nullptr) , m_selectionDepthStencilTexture(nullptr) , m_selectionDepthStencilView(nullptr) , m_selectionDepthStencilSRV(nullptr) , m_selectionTextureForCPU(nullptr) , m_pointSampler(nullptr) , m_linearSampler(nullptr) , m_wireframeMode(false) , m_debugPrimitiveVB(nullptr) , m_debugPrimitiveVBVerticesCount(0) , m_screenPrimitiveVB(nullptr) , m_screenPrimitiveVBVerticesCount(0) , m_shadowEnabled(true) , m_HBAOEnabled(true) , m_visibleOpaqueRenderablesCount(0) , m_visibleTransparentRenderablesCount(0) { m_worldCBData.ambientColor = DirectX::XMFLOAT3(0.21f, 0.21f, 0.22f); m_worldCBData.pointLightColor = DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f); m_worldCBData.pointLightPos = DirectX::XMFLOAT3(0.0f, 30.0f, 12.0f); m_worldCBData.dirLightColor = DirectX::XMFLOAT3(0.0f, 0.0f, 0.0f); m_worldCBData.dirLightDir = DirectX::XMFLOAT3(-0.08f, -0.34f, -0.91f); m_worldCBData.specularPower = 140.0f; m_worldCBData.specularIntensity = 0.4f; m_RSState[0] = nullptr; m_RSState[1] = nullptr; toggleCameraSpeed(false); g_Renderer = this; bFetchSelection = false; } Renderer::~Renderer() { } void Renderer::initializeDefaultRSState() { D3D11_RASTERIZER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.CullMode = D3D11_CULL_NONE; desc.AntialiasedLineEnable = FALSE; desc.DepthBias = 0; desc.DepthBiasClamp = 0; desc.DepthClipEnable = TRUE; desc.FrontCounterClockwise = FALSE; desc.MultisampleEnable = TRUE; desc.ScissorEnable = FALSE; desc.SlopeScaledDepthBias = 0; desc.FillMode = D3D11_FILL_SOLID; V(m_device->CreateRasterizerState(&desc, &m_RSState[0])); desc.FillMode = D3D11_FILL_WIREFRAME; V(m_device->CreateRasterizerState(&desc, &m_RSState[1])); } HRESULT Renderer::DeviceCreated(ID3D11Device* device) { m_device = device; // Camera constant buffer { D3D11_BUFFER_DESC buffer_desc; ZeroMemory(&buffer_desc, sizeof(buffer_desc)); buffer_desc.Usage = D3D11_USAGE_DYNAMIC; buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; buffer_desc.ByteWidth = sizeof(CBCamera); _ASSERT((buffer_desc.ByteWidth % 16) == 0); V(device->CreateBuffer(&buffer_desc, nullptr, &m_cameraCB)); } // World constant buffer { D3D11_BUFFER_DESC buffer_desc; ZeroMemory(&buffer_desc, sizeof(buffer_desc)); buffer_desc.Usage = D3D11_USAGE_DYNAMIC; buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; buffer_desc.ByteWidth = sizeof(CBWorld); _ASSERT((buffer_desc.ByteWidth % 16) == 0); V(device->CreateBuffer(&buffer_desc, nullptr, &m_worldCB)); } // Object constant buffer { D3D11_BUFFER_DESC buffer_desc; ZeroMemory(&buffer_desc, sizeof(buffer_desc)); buffer_desc.Usage = D3D11_USAGE_DYNAMIC; buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; buffer_desc.ByteWidth = sizeof(CBObject); _ASSERT((buffer_desc.ByteWidth % 16) == 0); V(device->CreateBuffer(&buffer_desc, nullptr, &m_objectCB)); } // Opaque Render Depth-Stencil state { D3D11_DEPTH_STENCIL_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.StencilEnable = FALSE; desc.DepthEnable = TRUE; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; V(device->CreateDepthStencilState(&desc, &m_opaqueRenderDSState)); } // Transparency Render Depth-Stencil state { D3D11_DEPTH_STENCIL_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.StencilEnable = FALSE; desc.DepthEnable = TRUE; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; V(device->CreateDepthStencilState(&desc, &m_transparencyRenderDSState)); } // Opaque Render Depth-Stencil state Without Depth Test { D3D11_DEPTH_STENCIL_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.StencilEnable = FALSE; desc.DepthEnable = FALSE; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; V(device->CreateDepthStencilState(&desc, &m_opaqueRenderNoDepthDSState)); } // Linear sampler { D3D11_SAMPLER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; desc.MaxAnisotropy = 1; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.MinLOD = 0; desc.MaxLOD = D3D11_FLOAT32_MAX; V(device->CreateSamplerState(&desc, &m_linearSampler)); } // Point sampler { D3D11_SAMPLER_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; desc.MaxAnisotropy = 1; desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; desc.MinLOD = 0; desc.MaxLOD = D3D11_FLOAT32_MAX; V(device->CreateSamplerState(&desc, &m_pointSampler)); } // Rasterizer state initializeDefaultRSState(); // init primitive render meshes for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++) { m_primitiveRenderMeshes[i] = nullptr; } // init shadows ID3D11DeviceContext* pd3dDeviceContext; m_device->GetImmediateContext(&pd3dDeviceContext); m_shadow.createResources(m_device, pd3dDeviceContext, &m_camera); // init hbao m_HBAO.createResources(m_device); return S_OK; } void Renderer::DeviceDestroyed() { SAFE_RELEASE(m_cameraCB); SAFE_RELEASE(m_worldCB); SAFE_RELEASE(m_objectCB); SAFE_RELEASE(m_RSState[0]); SAFE_RELEASE(m_RSState[1]); SAFE_RELEASE(m_opaqueRenderDSState); SAFE_RELEASE(m_transparencyRenderDSState); SAFE_RELEASE(m_opaqueRenderNoDepthDSState); SAFE_RELEASE(m_pointSampler); SAFE_RELEASE(m_linearSampler); SAFE_RELEASE(m_debugPrimitiveVB); SAFE_RELEASE(m_screenPrimitiveVB); SAFE_RELEASE(m_DSTexture); SAFE_RELEASE(m_DSView); SAFE_RELEASE(m_DSTextureSRV); SAFE_RELEASE(m_selectionRenderTargetTexture); SAFE_RELEASE(m_selectionRenderTargetView); SAFE_RELEASE(m_selectionRenderTargetSRV); SAFE_RELEASE(m_selectionDepthStencilTexture); SAFE_RELEASE(m_selectionDepthStencilView); SAFE_RELEASE(m_selectionDepthStencilSRV); SAFE_RELEASE(m_selectionTextureForCPU); for (uint32_t i = 0; i < PrimitiveRenderMeshType::Count; i++) { SAFE_DELETE(m_primitiveRenderMeshes[i]); } } void Renderer::onInitialize() { // search paths m_resourceManager.addSearchDir("..\\resources"); m_resourceManager.addSearchDir("..\\..\\..\\..\\bin\\resources"); //m_resourceManager.addSearchDir("..\\..\\samples\\resources"); //m_resourceManager.addSearchDir("..\\..\\..\\samples\\resources"); // debug primitive render material and input layout { m_debugPrimitiveRenderMaterial = new RenderMaterial("", m_resourceManager, "debug_primitive", ""); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; m_debugPrimitiveRenderMaterialInstance = m_debugPrimitiveRenderMaterial->getMaterialInstance(layout, ARRAYSIZE(layout)); } // screen primitive render material and input layout { m_screenPrimitiveRenderMaterial = new RenderMaterial("", m_resourceManager, "screen_primitive_ex", ""); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; m_screenPrimitiveRenderMaterialInstance = m_screenPrimitiveRenderMaterial->getMaterialInstance(layout, ARRAYSIZE(layout)); } // selection render material and input layout { m_selectionRenderMaterial = new RenderMaterial("idm", m_resourceManager, "model_simple_id_ex", ""); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "VERTEX_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "FACE_NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 36, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 48, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 1, DXGI_FORMAT_R32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 } }; m_selectionRenderMaterialInstance = m_selectionRenderMaterial->getMaterialInstance(layout, ARRAYSIZE(layout)); } } void Renderer::onTerminate() { SAFE_DELETE(m_debugPrimitiveRenderMaterial); SAFE_DELETE(m_screenPrimitiveRenderMaterial); } void Renderer::BackBufferResized(ID3D11Device* /*device*/, const DXGI_SURFACE_DESC* sd) { // Setup the camera's projection parameters m_screenWidth = sd->Width; m_screenHeight = sd->Height; float fAspectRatio = m_screenWidth / m_screenHeight; float fov = (GlobalSettings::Inst().m_fovAngle / 360.0f) * 3.141592653589793; m_camera.SetProjParams(fov, fAspectRatio, CAMERA_CLIP_NEAR, CAMERA_CLIP_FAR); SAFE_RELEASE(m_DSTexture); SAFE_RELEASE(m_DSView); SAFE_RELEASE(m_DSTextureSRV); SAFE_RELEASE(m_selectionRenderTargetTexture); SAFE_RELEASE(m_selectionRenderTargetView); SAFE_RELEASE(m_selectionRenderTargetSRV); SAFE_RELEASE(m_selectionDepthStencilTexture); SAFE_RELEASE(m_selectionDepthStencilView); SAFE_RELEASE(m_selectionDepthStencilSRV); SAFE_RELEASE(m_selectionTextureForCPU); // create m_selectionRenderTargetTexture { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = RenderTarget_Size; desc.Height = RenderTarget_Size; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R32_FLOAT; // Use a typeless type here so that it can be both depth-stencil and shader resource. desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; V(m_device->CreateTexture2D(&desc, NULL, &m_selectionRenderTargetTexture)); } // create m_selectionRenderTargetView { D3D11_RENDER_TARGET_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the view see this as D32_FLOAT instead of typeless desc.Texture2D.MipSlice = 0; V(m_device->CreateRenderTargetView(m_selectionRenderTargetTexture, &desc, &m_selectionRenderTargetView)); } // create m_selectionRenderTargetSRV { D3D11_SHADER_RESOURCE_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the shaders see this as R32_FLOAT instead of typeless desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; desc.Texture2D.MipLevels = 1; desc.Texture2D.MostDetailedMip = 0; V(m_device->CreateShaderResourceView(m_selectionRenderTargetTexture, &desc, &m_selectionRenderTargetSRV)); } // create m_selectionDepthStencilTexture { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = RenderTarget_Size; desc.Height = RenderTarget_Size; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R32_TYPELESS; // Use a typeless type here so that it can be both depth-stencil and shader resource. desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; V(m_device->CreateTexture2D(&desc, NULL, &m_selectionDepthStencilTexture)); } // create m_selectionDepthStencilView { D3D11_DEPTH_STENCIL_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; desc.Format = DXGI_FORMAT_D32_FLOAT; // Make the view see this as D32_FLOAT instead of typeless desc.Texture2D.MipSlice = 0; V(m_device->CreateDepthStencilView(m_selectionDepthStencilTexture, &desc, &m_selectionDepthStencilView)); } // create m_selectionDepthStencilSRV { D3D11_SHADER_RESOURCE_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the shaders see this as R32_FLOAT instead of typeless desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; desc.Texture2D.MipLevels = 1; desc.Texture2D.MostDetailedMip = 0; V(m_device->CreateShaderResourceView(m_selectionDepthStencilTexture, &desc, &m_selectionDepthStencilSRV)); } // create m_selectionTextureForCPU { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = RenderTarget_Size; desc.Height = RenderTarget_Size; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R32_FLOAT; // Use a typeless type here so that it can be both depth-stencil and shader resource. desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_STAGING; desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; desc.MiscFlags = 0; V(m_device->CreateTexture2D(&desc, NULL, &m_selectionTextureForCPU)); } // create a new Depth-Stencil texture { D3D11_TEXTURE2D_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Width = sd->Width; desc.Height = sd->Height; desc.MipLevels = 1; desc.ArraySize = 1; desc.Format = DXGI_FORMAT_R32_TYPELESS; // Use a typeless type here so that it can be both depth-stencil and shader resource. desc.SampleDesc.Count = sd->SampleDesc.Count; desc.SampleDesc.Quality = sd->SampleDesc.Quality; desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; V(m_device->CreateTexture2D(&desc, NULL, &m_DSTexture)); } // create Depth-Stencil view { D3D11_DEPTH_STENCIL_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D; desc.Format = DXGI_FORMAT_D32_FLOAT; // Make the view see this as D32_FLOAT instead of typeless desc.Texture2D.MipSlice = 0; V(m_device->CreateDepthStencilView(m_DSTexture, &desc, &m_DSView)); } // create Depth-Stencil shader resource view { D3D11_SHADER_RESOURCE_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Format = DXGI_FORMAT_R32_FLOAT; // Make the shaders see this as R32_FLOAT instead of typeless desc.ViewDimension = sd->SampleDesc.Count > 1 ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D; desc.Texture2D.MipLevels = 1; desc.Texture2D.MostDetailedMip = 0; V(m_device->CreateShaderResourceView(m_DSTexture, &desc, &m_DSTextureSRV)); } // setup viewport m_viewport.Width = (FLOAT)sd->Width; m_viewport.Height = (FLOAT)sd->Height; m_viewport.MinDepth = 0; m_viewport.MaxDepth = 1; m_viewport.TopLeftX = 0; m_viewport.TopLeftY = 0; // setup shadows m_shadow.setScreenResolution(0, sd->Width, sd->Height, sd->SampleDesc.Count, nullptr); } void Renderer::setAllConstantBuffers(ID3D11DeviceContext* ctx) { ID3D11Buffer* cbs[3] = { m_cameraCB, m_worldCB, m_objectCB }; ctx->VSSetConstantBuffers(0, 3, cbs); ctx->GSSetConstantBuffers(0, 3, cbs); ctx->PSSetConstantBuffers(0, 3, cbs); } void Renderer::Render(ID3D11Device* /*device*/, ID3D11DeviceContext* ctx, ID3D11RenderTargetView* pRTV, ID3D11DepthStencilView*) { GlobalSettings& globalSettings = GlobalSettings::Inst(); if (!globalSettings.m_showGraphicsMesh) return; PROFILER_SCOPED_FUNCTION(); m_context = ctx; ctx->ClearDepthStencilView(m_DSView, D3D11_CLEAR_DEPTH, 1.0, 0); ctx->RSSetViewports(1, &m_viewport); // needed matrices DirectX::XMMATRIX viewMatrix = SimpleScene::Inst()->GetViewMatrix(); DirectX::XMMATRIX projMatrix = SimpleScene::Inst()->GetProjMatrix(); DirectX::XMMATRIX projMatrixInv = DirectX::XMMatrixInverse(NULL, projMatrix); DirectX::XMMATRIX viewProjMatrix = viewMatrix * projMatrix; // Fill Camera constant buffer { D3D11_MAPPED_SUBRESOURCE mappedResource; ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; cameraBuffer->viewProjection = viewProjMatrix; cameraBuffer->projectionInv = projMatrixInv; DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), SimpleScene::Inst()->GetEyePt()); ctx->Unmap(m_cameraCB, 0); } // Fill World constant buffer { D3D11_MAPPED_SUBRESOURCE mappedResource; ctx->Map(m_worldCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBWorld* worldBuffer = (CBWorld*)mappedResource.pData; float flatNormal = -1.0; if (globalSettings.m_renderStyle == MESH_RENDER_FLAT) { flatNormal = 1.0; } float useLighting = 1.0; if (!globalSettings.m_useLighting) { useLighting = -1.0; } m_worldCBData.flatNormal = flatNormal; m_worldCBData.wireFrameOver = -1.0; m_worldCBData.useLighting = useLighting; Light::FillLightShaderParam(m_worldCBData.lightParam); memcpy(worldBuffer, &m_worldCBData, sizeof(m_worldCBData)); //worldBuffer->ambientColor = m_CBWorldData.ambientColor; //worldBuffer->pointLightPos = m_CBWorldData.pointLightPos; //worldBuffer->pointLightColor = m_CBWorldData.pointLightColor; //worldBuffer->dirLightDir = m_CBWorldData.dirLightDir; //worldBuffer->specularPower = m_CBWorldData.specularPower; //worldBuffer->dirLightColor = m_CBWorldData.dirLightColor; //worldBuffer->specularIntensity = m_CBWorldData.specularIntensity; ctx->Unmap(m_worldCB, 0); } if (globalSettings.m_renderStyle != MESH_RENDER_WIREFRAME) { ctx->RSSetState(m_RSState[0]); } else { ctx->RSSetState(m_RSState[1]); } ctx->PSSetSamplers(0, 1, &m_linearSampler); ctx->PSSetSamplers(1, 1, &m_pointSampler); if (m_shadowEnabled) { // render depth only { ctx->OMSetRenderTargets(0, nullptr, m_DSView); ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); // set constants buffers setAllConstantBuffers(ctx); for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if (!(*it)->isTransparent() && !(*it)->isHidden()) (*it)->renderDepthStencilOnly(*this); } } m_shadow.clearBuffer(); std::vector& lights = Light::GetDefaultLights(); for (int l = 0; l < 3; l++) { if (!lights[l].m_useShadows) { continue; } atcore_float3 eye = lights[l].m_lightCamera._eye; eye.x = -eye.x; atcore_float3 at = lights[l].m_lightCamera._at; at.x = -at.x; ctx->OMSetRenderTargets(0, nullptr, m_DSView); m_shadow.renderShadowMaps(this, eye, at); ctx->OMSetRenderTargets(0, nullptr, nullptr); m_shadow.renderShadowBuffer(m_DSTextureSRV, nullptr); } m_shadow.finalizeBuffer(); } // Opaque render { ctx->RSSetViewports(1, &m_viewport); ctx->OMSetRenderTargets(1, &pRTV, m_DSView); ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); // set constants buffers setAllConstantBuffers(ctx); // Fill Camera constant buffer { D3D11_MAPPED_SUBRESOURCE mappedResource; ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; cameraBuffer->viewProjection = viewProjMatrix; cameraBuffer->projectionInv = projMatrixInv; DirectX::XMStoreFloat3(&(cameraBuffer->viewPos), SimpleScene::Inst()->GetEyePt()); ctx->Unmap(m_cameraCB, 0); } std::vector renderablesWithoutDepthTest; // Render opaque renderables m_visibleOpaqueRenderablesCount = 0; for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if (!(*it)->isTransparent() && !(*it)->isHidden()) { if (!(*it)->isDepthTest()) { renderablesWithoutDepthTest.push_back(*it); continue; } (*it)->render(*this); m_visibleOpaqueRenderablesCount++; } } if (renderablesWithoutDepthTest.size() > 0) { ctx->OMSetDepthStencilState(m_opaqueRenderNoDepthDSState, 0xFF); std::vector::iterator itR; for (itR = renderablesWithoutDepthTest.begin(); itR != renderablesWithoutDepthTest.end(); itR++) { (*itR)->render(*this); } ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); } } // draw overline if (globalSettings.m_showWireframe) { if (globalSettings.m_renderStyle != MESH_RENDER_WIREFRAME) { ctx->RSSetState(m_RSState[1]); } // update wireFrameOver { D3D11_MAPPED_SUBRESOURCE mappedResource; ctx->Map(m_worldCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBWorld* worldBuffer = (CBWorld*)mappedResource.pData; float wireFrameOver = -1.0; { if (globalSettings.m_showWireframe) { wireFrameOver = 1.0; } } m_worldCBData.wireFrameOver = wireFrameOver; memcpy(worldBuffer, &m_worldCBData, sizeof(m_worldCBData)); ctx->Unmap(m_worldCB, 0); } for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if (!(*it)->isTransparent() && !(*it)->isHidden()) { (*it)->render(*this); } } if (globalSettings.m_renderStyle != MESH_RENDER_WIREFRAME) { ctx->RSSetState(m_RSState[0]); } } // modulate shadows if (m_shadowEnabled && globalSettings.m_useLighting) { m_shadow.modulateShadowBuffer(pRTV); } // render AO if (m_HBAOEnabled) { m_HBAO.renderAO(m_context, pRTV, m_DSTextureSRV, projMatrix); } ctx->RSSetViewports(1, &m_viewport); // render debug render buffers if (!AppMainWindow::Inst().m_bGizmoWithDepthTest) { ctx->OMSetDepthStencilState(m_opaqueRenderNoDepthDSState, 0xFF); } while (m_queuedRenderBuffers.size() > 0) { render(m_queuedRenderBuffers.back()); m_queuedRenderBuffers.pop_back(); } while (m_screenRenderBuffers.size() > 0) { render(m_screenRenderBuffers.back(), true); m_screenRenderBuffers.pop_back(); } // Transparency render ctx->OMSetRenderTargets(1, &pRTV, m_DSView); ctx->OMSetDepthStencilState(m_transparencyRenderDSState, 0xFF); // depth as SRV isn't used now (uncommenting will produce a warning, probably need readonly depth?) //ctx->PSSetShaderResources(1, 1, &mDSTextureSRV); // Render transparent renderables m_visibleTransparentRenderablesCount = 0; for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if ((*it)->isTransparent() && !(*it)->isHidden()) { (*it)->render(*this); m_visibleTransparentRenderablesCount++; } } // shadows debug render if (0) { m_shadow.displayMapFrustums(pRTV, m_DSView); } // Reset RT and SRV state ID3D11ShaderResourceView* nullAttach[16] = { nullptr }; ctx->PSSetShaderResources(0, 16, nullAttach); ctx->OMSetRenderTargets(0, nullptr, nullptr); } LRESULT Renderer::MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PX_UNUSED(hWnd); PX_UNUSED(wParam); PX_UNUSED(lParam); if (uMsg == WM_KEYDOWN || uMsg == WM_KEYUP) { // Camera overspeed event int iKeyPressed = static_cast(wParam); if (iKeyPressed == VK_SHIFT) { toggleCameraSpeed(uMsg == WM_KEYDOWN); } } UpdateCamera(); return 0; // Camera events return m_camera.HandleMessages(hWnd, uMsg, wParam, lParam); } void Renderer::Animate(double fElapsedTimeSeconds) { PROFILER_SCOPED_FUNCTION(); m_camera.FrameMove((float)fElapsedTimeSeconds); } void Renderer::renderDepthOnly(DirectX::XMMATRIX* viewProjectionSubstitute) { // Fill Camera constant buffer if (viewProjectionSubstitute) { D3D11_MAPPED_SUBRESOURCE mappedResource; m_context->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; cameraBuffer->viewProjection = *viewProjectionSubstitute; m_context->Unmap(m_cameraCB, 0); } // set constants buffers setAllConstantBuffers(m_context); // render for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if (!(*it)->isTransparent() && !(*it)->isHidden()) (*it)->renderDepthStencilOnly(*this); } } void Renderer::render(const PxRenderBuffer* renderBuffer, bool bScreen) { // points uint32_t pointsCount = renderBuffer->getNbPoints(); if (pointsCount > 0) { RenderDebugVertex* verts = new RenderDebugVertex[pointsCount]; const PxDebugPoint* points = renderBuffer->getPoints(); for (uint32_t i = 0; i < pointsCount; i++) { verts[i].mPos = points[i].pos; verts[i].mColor = points[i].color; } renderDebugPrimitive(verts, pointsCount, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); delete[] verts; } // lines uint32_t linesCount = renderBuffer->getNbLines(); if (linesCount > 0) { RenderDebugVertex* verts = new RenderDebugVertex[linesCount * 2]; const PxDebugLine* lines = renderBuffer->getLines(); for (uint32_t i = 0; i < linesCount; i++) { verts[i * 2].mPos = lines[i].pos0; verts[i * 2].mColor = lines[i].color0; verts[i * 2 + 1].mPos = lines[i].pos1; verts[i * 2 + 1].mColor = lines[i].color1; } renderDebugPrimitive(verts, linesCount * 2, D3D11_PRIMITIVE_TOPOLOGY_LINELIST, bScreen); delete[] verts; } // triangles uint32_t trianglesCount = renderBuffer->getNbTriangles(); if (trianglesCount > 0) { RenderDebugVertex* verts = new RenderDebugVertex[trianglesCount * 3]; const PxDebugTriangle* triangles = renderBuffer->getTriangles(); for (uint32_t i = 0; i < trianglesCount; i++) { verts[i * 3].mPos = triangles[i].pos0; verts[i * 3].mColor = triangles[i].color0; verts[i * 3 + 1].mPos = triangles[i].pos1; verts[i * 3 + 1].mColor = triangles[i].color1; verts[i * 3 + 2].mPos = triangles[i].pos2; verts[i * 3 + 2].mColor = triangles[i].color2; } renderDebugPrimitive(verts, trianglesCount * 3, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); delete[] verts; } // texts? // .... } void Renderer::renderDebugPrimitive(const Renderer::RenderDebugVertex *vertices, uint32_t verticesCount, D3D11_PRIMITIVE_TOPOLOGY topology, bool bScreen) { m_context->IASetPrimitiveTopology(topology); if (bScreen) { m_screenPrimitiveRenderMaterialInstance->bind(*m_context, 0); } else { m_debugPrimitiveRenderMaterialInstance->bind(*m_context, 0); } D3D11_MAPPED_SUBRESOURCE mappedResource; m_context->Map(m_objectCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBObject* objectBuffer = (CBObject*)mappedResource.pData; objectBuffer->worldMatrix = PxMat44ToXMMATRIX(PxMat44(PxIdentity)); m_context->Unmap(m_objectCB, 0); if (m_debugPrimitiveVBVerticesCount < verticesCount) { m_debugPrimitiveVBVerticesCount = verticesCount; SAFE_RELEASE(m_debugPrimitiveVB); D3D11_BUFFER_DESC bufferDesc; memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.ByteWidth = sizeof(Renderer::RenderDebugVertex) * m_debugPrimitiveVBVerticesCount; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; bufferDesc.Usage = D3D11_USAGE_DEFAULT; V(m_device->CreateBuffer(&bufferDesc, NULL, &m_debugPrimitiveVB)); } CD3D11_BOX box(0, 0, 0, (LONG)(sizeof(Renderer::RenderDebugVertex) * verticesCount), 1, 1); m_context->UpdateSubresource(m_debugPrimitiveVB, 0, &box, vertices, 0, 0); ID3D11Buffer* pBuffers[1] = { m_debugPrimitiveVB }; UINT strides[1] = { sizeof(RenderDebugVertex) }; UINT offsets[1] = { 0 }; m_context->IASetVertexBuffers(0, 1, pBuffers, strides, offsets); m_context->Draw(verticesCount, 0); } IRenderMesh* Renderer::getPrimitiveRenderMesh(PrimitiveRenderMeshType::Enum type) { if (m_primitiveRenderMeshes[type] == NULL) { switch (type) { case PrimitiveRenderMeshType::Box: m_primitiveRenderMeshes[type] = new BoxRenderMesh(); break; case PrimitiveRenderMeshType::Plane: m_primitiveRenderMeshes[type] = new PlaneRenderMesh(); break; case PrimitiveRenderMeshType::Sphere: m_primitiveRenderMeshes[type] = new SphereRenderMesh(); break; // Add By Lixu Begin case PrimitiveRenderMeshType::Cone: m_primitiveRenderMeshes[type] = new ConeRenderMesh(); break; // Add By Lixu End default: PX_ALWAYS_ASSERT_MESSAGE("Unsupported PxGeometryType"); return NULL; } } return m_primitiveRenderMeshes[type]; } Renderable* Renderer::createRenderable(IRenderMesh& mesh, RenderMaterial& material) { Renderable* renderable = new Renderable(mesh, material); m_renderables.emplace(renderable); return renderable; } void Renderer::removeRenderable(Renderable* r) { m_renderables.erase(m_renderables.find(r)); delete r; } void Renderer::toggleCameraSpeed(bool overspeed) { m_camera.SetScalers(0.002f, overspeed ? 150.f : 25.f); } void Renderer::reloadShaders() { // iterate Renderables materials and call reload() std::set materials; for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { materials.emplace(&((*it)->getMaterial())); } for (std::set::iterator it = materials.begin(); it != materials.end(); it++) { (*it)->reload(); } } void Renderer::drawUI() { // Lighting if (ImGui::TreeNode("Lighting")) { ImGui::ColorEdit3("Ambient Color", &(m_worldCBData.ambientColor.x)); ImGui::ColorEdit3("Point Light Color", &(m_worldCBData.pointLightColor.x)); ImGui::DragFloat3("Point Light Pos", &(m_worldCBData.pointLightPos.x)); ImGui::ColorEdit3("Dir Light Color", &(m_worldCBData.dirLightColor.x)); ImGui_DragFloat3Dir("Dir Light Dir", &(m_worldCBData.dirLightDir.x)); ImGui::DragFloat("Specular Power", &(m_worldCBData.specularPower), 1.0f, 1.0f, 500.0f); ImGui::DragFloat("Specular Intensity", &(m_worldCBData.specularIntensity), 0.01f, 0.0f, 2.0f); ImGui::TreePop(); } // Shadow if (ImGui::TreeNode("Shadow")) { ImGui::Checkbox("Shadows Enabled", &m_shadowEnabled); if (m_shadowEnabled) { m_shadow.drawUI(); } ImGui::TreePop(); } // HBAO+ if (ImGui::TreeNode("HBAO+")) { ImGui::Checkbox("HBAO Enabled", &(m_HBAOEnabled)); if (m_HBAOEnabled) { m_HBAO.drawUI(); } ImGui::TreePop(); } } void Renderer::UpdateCamera() { Camera* pCamera = SimpleScene::Inst()->m_pCamera; DirectX::XMVECTORF32 eyePt = { pCamera->_eye.x, pCamera->_eye.y, pCamera->_eye.z, 0 }; DirectX::XMVECTORF32 lookAtPt = { pCamera->_at.x, pCamera->_at.y, pCamera->_at.z, 0 }; m_camera.SetViewParams(eyePt, lookAtPt); m_camera.SetProjParams(pCamera->_fov, pCamera->_aspectRatio, pCamera->_znear, pCamera->_zfar); } bool _pointInPolygon(std::vector& screenPoints, PxVec2& test) { int polySides = screenPoints.size(); int i, j = polySides - 1; bool oddNodes = false; for (i = 0; i < polySides; i++) { if ((screenPoints[i].y < test.y && screenPoints[j].y >= test.y || screenPoints[j].y = test.y) && (screenPoints[i].x <= test.x || screenPoints[j].x <= test.x)) { float temp = (test.y - screenPoints[i].y) / (screenPoints[j].y - screenPoints[i].y) * (screenPoints[j].x - screenPoints[i].x); oddNodes ^= (screenPoints[i].x + temp < test.x); } j = i; } return oddNodes; } void Renderer::fetchSelection(std::vector& screenPoints, std::map>& selection) { PROFILER_SCOPED_FUNCTION(); selection.clear(); int pointSize = screenPoints.size(); if (pointSize == 0) { return; } GlobalSettings& globalSettings = GlobalSettings::Inst(); if (!globalSettings.m_showGraphicsMesh) return; ID3D11DeviceContext* ctx = m_context; // needed matrices DirectX::XMMATRIX viewMatrix = SimpleScene::Inst()->GetViewMatrix(); DirectX::XMMATRIX projMatrix = SimpleScene::Inst()->GetProjMatrix(); DirectX::XMMATRIX projMatrixInv = DirectX::XMMatrixInverse(NULL, projMatrix); DirectX::XMMATRIX viewProjMatrix = viewMatrix * projMatrix; // Fill Camera constant buffer { D3D11_MAPPED_SUBRESOURCE mappedResource; ctx->Map(m_cameraCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); CBCamera* cameraBuffer = (CBCamera*)mappedResource.pData; cameraBuffer->viewProjection = viewProjMatrix; ctx->Unmap(m_cameraCB, 0); } int width = RenderTarget_Size; int height = RenderTarget_Size; float init_data = SelectionTexture_InitData; int dataSize = width * height; if (m_selectionTextureData.size() != dataSize) { m_selectionTextureData.resize(dataSize); } std::fill(m_selectionTextureData.begin(), m_selectionTextureData.end(), init_data); ctx->OMSetRenderTargets(1, &m_selectionRenderTargetView, m_selectionDepthStencilView); float ClearColor[4] = { init_data, init_data, init_data, init_data }; ctx->ClearRenderTargetView(m_selectionRenderTargetView, ClearColor); ctx->ClearDepthStencilView(m_selectionDepthStencilView, D3D11_CLEAR_DEPTH, 1.0, 0); D3D11_VIEWPORT vp = { 0.0f, 0.0f, (float)width, (float)height, 0.0f, 1.0f }; ctx->RSSetViewports(1, &vp); ctx->RSSetState(m_RSState[0]); ctx->OMSetDepthStencilState(m_opaqueRenderDSState, 0xFF); // set constants buffers setAllConstantBuffers(ctx); bFetchSelection = true; // Render renderables for (auto it = m_renderables.begin(); it != m_renderables.end(); it++) { if (!(*it)->isHidden()) { (*it)->render(*this); } } bFetchSelection = false; { ctx->CopyResource(m_selectionTextureForCPU, m_selectionRenderTargetTexture); D3D11_MAPPED_SUBRESOURCE mapResource; HRESULT hr = ctx->Map(m_selectionTextureForCPU, 0, D3D11_MAP_READ, NULL, &mapResource); memcpy(m_selectionTextureData.data(), mapResource.pData, dataSize * sizeof(float)); ctx->Unmap(m_selectionTextureForCPU, 0); } std::set vids; if (pointSize == 1) { // point selection int centerX = screenPoints[0].x * width; int centerY = screenPoints[0].y * height; int ds = centerY * width + centerX; int vid = m_selectionTextureData[ds]; vids.emplace(vid); } else if (pointSize == 2) { // rect selection PxVec2 lefttop = screenPoints[0]; PxVec2 rightbottom = screenPoints[1]; int startX = lefttop.x * width; int startY = lefttop.y * height; int endX = rightbottom.x * width; int endY = rightbottom.y * height; for (int h = startY; h <= endY; h++) { for (int w = startX; w <= endX; w++) { int ds = h * width + w; int vid = m_selectionTextureData[ds]; vids.emplace(vid); } } } else { // draw selection PxVec2 pMin, pMax; pMin = pMax = screenPoints[0]; for (int ps = 1; ps < pointSize; ps++) { PxVec2& p = screenPoints[ps]; if (p.x < pMin.x) { pMin.x = p.x; } if (p.y < pMin.y) { pMin.y = p.y; } if (p.x > pMax.x) { pMax.x = p.x; } if (p.y > pMax.y) { pMax.y = p.y; } } int startX = pMin.x * width; int startY = pMin.y * height; int endX = pMax.x * width; int endY = pMax.y * height; for (int h = startY; h <= endY; h++) { for (int w = startX; w <= endX; w++) { PxVec2 test(1.0 * w / width, 1.0 * h / height); bool valid = _pointInPolygon(screenPoints, test); if (valid) { int ds = h * width + w; int vid = m_selectionTextureData[ds]; vids.emplace(vid); } } } } int familyId, chunkId; for (int vid : vids) { if (vid < 0) { continue; } Renderable::getFamilyChunkId(vid, familyId, chunkId); selection[familyId].emplace(chunkId); } }