diff --git a/HPL2/include/graphics/RenderList.h b/HPL2/include/graphics/RenderList.h index 45bc0d9d2..acb258ac0 100644 --- a/HPL2/include/graphics/RenderList.h +++ b/HPL2/include/graphics/RenderList.h @@ -21,6 +21,7 @@ #include "graphics/Enum.h" #include #include +#include namespace hpl { @@ -36,20 +37,25 @@ namespace hpl { cRenderList(); ~cRenderList(); + [[deprecated("use BeginAndReset")]] void Setup(float afFrameTime, cFrustum *apFrustum); + [[deprecated("Use BeginAndReset")]] + void Clear(); void AddObject(iRenderable *apObject); + [[deprecated("Use End")]] void Compile(tRenderListCompileFlag aFlags); bool ArrayHasObjects(eRenderListType aType); - + std::span GetRenderableItems(eRenderListType aType); std::span GetOcclusionQueryItems(); std::span GetFogAreas(); std::span GetLights(); - void Clear(); + void BeginAndReset(float frameTime, cFrustum* frustum); + void End(tRenderListCompileFlag aFlags); iLight* GetLight(int alIdx){ return m_lights[alIdx];} int GetLightNum(){ return(int)m_lights.size();} @@ -67,8 +73,8 @@ namespace hpl { iRenderable* GetTransObject(int alIdx){ return m_transObjects[alIdx];} private: - float m_frameTime; - cFrustum* m_frustum; + float m_frameTime = 0.0f; + cFrustum* m_frustum = nullptr; std::vector m_occlusionQueryObjects; std::vector m_solidObjects; @@ -77,8 +83,7 @@ namespace hpl { std::vector m_illumObjects; std::vector m_lights; std::vector m_fogAreas; - - tRenderableVec m_sortedArrays[eRenderListType_LastEnum]; + std::array,eRenderListType_LastEnum> m_sortedArrays; }; //--------------------------------------------- diff --git a/HPL2/include/graphics/Renderer.h b/HPL2/include/graphics/Renderer.h index 4d2f0308b..58cfd9c93 100644 --- a/HPL2/include/graphics/Renderer.h +++ b/HPL2/include/graphics/Renderer.h @@ -170,7 +170,7 @@ namespace hpl { friend class cRenderSettings; public: - iRenderer(const tString& asName, cGraphics *apGraphics,cResources* apResources, int alNumOfProgramComboModes); + iRenderer(const tString& asName, cGraphics *apGraphics,cResources* apResources); virtual ~iRenderer(); // plan to just use the single draw call need to call BeginRendering to setup state diff --git a/HPL2/include/graphics/RendererDeferred.h b/HPL2/include/graphics/RendererDeferred.h index 09ed12221..af4df18cb 100644 --- a/HPL2/include/graphics/RendererDeferred.h +++ b/HPL2/include/graphics/RendererDeferred.h @@ -21,6 +21,7 @@ #include "engine/RTTI.h" #include "scene/Viewport.h" +#include "scene/World.h" #include "windowing/NativeWindow.h" #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -76,15 +78,20 @@ namespace hpl { static constexpr TinyImageFormat SpecularBufferFormat = TinyImageFormat_R8G8_UNORM; static constexpr TinyImageFormat ColorBufferFormat = TinyImageFormat_R8G8B8A8_UNORM; static constexpr TinyImageFormat ShadowDepthBufferFormat = TinyImageFormat_D32_SFLOAT; + static constexpr uint32_t MaxReflectionBuffers = 4; static constexpr uint32_t MaxObjectUniforms = 4096; static constexpr uint32_t MaxLightUniforms = 1024; static constexpr uint32_t MaxHiZMipLevels = 10; - static constexpr uint32_t MaxMaterialFrameDescriptors = 256; + static constexpr uint32_t MaxViewportFrameDescriptors = 256; static constexpr uint32_t MaxMaterialSamplers = static_cast(eTextureWrap_LastEnum) * static_cast(eTextureFilter_LastEnum) * static_cast(cMaterial::TextureAntistropy::Antistropy_Count); static constexpr uint32_t MaxObjectTest = 32768; static constexpr uint32_t MaxOcclusionDescSize = 4096; static constexpr uint32_t MaxQueryPoolSize = MaxOcclusionDescSize * 2; + static constexpr uint32_t TranslucencyBlendModeMask = 0xf; + + static constexpr uint32_t TranslucencyReflectionBufferMask = 0x7; + static constexpr uint32_t TranslucencyReflectionBufferOffset = 4; enum LightConfiguration { HasGoboMap = 0x1, HasShadowMap = 0x2 }; enum LightPipelineVariants { @@ -94,13 +101,11 @@ namespace hpl { LightPipelineVariant_Size = 4, }; - - static constexpr uint32_t TranslucencyBlendModeMask = 0xf; enum TranslucencyFlags { - UseIlluminationTrans = (1 << 4), - UseReflectionTrans = (1 << 5), - UseRefractionTrans = (1 << 6), - UseFog = (1 << 7), + UseIlluminationTrans = (1 << 7), + UseReflectionTrans = (1 << 8), + UseRefractionTrans = (1 << 9), + UseFog = (1 << 10), }; struct MaterialRootConstant { uint32_t objectId; @@ -201,20 +206,19 @@ namespace hpl { float m_fogFalloffExp; }; - class ShadowMapData { public: SharedRenderTarget m_target; - iLight* m_light; uint32_t m_transformCount = 0; uint32_t m_frameCount = 0; float m_radius = 0.0f; float m_fov = 0.0f; float m_aspect = 0.0f; - CmdPool* m_pool; - Cmd* m_cmd = nullptr; - Fence* m_shadowFence = nullptr; + iLight* m_light = nullptr; + SharedCmdPool m_pool; + SharedCmd m_cmd; + SharedFence m_shadowFence; }; struct FogRendererData { @@ -237,7 +241,8 @@ namespace hpl { , m_outputBuffer(std::move(buffer.m_outputBuffer)) , m_refractionImage(std::move(buffer.m_refractionImage)) , m_hizDepthBuffer(std::move(buffer.m_hizDepthBuffer)) - , m_hiZMipCount(buffer.m_hiZMipCount) { + , m_preZPassRenderables(std::move(buffer.m_preZPassRenderables)) + { } void operator=(GBuffer&& buffer) { m_colorBuffer = std::move(buffer.m_colorBuffer); @@ -248,11 +253,12 @@ namespace hpl { m_outputBuffer = std::move(buffer.m_outputBuffer); m_refractionImage = std::move(buffer.m_refractionImage); m_hizDepthBuffer = std::move(buffer.m_hizDepthBuffer); - m_hiZMipCount = buffer.m_hiZMipCount; + m_preZPassRenderables = std::move(buffer.m_preZPassRenderables); } + std::set m_preZPassRenderables; + SharedTexture m_refractionImage; SharedRenderTarget m_hizDepthBuffer; - uint8_t m_hiZMipCount; SharedRenderTarget m_colorBuffer; SharedRenderTarget m_normalBuffer; @@ -260,6 +266,43 @@ namespace hpl { SharedRenderTarget m_specularBuffer; SharedRenderTarget m_depthBuffer; SharedRenderTarget m_outputBuffer; + + bool isValid() { + return m_refractionImage.IsValid() + && m_hizDepthBuffer.IsValid() + && m_colorBuffer.IsValid() + && m_normalBuffer.IsValid() + && m_positionBuffer.IsValid() + && m_specularBuffer.IsValid() + && m_depthBuffer.IsValid() + && m_outputBuffer.IsValid(); + } + }; + + struct ReflectionGBuffer { + iRenderable* m_target = nullptr; + + uint32_t m_frameCount = 0; + GBuffer m_buffer; + SharedCmdPool m_pool; + SharedCmd m_cmd; + SharedFence m_fence; + + ReflectionGBuffer() = default; + ReflectionGBuffer(ReflectionGBuffer&& buffer): + m_pool(std::move(buffer.m_pool)), + m_cmd(std::move(buffer.m_cmd)), + m_fence(std::move(buffer.m_fence)), + m_buffer(std::move(buffer.m_buffer)), + m_frameCount(buffer.m_frameCount){ + } + void operator=(ReflectionGBuffer&& buffer) { + m_pool = std::move(buffer.m_pool); + m_cmd = std::move(buffer.m_cmd); + m_fence = std::move(buffer.m_fence); + m_buffer = std::move(buffer.m_buffer); + m_frameCount= buffer.m_frameCount; + } }; struct ViewportData { @@ -270,7 +313,7 @@ namespace hpl { : m_size(buffer.m_size) , m_refractionImage(std::move(buffer.m_refractionImage)) , m_gBuffer(std::move(buffer.m_gBuffer)) - , m_gBufferReflection(std::move(buffer.m_gBufferReflection)) { + , m_reflectionBuffer(std::move(buffer.m_reflectionBuffer)) { } ViewportData& operator=(const ViewportData&) = delete; @@ -279,13 +322,13 @@ namespace hpl { m_size = buffer.m_size; m_refractionImage = std::move(buffer.m_refractionImage); m_gBuffer = std::move(buffer.m_gBuffer); - m_gBufferReflection = std::move(buffer.m_gBufferReflection); + m_reflectionBuffer = std::move(buffer.m_reflectionBuffer); } cVector2l m_size = cVector2l(0, 0); std::array m_gBuffer; + std::array m_reflectionBuffer; std::shared_ptr m_refractionImage; - GBuffer m_gBufferReflection; }; cRendererDeferred(cGraphics* apGraphics, cResources* apResources); @@ -314,15 +357,12 @@ namespace hpl { cRenderSettings* apSettings, bool abSendFrameBufferToPostEffects) override; - private: LegacyRenderTarget& resolveRenderTarget(std::array& rt); std::shared_ptr& resolveRenderImage(std::array, 2>& img); iVertexBuffer* GetLightShape(iLight* apLight, eDeferredShapeQuality aQuality) const; struct PerObjectOption { - cMatrixf m_viewMat; - cMatrixf m_projectionMat; std::optional m_modelMatrix = std::nullopt; }; struct PerFrameOption { @@ -330,13 +370,79 @@ namespace hpl { cMatrixf m_viewMat; cMatrixf m_projectionMat; }; + void RebuildGBuffer(ForgeRenderer& renderer,GBuffer& buffer, uint32_t width, uint32_t height); + struct AdditionalGbufferPassOptions { + bool m_invert = false; + }; + + void cmdBuildPrimaryGBuffer(const ForgeRenderer::Frame& frame, Cmd* cmd, + uint32_t frameDescriptorIndex, + RenderTarget* colorBuffer, + RenderTarget* normalBuffer, + RenderTarget* positionBuffer, + RenderTarget* specularBuffer, + RenderTarget* depthBuffer, + AdditionalGbufferPassOptions options + ); + + struct AdditionalLightPassOptions { + bool m_invert = false; + }; + void cmdLightPass(Cmd* cmd, + const ForgeRenderer::Frame& frame, + cWorld* apWorld, + cFrustum* apFrustum, + cRenderList& renderList, + uint32_t frameDescriptorIndex, + RenderTarget* colorBuffer, + RenderTarget* normalBuffer, + RenderTarget* positionBuffer, + RenderTarget* specularBuffer, + RenderTarget* depthBuffer, + RenderTarget* outputBuffer, + cMatrixf viewMat, + cMatrixf invViewMat, + cMatrixf projectionMat, + AdditionalLightPassOptions options); + + struct AdditionalIlluminationPassOptions { + bool m_invert = false; + }; + void cmdIlluminationPass(Cmd* cmd, + const ForgeRenderer::Frame& frame, + cRenderList& renderList, + uint32_t frameDescriptorIndex, + RenderTarget* depthBuffer, + RenderTarget* outputBuffer, + AdditionalIlluminationPassOptions options + ); + + struct AdditionalZPassOptions { + tRenderableFlag objectVisibilityFlags = eRenderableFlag_VisibleInNonReflection; + std::span clipPlanes = {}; + bool m_invert = false; + bool m_disableOcclusionQueries = false; + }; + void cmdPreAndPostZ( + Cmd* cmd, + std::set& prePassRenderables, + const ForgeRenderer::Frame& frame, + cRenderList& renderList, + float frameTime, + RenderTarget* depthBuffer, + RenderTarget* hiZBuffer, + cFrustum* apFrustum, + uint32_t frameDescriptorIndex, + cMatrixf viewMat, + cMatrixf projectionMat, + AdditionalZPassOptions flags); uint32_t updateFrameDescriptor(const ForgeRenderer::Frame& frame,Cmd* cmd, cWorld* apWorld,const PerFrameOption& options); uint32_t cmdBindMaterialAndObject(Cmd* cmd, const ForgeRenderer::Frame& frame, cMaterial* apMaterial, iRenderable* apObject, - const PerObjectOption& option); + std::optional modelMatrix = std::nullopt); std::array, eDeferredShapeQuality_LastEnum> m_shapeSphere; std::unique_ptr m_shapePyramid; @@ -360,10 +466,11 @@ namespace hpl { SharedTexture m_ssaoScatterDiskTexture; Image* m_dissolveImage; - std::array m_perFrameBuffer; + std::array m_perFrameBuffer; // decal pass std::array m_decalPipeline; + std::array m_decalPipelineCW; SharedShader m_decalShader; struct Fog { @@ -402,11 +509,15 @@ namespace hpl { SharedShader m_solidDiffuseParallaxShader; SharedPipeline m_solidDiffusePipeline; SharedPipeline m_solidDiffuseParallaxPipeline; + + SharedPipeline m_solidDiffusePipelineCW; + SharedPipeline m_solidDiffuseParallaxPipelineCW; } m_materialSolidPass; // illumination pass SharedShader m_solidIlluminationShader; - SharedPipeline m_solidIlluminationPipeline; + SharedPipeline m_solidIlluminationPipelineCCW; + SharedPipeline m_solidIlluminationPipelineCW; // translucency pass struct TranslucencyPipeline { @@ -485,13 +596,16 @@ namespace hpl { SharedTexture m_falloffMap; SharedTexture m_attenuationLightMap; }; + folly::F14ValueMap m_lightDescriptorLookup; std::array, ForgeRenderer::SwapChainLength> m_lightResources{}; // z pass SharedShader m_zPassShader; - SharedPipeline m_zPassPipeline; + SharedPipeline m_zPassPipelineCCW; + SharedPipeline m_zPassPipelineCW; + SharedPipeline m_zPassShadowPipelineCW; SharedPipeline m_zPassShadowPipelineCCW; - std::set m_preZPassRenderables; + std::array m_objectUniformBuffer; struct MaterialPassDescriptorSet { @@ -573,7 +687,8 @@ namespace hpl { std::array m_lightPassBuffer; SharedRootSignature m_lightPassRootSignature; - SharedPipeline m_lightStencilPipeline; + SharedPipeline m_lightStencilPipelineCCW; + SharedPipeline m_lightStencilPipelineCW; std::array m_pointLightPipeline; std::array m_boxLightPipeline; std::array m_spotLightPipeline; @@ -583,6 +698,7 @@ namespace hpl { SharedShader m_boxLightShader; std::array m_lightPerLightSet; std::array m_lightPerFrameSet; + uint32_t m_lightIndex = 0; SharedSampler m_shadowCmpSampler; SharedSampler m_samplerPointClampToBorder; @@ -590,7 +706,8 @@ namespace hpl { SharedSampler m_goboSampler; SharedSampler m_bilinearSampler; - cRenderList m_reflectionRenderList; + cRenderList m_rendererList; + cRenderList m_reflectionRendererList; std::unique_ptr m_hbaoPlusPipeline; }; }; // namespace hpl diff --git a/HPL2/resource/deferred_resources.h.fsl b/HPL2/resource/deferred_resources.h.fsl index d0ff91943..35cf71708 100644 --- a/HPL2/resource/deferred_resources.h.fsl +++ b/HPL2/resource/deferred_resources.h.fsl @@ -10,7 +10,6 @@ #define BLEND_MODE_ALPHA 3 #define BLEND_MODE_PREMUL_ALPHA 4 - CBUFFER(perFrameConstants, UPDATE_FREQ_PER_FRAME, b0, binding = 0) { DATA(float4x4, invViewRotationMat, None); @@ -93,9 +92,6 @@ STRUCT(UniformObject) DATA(uint, _pad0[8], None); }; #endif - -RES(Buffer(UniformMaterial), uniformMaterialBuffer, UPDATE_FREQ_PER_FRAME, t0, binding = 1); -RES(Buffer(UniformObject), uniformObjectBuffer, UPDATE_FREQ_PER_FRAME, t1, binding = 2); RES(Tex2D(float4), diffuseMap, UPDATE_FREQ_PER_BATCH, t2, binding = 3); RES(Tex2D(float4), normalMap, UPDATE_FREQ_PER_BATCH, t3, binding = 4); @@ -112,8 +108,11 @@ RES(SamplerState, nearestSampler, UPDATE_FREQ_NONE, s2, binding = 13); RES(SamplerState, materialSampler, UPDATE_FREQ_NONE, s3, binding = 14); RES(Tex2D(float4), dissolveMap, UPDATE_FREQ_NONE, t11, binding = 15); + +RES(Buffer(UniformMaterial), uniformMaterialBuffer, UPDATE_FREQ_PER_FRAME, t0, binding = 1); +RES(Buffer(UniformObject), uniformObjectBuffer, UPDATE_FREQ_PER_FRAME, t1, binding = 2); RES(Tex2D(float4), refractionMap, UPDATE_FREQ_PER_FRAME, t12, binding = 16); -RES(Tex2D(float4), reflectionMap, UPDATE_FREQ_PER_FRAME, t13, binding = 17); +RES(Tex2D(float4), reflectionMap[4], UPDATE_FREQ_PER_FRAME, t13, binding = 17); PUSH_CONSTANT(materialRootConstant, b0) { @@ -126,10 +125,11 @@ PUSH_CONSTANT(materialRootConstant, b0) // translucency INLINE uint BlendModeTrans(uint _options) { return (_options & 0xf); } -INLINE bool UseIlluminationTrans(uint _options) { return (_options & (1 << 4)) != 0;} -INLINE bool UseReflectionTrans(uint _options) { return (_options & (1 << 5)) != 0; } -INLINE bool UseRefractionTrans(uint _options) { return (_options & (1 << 6)) != 0; } -INLINE bool UseFog(uint _options) { return (_options & (1 << 7)) != 0;} +INLINE uint ReflectionBuffer(uint _options) { return (_options >> 4) & 0x7; } +INLINE bool UseIlluminationTrans(uint _options) { return (_options & (1 << 7)) != 0;} +INLINE bool UseReflectionTrans(uint _options) { return (_options & (1 << 8)) != 0; } +INLINE bool UseRefractionTrans(uint _options) { return (_options & (1 << 9)) != 0; } +INLINE bool UseFog(uint _options) { return (_options & (1 << 10)) != 0;} INLINE float3x3 ToNormalMat(float4x4 invModel, float4x4 invView) { return transpose(mul(float3x3(invModel[0].xyz, invModel[1].xyz, invModel[2].xyz), float3x3(invView[0].xyz, invView[1].xyz, invView[2].xyz))); diff --git a/HPL2/resource/translucency_water.frag.fsl b/HPL2/resource/translucency_water.frag.fsl index df6c28f73..f6b6999f6 100644 --- a/HPL2/resource/translucency_water.frag.fsl +++ b/HPL2/resource/translucency_water.frag.fsl @@ -103,9 +103,9 @@ PsOut PS_MAIN(PsIn In) if(HasCubeMap(Get(uniformMaterialBuffer)[materialID].materialConfig)) { float3 vEnvUv = reflect(vEyeVec, vScreenNormal); vEnvUv = mul(Get(invViewRotationMat), float4(vEnvUv.x, vEnvUv.y, vEnvUv.z, 1)).xyz; - vReflectionColor = SampleTexCube(Get(cubeMap), Get(materialSampler), vEnvUv); + vReflectionColor = SampleTexCube(Get(cubeMap), Get(materialSampler), vEnvUv); } else { - vRefractionColor = SampleTex2D(Get(reflectionMap), Get(nearestSampler), vDistortedScreenPos * Get(viewTexel)); + vReflectionColor = SampleTex2D(Get(reflectionMap)[ReflectionBuffer(Get(options))], Get(nearestSampler), vDistortedScreenPos * Get(viewTexel)); } } diff --git a/HPL2/sources/graphics/RenderList.cpp b/HPL2/sources/graphics/RenderList.cpp index 88303e8ce..d984023df 100644 --- a/HPL2/sources/graphics/RenderList.cpp +++ b/HPL2/sources/graphics/RenderList.cpp @@ -160,12 +160,168 @@ namespace hpl { cRenderList::~cRenderList() { } + void cRenderList::BeginAndReset(float frameTime, cFrustum* frustum) { + m_frameTime = frameTime; + m_frustum = frustum; + + // Use resize instead of clear, because that way capacity is preserved and allocation is never + // needed unless there is a need to increase the vector size. + m_occlusionQueryObjects.resize(0); + m_transObjects.resize(0); + m_decalObjects.resize(0); + m_solidObjects.resize(0); + m_illumObjects.resize(0); + m_lights.resize(0); + m_fogAreas.resize(0); + + for (int i = 0; i < eRenderListType_LastEnum; ++i) { + m_sortedArrays[i].resize(0); + } + } + + void cRenderList::End(tRenderListCompileFlag aFlags) { + auto sortRenderType = [&](eRenderListType type) { + switch (type) { + case eRenderListType_Translucent: + m_sortedArrays[type] = m_transObjects; + break; + case eRenderListType_Decal: + m_sortedArrays[type] = m_decalObjects; + break; + case eRenderListType_Illumination: + m_sortedArrays[type] = m_illumObjects; + break; + default: + m_sortedArrays[type] = m_solidObjects; + break; + } + switch (type) { + case eRenderListType_Z: + std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Z); + break; + case eRenderListType_Diffuse: + std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Diffuse); + break; + case eRenderListType_Translucent: + std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Translucent); + break; + case eRenderListType_Decal: + std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Decal); + break; + case eRenderListType_Illumination: + std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Illumination); + break; + default: + break; + } + }; + + if (aFlags & eRenderListCompileFlag_Z) { + sortRenderType(eRenderListType_Z); + } + if (aFlags & eRenderListCompileFlag_Diffuse) { + sortRenderType(eRenderListType_Diffuse); + } + if (aFlags & eRenderListCompileFlag_Decal) { + sortRenderType(eRenderListType_Decal); + } + if (aFlags & eRenderListCompileFlag_Illumination) { + sortRenderType(eRenderListType_Illumination); + } + if(aFlags & eRenderListCompileFlag_FogArea) { + std::sort(m_fogAreas.begin(), m_fogAreas.end(), [](cFogArea* a, cFogArea* b) { + return a->GetViewSpaceZ() < b->GetViewSpaceZ(); + }); + } + if (aFlags & eRenderListCompileFlag_Translucent) { + //////////////////////////////////// + // Setup variables + cPlanef nearestSurfacePlane; + bool bHasLargeSurfacePlane = false; + float fClosestDist = 0; + iRenderable* pLargeSurfaceObject = NULL; + + //////////////////////////////////// + // Find the neareest surface plane + for (size_t i = 0; i < m_transObjects.size(); ++i) { + ///////////////////////////////// + // Check so object is of right type + iRenderable* pObject = m_transObjects[i]; + if (pObject->GetRenderType() != eRenderableType_SubMesh) { + continue; + } + + cMaterial* pMat = pObject->GetMaterial(); + if (pMat->GetLargeTransperantSurface() == false) { + continue; + } + + ///////////////////////////////// + // Check so sub mesh is one sided + cSubMeshEntity* pSubEnt = static_cast(pObject); + cSubMesh* pSubMesh = pSubEnt->GetSubMesh(); + if (pSubMesh->GetIsOneSided() == false) { + continue; + } + + cVector3f vSurfaceNormal = + cMath::Vector3Normalize(cMath::MatrixMul3x3(pSubEnt->GetWorldMatrix(), pSubMesh->GetOneSidedNormal())); + cVector3f vSurfacePos = cMath::MatrixMul(pSubEnt->GetWorldMatrix(), pSubMesh->GetOneSidedPoint()); + + ///////////////////////////////// + // Make sure it does not face away from frustum. + float fDot = cMath::Vector3Dot(vSurfacePos - m_frustum->GetOrigin(), vSurfaceNormal); + if (fDot >= 0) { + continue; + } + + ///////////////////////////////// + // Create surface normal and check if nearest. + cPlanef surfacePlane; + surfacePlane.FromNormalPoint(vSurfaceNormal, vSurfacePos); + + float fDist = cMath::PlaneToPointDist(surfacePlane, m_frustum->GetOrigin()); + if (fDist < fClosestDist || bHasLargeSurfacePlane == false) { + bHasLargeSurfacePlane = true; + fClosestDist = fDist; + nearestSurfacePlane = surfacePlane; + pLargeSurfaceObject = pObject; + } + } + + //////////////////////////////////// + // Check if objects are above or below surface plane + if (bHasLargeSurfacePlane) { + for (size_t i = 0; i < m_transObjects.size(); ++i) { + iRenderable* pObject = m_transObjects[i]; + + // If this is large plane, then set value to 0 + if (pObject == pLargeSurfaceObject) { + pObject->SetLargePlaneSurfacePlacement(0); + continue; + } + + float fDist = cMath::PlaneToPointDist(nearestSurfacePlane, pObject->GetBoundingVolume()->GetWorldCenter()); + pObject->SetLargePlaneSurfacePlacement(fDist < 0 ? -1 : 1); + } + } else { + for (size_t i = 0; i < m_transObjects.size(); ++i) { + iRenderable* pObject = m_transObjects[i]; + pObject->SetLargePlaneSurfacePlacement(0); + } + } + sortRenderType(eRenderListType_Translucent); + } + } + void cRenderList::Setup(float afFrameTime, cFrustum* apFrustum) { m_frameTime = afFrameTime; m_frustum = apFrustum; } void cRenderList::AddObject(iRenderable* apObject) { + ASSERT(m_frustum && "call begin with frustum"); + eRenderableType renderType = apObject->GetRenderType(); //////////////////////////////////////// @@ -275,13 +431,6 @@ namespace hpl { void cRenderList::Compile(tRenderListCompileFlag aFlags) { auto sortRenderType = [&](eRenderListType type) { - // constexpr std::array sortFunction = { - // { [eRenderListType_Z] = SortFunc_Z, - // [eRenderListType_Diffuse] = SortFunc_Diffuse, - // [eRenderListType_Translucent] = SortFunc_Translucent, - // [eRenderListType_Decal] = SortFunc_Decal, - // [eRenderListType_Illumination] = SortFunc_Illumination } - // }; switch (type) { case eRenderListType_Translucent: m_sortedArrays[type] = m_transObjects; diff --git a/HPL2/sources/graphics/Renderer.cpp b/HPL2/sources/graphics/Renderer.cpp index 62ec65db7..425486408 100644 --- a/HPL2/sources/graphics/Renderer.cpp +++ b/HPL2/sources/graphics/Renderer.cpp @@ -364,7 +364,7 @@ namespace hpl RenderSettingsCopy(mlNumberOfOcclusionQueries); } - iRenderer::iRenderer(const tString& asName, cGraphics* apGraphics, cResources* apResources, int alNumOfProgramComboModes) + iRenderer::iRenderer(const tString& asName, cGraphics* apGraphics, cResources* apResources) { mpGraphics = apGraphics; mpResources = apResources; diff --git a/HPL2/sources/graphics/RendererDeferred.cpp b/HPL2/sources/graphics/RendererDeferred.cpp index 1d118490f..216d2deeb 100644 --- a/HPL2/sources/graphics/RendererDeferred.cpp +++ b/HPL2/sources/graphics/RendererDeferred.cpp @@ -24,6 +24,7 @@ #include "engine/Interface.h" #include "graphics/ForgeHandles.h" #include "graphics/ImmediateDrawBatch.h" +#include "math/Frustum.h" #include "scene/ParticleEmitter.h" #include "scene/Viewport.h" #include "windowing/NativeWindow.h" @@ -79,11 +80,11 @@ #include #include +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "FixPreprocessor.h" #include +#include #include -#include "Common_3/Graphics/Interfaces/IGraphics.h" -#include "FixPreprocessor.h" namespace hpl { @@ -116,8 +117,11 @@ namespace hpl { } uint32_t resolveMaterialID(cMaterial::TextureAntistropy anisotropy, eTextureWrap wrap, eTextureFilter filter) { - const uint32_t anisotropyGroup = (static_cast(eTextureFilter_LastEnum) * static_cast(eTextureWrap_LastEnum)) * static_cast(anisotropy); - return anisotropyGroup + ((static_cast(wrap) * static_cast(eTextureFilter_LastEnum)) + static_cast(filter)); + const uint32_t anisotropyGroup = + (static_cast(eTextureFilter_LastEnum) * static_cast(eTextureWrap_LastEnum)) * + static_cast(anisotropy); + return anisotropyGroup + + ((static_cast(wrap) * static_cast(eTextureFilter_LastEnum)) + static_cast(filter)); } struct DeferredLight { @@ -135,13 +139,13 @@ namespace hpl { } }; - - static inline std::vector createFogRenderData(std::span fogAreas, cFrustum* apFrustum) { + static inline std::vector createFogRenderData( + std::span fogAreas, cFrustum* apFrustum) { std::vector fogRenderData; fogRenderData.reserve(fogAreas.size()); for (const auto& fogArea : fogAreas) { - auto& fogData = - fogRenderData.emplace_back(cRendererDeferred::FogRendererData{ fogArea, false, cVector3f(0.0f), cMatrixf(cMatrixf::Identity) }); + auto& fogData = fogRenderData.emplace_back( + cRendererDeferred::FogRendererData{ fogArea, false, cVector3f(0.0f), cMatrixf(cMatrixf::Identity) }); fogData.m_fogArea = fogArea; fogData.m_mtxInvBoxSpace = cMath::MatrixInverse(*fogArea->GetModelMatrixPtr()); fogData.m_boxSpaceFrustumOrigin = cMath::MatrixMul(fogData.m_mtxInvBoxSpace, apFrustum->GetOrigin()); @@ -169,8 +173,8 @@ namespace hpl { return fogRenderData; } - - static inline bool SetupShadowMapRendering(std::vector& shadowCasters, cWorld* world, cFrustum* frustum, iLight* light, std::span clipPlanes) { + static inline bool SetupShadowMapRendering( + std::vector& shadowCasters, cWorld* world, cFrustum* frustum, iLight* light, std::span clipPlanes) { ///////////////////////// // Get light data if (light->GetLightType() != eLightType_Spot) @@ -179,10 +183,9 @@ namespace hpl { cLightSpot* pSpotLight = static_cast(light); cFrustum* pLightFrustum = pSpotLight->GetFrustum(); - std::function walkShadowCasters; + std::function walkShadowCasters; walkShadowCasters = [&](iRenderableContainerNode* apNode, eCollision aPrevCollision) { - - /////////////////////////////////////// + /////////////////////////////////////// // Get frustum collision, if previous was inside, then this is too! eCollision frustumCollision = aPrevCollision == eCollision_Inside ? aPrevCollision : pLightFrustum->CollideNode(apNode); @@ -207,8 +210,8 @@ namespace hpl { // Iterate objects for (auto& object : apNode->GetObjects()) { // Check so visible and shadow caster - if (rendering::detail::IsObjectIsVisible(object, eRenderableFlag_ShadowCaster, clipPlanes) == false || object->GetMaterial() == NULL || - object->GetMaterial()->GetType()->IsTranslucent()) { + if (rendering::detail::IsObjectIsVisible(object, eRenderableFlag_ShadowCaster, clipPlanes) == false || + object->GetMaterial() == NULL || object->GetMaterial()->GetType()->IsTranslucent()) { continue; } @@ -227,11 +230,9 @@ namespace hpl { } }; - ///////////////////////// // If culling by occlusion, skip rest of function - if (light->GetOcclusionCullShadowCasters()) - { + if (light->GetOcclusionCullShadowCasters()) { return true; } @@ -260,56 +261,54 @@ namespace hpl { // Sort the list std::sort(shadowCasters.begin(), shadowCasters.end(), [](iRenderable* a, iRenderable* b) { - cMaterial* pMatA = a->GetMaterial(); - cMaterial* pMatB = b->GetMaterial(); + cMaterial* pMatA = a->GetMaterial(); + cMaterial* pMatB = b->GetMaterial(); - ////////////////////////// - // Alpha mode - if (pMatA->GetAlphaMode() != pMatB->GetAlphaMode()) - { - return pMatA->GetAlphaMode() < pMatB->GetAlphaMode(); - } + ////////////////////////// + // Alpha mode + if (pMatA->GetAlphaMode() != pMatB->GetAlphaMode()) { + return pMatA->GetAlphaMode() < pMatB->GetAlphaMode(); + } - ////////////////////////// - // If alpha, sort by texture (we know alpha is same for both materials, so can just test one) - if (pMatA->GetAlphaMode() == eMaterialAlphaMode_Trans) - { - if (pMatA->GetImage(eMaterialTexture_Diffuse) != pMatB->GetImage(eMaterialTexture_Diffuse)) - { - return pMatA->GetImage(eMaterialTexture_Diffuse) < pMatB->GetImage(eMaterialTexture_Diffuse); - } + ////////////////////////// + // If alpha, sort by texture (we know alpha is same for both materials, so can just test one) + if (pMatA->GetAlphaMode() == eMaterialAlphaMode_Trans) { + if (pMatA->GetImage(eMaterialTexture_Diffuse) != pMatB->GetImage(eMaterialTexture_Diffuse)) { + return pMatA->GetImage(eMaterialTexture_Diffuse) < pMatB->GetImage(eMaterialTexture_Diffuse); } + } - ////////////////////////// - // View space depth, no need to test further since Z should almost never be the same for two objects. - // View space z is really just BB dist dis squared, so use "<" - return a->GetViewSpaceZ() < b->GetViewSpaceZ(); - }); + ////////////////////////// + // View space depth, no need to test further since Z should almost never be the same for two objects. + // View space z is really just BB dist dis squared, so use "<" + return a->GetViewSpaceZ() < b->GetViewSpaceZ(); + }); return true; } - static inline cMatrixf GetLightMtx(const DeferredLight& light) { switch (light.m_light->GetLightType()) { case eLightType_Point: return cMath::MatrixScale(light.m_light->GetRadius() * kLightRadiusMul_Medium); - case eLightType_Spot: { - cLightSpot* pLightSpot = static_cast(light.m_light); + case eLightType_Spot: + { + cLightSpot* pLightSpot = static_cast(light.m_light); - float fFarHeight = pLightSpot->GetTanHalfFOV() * pLightSpot->GetRadius() * 2.0f; - // Note: Aspect might be wonky if there is no gobo. - float fFarWidth = fFarHeight * pLightSpot->GetAspect(); + float fFarHeight = pLightSpot->GetTanHalfFOV() * pLightSpot->GetRadius() * 2.0f; + // Note: Aspect might be wonky if there is no gobo. + float fFarWidth = fFarHeight * pLightSpot->GetAspect(); - return cMath::MatrixScale( - cVector3f(fFarWidth, fFarHeight, light.m_light->GetRadius())); // x and y = "far plane", z = radius - } - case eLightType_Box: { - cLightBox* pLightBox = static_cast(light.m_light); - auto mtx = cMath::MatrixScale(pLightBox->GetSize()); - mtx.SetTranslation(pLightBox->GetWorldPosition()); - return mtx; - } + return cMath::MatrixScale( + cVector3f(fFarWidth, fFarHeight, light.m_light->GetRadius())); // x and y = "far plane", z = radius + } + case eLightType_Box: + { + cLightBox* pLightBox = static_cast(light.m_light); + auto mtx = cMath::MatrixScale(pLightBox->GetSize()); + mtx.SetTranslation(pLightBox->GetWorldPosition()); + return mtx; + } default: break; } @@ -317,7 +316,6 @@ namespace hpl { return cMatrixf::Identity; } - static inline bool SortDeferredLightDefault(const DeferredLight* a, const DeferredLight* b) { iLight* pLightA = a->m_light; iLight* pLightB = b->m_light; @@ -364,11 +362,11 @@ namespace hpl { return pLightSpotA->GetSpotFalloffMap() < pLightSpotB->GetSpotFalloffMap(); } } - if(pLightA->GetLightType() == eLightType_Box) { + if (pLightA->GetLightType() == eLightType_Box) { cLightBox* pBoxLightA = static_cast(pLightA); cLightBox* pBoxLightB = static_cast(pLightB); - if(pBoxLightA->GetBoxLightPrio() != pBoxLightB->GetBoxLightPrio()) { - return pBoxLightA->GetBoxLightPrio() < pBoxLightB->GetBoxLightPrio(); + if (pBoxLightA->GetBoxLightPrio() != pBoxLightB->GetBoxLightPrio()) { + return pBoxLightA->GetBoxLightPrio() < pBoxLightB->GetBoxLightPrio(); } } @@ -377,7 +375,8 @@ namespace hpl { return pLightA < pLightB; } - static inline float GetFogAreaVisibilityForObject(const cRendererDeferred::FogRendererData& fogData, cFrustum& frustum, iRenderable* apObject) { + static inline float GetFogAreaVisibilityForObject( + const cRendererDeferred::FogRendererData& fogData, cFrustum& frustum, iRenderable* apObject) { cFogArea* pFogArea = fogData.m_fogArea; cVector3f vObjectPos = apObject->GetBoundingVolume()->GetWorldCenter(); @@ -522,12 +521,10 @@ namespace hpl { } } // namespace detail - enum eDefferredProgramMode { eDefferredProgramMode_Lights, eDefferredProgramMode_Misc, eDefferredProgramMode_LastEnum }; cRendererDeferred::cRendererDeferred(cGraphics* apGraphics, cResources* apResources) - : iRenderer("Deferred", apGraphics, apResources, eDefferredProgramMode_LastEnum) { - + : iRenderer("Deferred", apGraphics, apResources) { m_hbaoPlusPipeline = std::make_unique(); //////////////////////////////////// // Set up render specific things @@ -539,11 +536,9 @@ namespace hpl { m_shadowDistanceLow = 20; m_shadowDistanceNone = 40; - UVector3 shadowSizes[] = { UVector3( 128, 128, 1), - UVector3( 256, 256, 1), - UVector3( 256, 256, 1), - UVector3( 512, 512, 1), - UVector3( 1024, 1024, 1) }; + UVector3 shadowSizes[] = { + UVector3(128, 128, 1), UVector3(256, 256, 1), UVector3(256, 256, 1), UVector3(512, 512, 1), UVector3(1024, 1024, 1) + }; int startSize = 2; if (mShadowMapResolution == eShadowMapResolution_Medium) { startSize = 1; @@ -556,41 +551,41 @@ namespace hpl { m_occlusionUniformBuffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; - desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; - desc.mDesc.mFirstElement = 0; - desc.mDesc.mElementCount = MaxOcclusionDescSize; - desc.mDesc.mStructStride = sizeof(mat4); - desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = MaxOcclusionDescSize; + desc.mDesc.mStructStride = sizeof(mat4); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; }); m_materialSet.m_materialUniformBuffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; - desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; - desc.mDesc.mFirstElement = 0; - desc.mDesc.mElementCount = cMaterial::MaxMaterialID; - desc.mDesc.mStructStride = sizeof(cMaterial::MaterialType::MaterialData); - desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = cMaterial::MaxMaterialID; + desc.mDesc.mStructStride = sizeof(cMaterial::MaterialType::MaterialData); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; }); - for(auto& buffer: m_objectUniformBuffer) { + for (auto& buffer : m_objectUniformBuffer) { buffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; - desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; - desc.mDesc.mFirstElement = 0; - desc.mDesc.mElementCount = MaxObjectUniforms; - desc.mDesc.mStructStride = sizeof(cRendererDeferred::UniformObject); - desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = MaxObjectUniforms; + desc.mDesc.mStructStride = sizeof(cRendererDeferred::UniformObject); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; @@ -663,8 +658,8 @@ namespace hpl { BufferLoadDesc desc = {}; desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_UNIFORM_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - desc.mDesc.mElementCount = 1; - desc.mDesc.mStructStride = sizeof(cRendererDeferred::UniformPerFrameData); + desc.mDesc.mElementCount = 1; + desc.mDesc.mStructStride = sizeof(cRendererDeferred::UniformPerFrameData); desc.mDesc.mSize = sizeof(cRendererDeferred::UniformPerFrameData); desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; desc.pData = nullptr; @@ -700,7 +695,6 @@ namespace hpl { loadDesc.mStages[0].pFileName = "generate_hi_z.comp"; addShader(forgeRenderer->Rend(), &loadDesc, shader); return true; - }); m_shaderTestOcclusion.Load(forgeRenderer->Rend(), [&](Shader** shader) { @@ -708,7 +702,7 @@ namespace hpl { loadDesc.mStages[0].pFileName = "test_AABB_hi_z.comp"; addShader(forgeRenderer->Rend(), &loadDesc, shader); return true; - }); + }); m_copyDepthShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { ShaderLoadDesc loadDesc = {}; @@ -755,7 +749,7 @@ namespace hpl { addResource(&desc, nullptr); return true; }); - m_rootSignatureHIZOcclusion.Load(forgeRenderer->Rend(), [&](RootSignature ** sig) { + m_rootSignatureHIZOcclusion.Load(forgeRenderer->Rend(), [&](RootSignature** sig) { std::array shaders = { m_ShaderHIZGenerate.m_handle, m_shaderTestOcclusion.m_handle }; RootSignatureDesc rootSignatureDesc = {}; const char* pStaticSamplers[] = { "depthSampler" }; @@ -788,7 +782,6 @@ namespace hpl { return true; }); - m_descriptorCopyDepth.Load(forgeRenderer->Rend(), [&](DescriptorSet** handle) { DescriptorSetDesc setDesc = { m_rootSignatureCopyDepth.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1 }; addDescriptorSet(forgeRenderer->Rend(), &setDesc, handle); @@ -804,7 +797,7 @@ namespace hpl { return true; }); - m_pipelineAABBOcclusionTest.Load(forgeRenderer->Rend(),[&](Pipeline** handle) { + m_pipelineAABBOcclusionTest.Load(forgeRenderer->Rend(), [&](Pipeline** handle) { PipelineDesc pipelineDesc = {}; pipelineDesc.mType = PIPELINE_TYPE_COMPUTE; ComputePipelineDesc& computePipelineDesc = pipelineDesc.mComputeDesc; @@ -880,11 +873,8 @@ namespace hpl { return true; }); - m_descriptorOcclusionConstSet.Load(forgeRenderer->Rend(), [&](DescriptorSet** handle) { - DescriptorSetDesc setDesc = { m_rootSignatureOcclusuion.m_handle, - DESCRIPTOR_UPDATE_FREQ_NONE, - 1 }; + DescriptorSetDesc setDesc = { m_rootSignatureOcclusuion.m_handle, DESCRIPTOR_UPDATE_FREQ_NONE, 1 }; addDescriptorSet(forgeRenderer->Rend(), &setDesc, handle); return true; }); @@ -897,10 +887,10 @@ namespace hpl { { VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 1; - vertexLayout.mBindings[0].mStride = sizeof(float3); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 1; + vertexLayout.mBindings[0].mStride = sizeof(float3); +#endif vertexLayout.mAttribCount = 1; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -941,7 +931,7 @@ namespace hpl { return true; }); } - m_occlusionQuery.Load(forgeRenderer->Rend(), [&](QueryPool ** pool) { + m_occlusionQuery.Load(forgeRenderer->Rend(), [&](QueryPool** pool) { QueryPoolDesc queryPoolDesc = {}; queryPoolDesc.mType = QUERY_TYPE_OCCLUSION; queryPoolDesc.mQueryCount = MaxQueryPoolSize; @@ -990,12 +980,11 @@ namespace hpl { return true; }); - VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 1; - vertexLayout.mBindings[0].mStride = sizeof(float3); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 1; + vertexLayout.mBindings[0].mStride = sizeof(float3); +#endif vertexLayout.mAttribCount = 1; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; @@ -1018,11 +1007,11 @@ namespace hpl { blendStateDesc.mSrcAlphaFactors[0] = BC_SRC_ALPHA; blendStateDesc.mDstAlphaFactors[0] = BC_ONE_MINUS_SRC_ALPHA; blendStateDesc.mBlendAlphaModes[0] = BM_ADD; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = RED | GREEN | BLUE; - #else - blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; - #endif +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = RED | GREEN | BLUE; +#else + blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1045,18 +1034,17 @@ namespace hpl { pipelineSettings.pShaderProgram = m_fogPass.m_shader.m_handle; pipelineSettings.pRasterizerState = &rasterizerStateDesc; pipelineSettings.pVertexLayout = &vertexLayout; - m_fogPass.m_pipeline.Load(forgeRenderer->Rend(), [&](Pipeline ** pipline) { + m_fogPass.m_pipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); return true; }); rasterizerStateDesc.mFrontFace = FrontFace::FRONT_FACE_CW; depthStateDesc.mDepthFunc = CMP_ALWAYS; - m_fogPass.m_pipelineInsideNearFrustum.Load(forgeRenderer->Rend(), [&](Pipeline ** pipline) { + m_fogPass.m_pipelineInsideNearFrustum.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); return true; }); - } m_fogPass.m_fullScreenPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { DepthStateDesc depthStateDisabledDesc = {}; @@ -1070,11 +1058,11 @@ namespace hpl { blendStateDesc.mSrcAlphaFactors[0] = BC_SRC_ALPHA; blendStateDesc.mDstAlphaFactors[0] = BC_ONE_MINUS_SRC_ALPHA; blendStateDesc.mBlendAlphaModes[0] = BM_ADD; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = RED | GREEN | BLUE; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = RED | GREEN | BLUE; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; - #endif +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1101,37 +1089,37 @@ namespace hpl { return true; }); - for(auto& buffer: m_fogPass.m_fogUniformBuffer) { - buffer.Load([&](Buffer** buffer){ + for (auto& buffer : m_fogPass.m_fogUniformBuffer) { + buffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; - desc.mDesc.mFirstElement = 0; - desc.mDesc.mElementCount = Fog::MaxFogCount; - desc.mDesc.mStructStride = sizeof(UniformFogData); - desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = Fog::MaxFogCount; + desc.mDesc.mStructStride = sizeof(UniformFogData); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; }); } - for(auto& buffer: m_fogPass.m_fogFullscreenUniformBuffer) { - buffer.Load([&](Buffer** buffer){ + for (auto& buffer : m_fogPass.m_fogFullscreenUniformBuffer) { + buffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_UNIFORM_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; desc.mDesc.mElementCount = 1; desc.mDesc.mStructStride = sizeof(UniformFullscreenFogData); - desc.mDesc.mSize = sizeof(UniformFullscreenFogData); + desc.mDesc.mSize = sizeof(UniformFullscreenFogData); desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; }); } DescriptorSetDesc perFrameDescSet{ m_fogPass.m_fogRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1 }; - for(size_t setIndex = 0; setIndex < m_fogPass.m_perFrameSet.size(); setIndex++ ) { + for (size_t setIndex = 0; setIndex < m_fogPass.m_perFrameSet.size(); setIndex++) { addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, &m_fogPass.m_perFrameSet[setIndex]); std::array params = {}; @@ -1142,18 +1130,18 @@ namespace hpl { updateDescriptorSet(forgeRenderer->Rend(), 0, m_fogPass.m_perFrameSet[setIndex], params.size(), params.data()); } - // DescriptorSetDesc perObjectSet{ m_fogPass.m_fogRootSignature, DESCRIPTOR_UPDATE_FREQ_PER_DRAW, Fog::MaxFogCount }; - // for (auto& objectSet : m_fogPass.m_perObjectSet) { - // addDescriptorSet(forgeRenderer->Rend(), &perObjectSet, &objectSet); - // } + // DescriptorSetDesc perObjectSet{ m_fogPass.m_fogRootSignature, DESCRIPTOR_UPDATE_FREQ_PER_DRAW, Fog::MaxFogCount }; + // for (auto& objectSet : m_fogPass.m_perObjectSet) { + // addDescriptorSet(forgeRenderer->Rend(), &perObjectSet, &objectSet); + // } - // addUniformGPURingBuffer( - // forgeRenderer->Rend(), sizeof(Fog::UniformFogData) * Fog::MaxFogCount, &m_fogPass.m_fogUniformBuffer, true); + // addUniformGPURingBuffer( + // forgeRenderer->Rend(), sizeof(Fog::UniformFogData) * Fog::MaxFogCount, &m_fogPass.m_fogUniformBuffer, true); } //---------------- Diffuse Pipeline ------------------------ { // z pass - m_zPassShader.Load(forgeRenderer->Rend(), [&](Shader** shader){ + m_zPassShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { ShaderLoadDesc loadDesc = {}; loadDesc.mStages[0].pFileName = "solid_z.vert"; loadDesc.mStages[1].pFileName = "solid_z.frag"; @@ -1177,7 +1165,7 @@ namespace hpl { return true; }); - m_solidIlluminationShader.Load(forgeRenderer->Rend(),[&](Shader** shader){ + m_solidIlluminationShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { ShaderLoadDesc loadDesc = {}; loadDesc.mStages[0].pFileName = "solid_illumination.vert"; loadDesc.mStages[1].pFileName = "solid_illumination.frag"; @@ -1186,7 +1174,7 @@ namespace hpl { }); // decal pass - m_decalShader.Load(forgeRenderer->Rend(), [&](Shader** shader){ + m_decalShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { ShaderLoadDesc loadDesc = {}; loadDesc.mStages[0].pFileName = "decal.vert"; loadDesc.mStages[1].pFileName = "decal.frag"; @@ -1228,7 +1216,6 @@ namespace hpl { return true; }); - m_materialTranslucencyPass.m_refractionCopyRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** signature) { RootSignatureDesc refractionCopyRootDesc = {}; refractionCopyRootDesc.mShaderCount = 1; @@ -1237,7 +1224,6 @@ namespace hpl { return true; }); - DescriptorSetDesc setDesc = { m_materialTranslucencyPass.m_refractionCopyRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, 1 }; @@ -1246,7 +1232,6 @@ namespace hpl { addDescriptorSet(forgeRenderer->Rend(), &setDesc, descriptor); return true; }); - } m_materialTranslucencyPass.m_refractionCopyPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { PipelineDesc desc = {}; @@ -1257,7 +1242,6 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &desc, pipeline); return true; }); - } folly::small_vector shaders{ m_materialSolidPass.m_solidDiffuseShader.m_handle, @@ -1272,7 +1256,7 @@ namespace hpl { m_materialRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** signature) { RootSignatureDesc rootSignatureDesc = {}; const char* pStaticSamplersNames[] = { "nearestSampler", "refractionSampler" }; - Sampler* pStaticSampler[] = {m_samplerPointClampToBorder.m_handle, m_samplerPointClampToEdge.m_handle}; + Sampler* pStaticSampler[] = { m_samplerPointClampToBorder.m_handle, m_samplerPointClampToEdge.m_handle }; rootSignatureDesc.mStaticSamplerCount = std::size(pStaticSamplersNames); rootSignatureDesc.ppStaticSamplerNames = pStaticSamplersNames; rootSignatureDesc.ppStaticSamplers = pStaticSampler; @@ -1282,17 +1266,16 @@ namespace hpl { return true; }); - // diffuse material pass { VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 4; - vertexLayout.mBindings[0].mStride = sizeof(float3); - vertexLayout.mBindings[1].mStride = sizeof(float2); - vertexLayout.mBindings[2].mStride = sizeof(float3); - vertexLayout.mBindings[3].mStride = sizeof(float3); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 4; + vertexLayout.mBindings[0].mStride = sizeof(float3); + vertexLayout.mBindings[1].mStride = sizeof(float2); + vertexLayout.mBindings[2].mStride = sizeof(float3); + vertexLayout.mBindings[3].mStride = sizeof(float3); +#endif vertexLayout.mAttribCount = 4; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -1320,6 +1303,7 @@ namespace hpl { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + rasterizerStateDesc.mFrontFace = FRONT_FACE_CCW; DepthStateDesc depthStateDesc = {}; depthStateDesc.mDepthTest = true; @@ -1353,16 +1337,27 @@ namespace hpl { return true; }); + rasterizerStateDesc.mFrontFace = FRONT_FACE_CW; + m_materialSolidPass.m_solidDiffusePipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); + + pipelineSettings.pShaderProgram = m_materialSolidPass.m_solidDiffuseParallaxShader.m_handle; + m_materialSolidPass.m_solidDiffuseParallaxPipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); } // decal material pass { VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 3; - vertexLayout.mBindings[0].mStride = sizeof(float3); - vertexLayout.mBindings[1].mStride = sizeof(float2); - vertexLayout.mBindings[2].mStride = sizeof(float4); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 3; + vertexLayout.mBindings[0].mStride = sizeof(float3); + vertexLayout.mBindings[1].mStride = sizeof(float2); + vertexLayout.mBindings[2].mStride = sizeof(float4); +#endif vertexLayout.mAttribCount = 3; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -1385,6 +1380,7 @@ namespace hpl { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + DepthStateDesc depthStateDesc = {}; depthStateDesc.mDepthTest = true; depthStateDesc.mDepthWrite = false; @@ -1416,18 +1412,24 @@ namespace hpl { blendStateDesc.mSrcAlphaFactors[0] = hpl::HPL2BlendTable[blendMode].srcAlpha; blendStateDesc.mDstAlphaFactors[0] = hpl::HPL2BlendTable[blendMode].dstAlpha; blendStateDesc.mBlendAlphaModes[0] = hpl::HPL2BlendTable[blendMode].alphaMode; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = RED | GREEN | BLUE; - #else - blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; - #endif +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = RED | GREEN | BLUE; +#else + blendStateDesc.mColorWriteMasks[0] = + ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; pipelineSettings.pBlendState = &blendStateDesc; + rasterizerStateDesc.mFrontFace = FRONT_FACE_CCW; m_decalPipeline[blendMode].Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { - addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); - return true; + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); + return true; + }); + rasterizerStateDesc.mFrontFace = FRONT_FACE_CW; + m_decalPipelineCW[blendMode].Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); + return true; }); - } } // z pass material @@ -1436,13 +1438,13 @@ namespace hpl { VertexLayout vertexLayout = {}; vertexLayout.mAttribCount = 4; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 4; - vertexLayout.mBindings[0].mStride = sizeof(float3); - vertexLayout.mBindings[1].mStride = sizeof(float2); - vertexLayout.mBindings[2].mStride = sizeof(float3); - vertexLayout.mBindings[3].mStride = sizeof(float3); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 4; + vertexLayout.mBindings[0].mStride = sizeof(float3); + vertexLayout.mBindings[1].mStride = sizeof(float2); + vertexLayout.mBindings[2].mStride = sizeof(float3); + vertexLayout.mBindings[3].mStride = sizeof(float3); +#endif vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; vertexLayout.mAttribs[0].mBinding = 0; @@ -1467,9 +1469,37 @@ namespace hpl { vertexLayout.mAttribs[3].mLocation = 3; vertexLayout.mAttribs[3].mOffset = 0; - m_zPassPipeline.Load(forgeRenderer->Rend(),[&](Pipeline** pipeline) { + m_zPassPipelineCCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + RasterizerStateDesc rasterizerStateDesc = {}; + rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + rasterizerStateDesc.mFrontFace = FrontFace::FRONT_FACE_CCW; + + DepthStateDesc depthStateDesc = {}; + depthStateDesc.mDepthTest = true; + depthStateDesc.mDepthWrite = true; + depthStateDesc.mDepthFunc = CMP_LEQUAL; + + PipelineDesc pipelineDesc = {}; + pipelineDesc.mType = PIPELINE_TYPE_GRAPHICS; + auto& pipelineSettings = pipelineDesc.mGraphicsDesc; + pipelineSettings.mPrimitiveTopo = PRIMITIVE_TOPO_TRI_LIST; + pipelineSettings.mRenderTargetCount = 0; + pipelineSettings.pDepthState = &depthStateDesc; + pipelineSettings.pColorFormats = NULL; + pipelineSettings.mSampleCount = SAMPLE_COUNT_1; + pipelineSettings.mSampleQuality = 0; + pipelineSettings.mDepthStencilFormat = DepthBufferFormat; + pipelineSettings.pRootSignature = m_materialRootSignature.m_handle; + pipelineSettings.pShaderProgram = m_zPassShader.m_handle; + pipelineSettings.pRasterizerState = &rasterizerStateDesc; + pipelineSettings.pVertexLayout = &vertexLayout; + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); + m_zPassPipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + rasterizerStateDesc.mFrontFace = FrontFace::FRONT_FACE_CW; DepthStateDesc depthStateDesc = {}; depthStateDesc.mDepthTest = true; @@ -1493,7 +1523,7 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); return true; }); - m_zPassShadowPipelineCW.Load(forgeRenderer->Rend(),[&](Pipeline** pipeline) { + m_zPassShadowPipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mFrontFace = FRONT_FACE_CW; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; @@ -1520,7 +1550,7 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); return true; }); - m_zPassShadowPipelineCCW.Load(forgeRenderer->Rend(),[&](Pipeline** pipeline) { + m_zPassShadowPipelineCCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mFrontFace = FRONT_FACE_CW; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; @@ -1549,65 +1579,68 @@ namespace hpl { }); m_materialSet.m_materialConstSet.Load(forgeRenderer->Rend(), [&](DescriptorSet** handle) { - DescriptorSetDesc setDesc{ m_materialRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_NONE, MaxMaterialSamplers}; + DescriptorSetDesc setDesc{ m_materialRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_NONE, MaxMaterialSamplers }; addDescriptorSet(forgeRenderer->Rend(), &setDesc, handle); return true; }); - for(size_t antistropy = 0; antistropy < cMaterial::Antistropy_Count; antistropy++) { - for(size_t textureWrap = 0; textureWrap < eTextureWrap_LastEnum; textureWrap++) { - for(size_t textureFilter = 0; textureFilter < eTextureFilter_LastEnum; textureFilter++) { - uint32_t materialID = detail::resolveMaterialID(static_cast(antistropy), static_cast(textureWrap), static_cast(textureFilter)); - m_materialSet.m_samplers[materialID].Load(forgeRenderer->Rend(), [&](Sampler** sampler){ + for (size_t antistropy = 0; antistropy < cMaterial::Antistropy_Count; antistropy++) { + for (size_t textureWrap = 0; textureWrap < eTextureWrap_LastEnum; textureWrap++) { + for (size_t textureFilter = 0; textureFilter < eTextureFilter_LastEnum; textureFilter++) { + uint32_t materialID = detail::resolveMaterialID( + static_cast(antistropy), + static_cast(textureWrap), + static_cast(textureFilter)); + m_materialSet.m_samplers[materialID].Load(forgeRenderer->Rend(), [&](Sampler** sampler) { SamplerDesc samplerDesc = {}; - switch(textureWrap) { - case eTextureWrap_Repeat: - samplerDesc.mAddressU = ADDRESS_MODE_REPEAT; - samplerDesc.mAddressV = ADDRESS_MODE_REPEAT; - samplerDesc.mAddressW = ADDRESS_MODE_REPEAT; - break; - case eTextureWrap_Clamp: - samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_EDGE; - samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_EDGE; - samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_EDGE; - break; - case eTextureWrap_ClampToBorder: - samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_BORDER; - samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_BORDER; - samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_BORDER; - break; - default: - ASSERT(false && "Invalid wrap mode"); - break; + switch (textureWrap) { + case eTextureWrap_Repeat: + samplerDesc.mAddressU = ADDRESS_MODE_REPEAT; + samplerDesc.mAddressV = ADDRESS_MODE_REPEAT; + samplerDesc.mAddressW = ADDRESS_MODE_REPEAT; + break; + case eTextureWrap_Clamp: + samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_EDGE; + samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_EDGE; + samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_EDGE; + break; + case eTextureWrap_ClampToBorder: + samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_BORDER; + break; + default: + ASSERT(false && "Invalid wrap mode"); + break; } - switch(textureFilter) { - case eTextureFilter_Nearest: - samplerDesc.mMinFilter = FilterType::FILTER_NEAREST; - samplerDesc.mMagFilter = FilterType::FILTER_NEAREST; - samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; - break; - case eTextureFilter_Bilinear: - samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; - samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; - samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; - break; - case eTextureFilter_Trilinear: - samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; - samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; - samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_LINEAR; - break; - default: - ASSERT(false && "Invalid filter"); - break; + switch (textureFilter) { + case eTextureFilter_Nearest: + samplerDesc.mMinFilter = FilterType::FILTER_NEAREST; + samplerDesc.mMagFilter = FilterType::FILTER_NEAREST; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; + break; + case eTextureFilter_Bilinear: + samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; + break; + case eTextureFilter_Trilinear: + samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_LINEAR; + break; + default: + ASSERT(false && "Invalid filter"); + break; } - switch(antistropy) { - case cMaterial::Antistropy_8: - samplerDesc.mMaxAnisotropy = 8.0f; - break; - case cMaterial::Antistropy_16: - samplerDesc.mMaxAnisotropy = 16.0f; - break; - default: - break; + switch (antistropy) { + case cMaterial::Antistropy_8: + samplerDesc.mMaxAnisotropy = 8.0f; + break; + case cMaterial::Antistropy_16: + samplerDesc.mMaxAnisotropy = 16.0f; + break; + default: + break; } addSampler(forgeRenderer->Rend(), &samplerDesc, sampler); return true; @@ -1617,22 +1650,20 @@ namespace hpl { params[0].pName = "dissolveMap"; params[1].ppSamplers = &m_materialSet.m_samplers[materialID].m_handle; params[1].pName = "materialSampler"; - updateDescriptorSet(forgeRenderer->Rend(), materialID, m_materialSet.m_materialConstSet.m_handle, params.size(), params.data()); - + updateDescriptorSet( + forgeRenderer->Rend(), materialID, m_materialSet.m_materialConstSet.m_handle, params.size(), params.data()); } } } } - - // illumination pass - m_solidIlluminationPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { + { // layout and pipeline for sphere draw VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY +#ifndef USE_THE_FORGE_LEGACY vertexLayout.mBindingCount = 2; vertexLayout.mBindings[0].mStride = sizeof(float3); vertexLayout.mBindings[1].mStride = sizeof(float2); - #endif +#endif vertexLayout.mAttribCount = 2; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -1648,13 +1679,14 @@ namespace hpl { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + rasterizerStateDesc.mFrontFace = FRONT_FACE_CCW; BlendStateDesc blendStateDesc{}; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = ALL; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = ALL; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; - #endif +#endif blendStateDesc.mSrcFactors[0] = BC_ONE; blendStateDesc.mDstFactors[0] = BC_ONE; blendStateDesc.mBlendModes[0] = BM_ADD; @@ -1685,19 +1717,29 @@ namespace hpl { pipelineSettings.pShaderProgram = m_solidIlluminationShader.m_handle; pipelineSettings.pRasterizerState = &rasterizerStateDesc; pipelineSettings.pVertexLayout = &vertexLayout; - addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); - return true; - }); + // illumination pass + m_solidIlluminationPipelineCCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); + return true; + }); + + rasterizerStateDesc.mFrontFace = FRONT_FACE_CW; + m_solidIlluminationPipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** pipline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); + return true; + }); + + } // translucency pass { VertexLayout particleVertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - particleVertexLayout.mBindingCount = 3; - particleVertexLayout.mBindings[0].mStride = sizeof(float3); - particleVertexLayout.mBindings[1].mStride = sizeof(float2); - particleVertexLayout.mBindings[2].mStride = sizeof(float4); - #endif +#ifndef USE_THE_FORGE_LEGACY + particleVertexLayout.mBindingCount = 3; + particleVertexLayout.mBindings[0].mStride = sizeof(float3); + particleVertexLayout.mBindings[1].mStride = sizeof(float2); + particleVertexLayout.mBindings[2].mStride = sizeof(float4); +#endif particleVertexLayout.mAttribCount = 3; particleVertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; @@ -1720,14 +1762,14 @@ namespace hpl { VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY - vertexLayout.mBindingCount = 5; - vertexLayout.mBindings[0].mStride = sizeof(float3); - vertexLayout.mBindings[1].mStride = sizeof(float2); - vertexLayout.mBindings[2].mStride = sizeof(float3); - vertexLayout.mBindings[3].mStride = sizeof(float3); - vertexLayout.mBindings[4].mStride = sizeof(float3); - #endif +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 5; + vertexLayout.mBindings[0].mStride = sizeof(float3); + vertexLayout.mBindings[1].mStride = sizeof(float2); + vertexLayout.mBindings[2].mStride = sizeof(float3); + vertexLayout.mBindings[3].mStride = sizeof(float3); + vertexLayout.mBindings[4].mStride = sizeof(float3); +#endif vertexLayout.mAttribCount = 5; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -1776,11 +1818,11 @@ namespace hpl { pipelineBlendGroup[key.m_id].Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { BlendStateDesc blendStateDesc{}; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = ALL; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = ALL; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; - #endif +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1832,11 +1874,11 @@ namespace hpl { pipelineBlendGroup[key.m_id].Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { BlendStateDesc blendStateDesc{}; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = RED | GREEN | BLUE; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = RED | GREEN | BLUE; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; - #endif +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1884,11 +1926,11 @@ namespace hpl { key.m_id = pipelineKey; pipelineBlendGroup[key.m_id].Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { BlendStateDesc blendStateDesc{}; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = ALL; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = ALL; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; - #endif +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1939,11 +1981,11 @@ namespace hpl { key.m_id = pipelineKey; m_materialTranslucencyPass.m_refractionPipeline[key.m_id].Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { BlendStateDesc blendStateDesc{}; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = ALL; - #else +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = ALL; +#else blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; - #endif +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -1985,19 +2027,20 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); return true; }); - } } } - DescriptorSetDesc perFrameDescSet{ m_materialRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, MaxMaterialFrameDescriptors }; + DescriptorSetDesc perFrameDescSet{ m_materialRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_FRAME, + MaxViewportFrameDescriptors }; for (size_t setIndex = 0; setIndex < m_materialSet.m_frameSet.size(); setIndex++) { m_materialSet.m_frameSet[setIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, descSet); return true; }); - for(size_t i = 0; i < MaxMaterialFrameDescriptors; i++) { + for (size_t i = 0; i < MaxViewportFrameDescriptors; i++) { std::array params = {}; params[0].pName = "perFrameConstants"; params[0].ppBuffers = &m_perFrameBuffer[i].m_handle; @@ -2005,34 +2048,34 @@ namespace hpl { params[1].ppBuffers = &m_objectUniformBuffer[setIndex].m_handle; params[2].pName = "uniformMaterialBuffer"; params[2].ppBuffers = &m_materialSet.m_materialUniformBuffer.m_handle; - updateDescriptorSet(forgeRenderer->Rend(), i, m_materialSet.m_frameSet[setIndex].m_handle, params.size(), params.data()); + updateDescriptorSet( + forgeRenderer->Rend(), i, m_materialSet.m_frameSet[setIndex].m_handle, params.size(), params.data()); } } - - for(size_t setIndex = 0; setIndex < m_materialSet.m_perBatchSet.size(); setIndex++ ) { + for (size_t setIndex = 0; setIndex < m_materialSet.m_perBatchSet.size(); setIndex++) { m_materialSet.m_perBatchSet[setIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { - DescriptorSetDesc batchDescriptorSet{ m_materialRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_BATCH, cMaterial::MaxMaterialID }; + DescriptorSetDesc batchDescriptorSet{ m_materialRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_BATCH, + cMaterial::MaxMaterialID }; addDescriptorSet(forgeRenderer->Rend(), &batchDescriptorSet, descSet); return true; }); - } } // ------------------------ Light Pass ----------------------------------------------------------------- { - - for(auto& buffer: m_lightPassBuffer) { + for (auto& buffer : m_lightPassBuffer) { buffer.Load([&](Buffer** buffer) { BufferLoadDesc desc = {}; - desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; - desc.mDesc.mFirstElement = 0; - desc.mDesc.mElementCount = MaxLightUniforms; - desc.mDesc.mStructStride = sizeof(UniformLightData); - desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = MaxLightUniforms; + desc.mDesc.mStructStride = sizeof(UniformLightData); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); return true; @@ -2110,14 +2153,15 @@ namespace hpl { addShader(forgeRenderer->Rend(), &loadDesc, handle); return true; }); - Sampler* vbShadeSceneSamplers[] = { - m_shadowCmpSampler.m_handle, m_samplerPointClampToBorder.m_handle, m_goboSampler.m_handle, m_samplerPointClampToBorder.m_handle - }; - const char* vbShadeSceneSamplersNames[] = { "shadowCmpSampler", "pointSampler", "goboSampler", "nearestSampler"}; + Sampler* vbShadeSceneSamplers[] = { m_shadowCmpSampler.m_handle, + m_samplerPointClampToBorder.m_handle, + m_goboSampler.m_handle, + m_samplerPointClampToBorder.m_handle }; + const char* vbShadeSceneSamplersNames[] = { "shadowCmpSampler", "pointSampler", "goboSampler", "nearestSampler" }; Shader* shaders[] = { m_pointLightShader.m_handle, m_stencilLightShader.m_handle, m_boxLightShader.m_handle, m_spotLightShader.m_handle }; - m_lightPassRootSignature.Load(forgeRenderer->Rend(),[&](RootSignature** signature) { + m_lightPassRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** signature) { RootSignatureDesc rootSignatureDesc = {}; rootSignatureDesc.ppShaders = shaders; rootSignatureDesc.mShaderCount = std::size(shaders); @@ -2129,10 +2173,10 @@ namespace hpl { }); VertexLayout vertexLayout = {}; - #ifndef USE_THE_FORGE_LEGACY +#ifndef USE_THE_FORGE_LEGACY vertexLayout.mBindingCount = 1; vertexLayout.mBindings[0].mStride = sizeof(float3); - #endif +#endif vertexLayout.mAttribCount = 1; vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; @@ -2140,7 +2184,8 @@ namespace hpl { vertexLayout.mAttribs[0].mLocation = 0; vertexLayout.mAttribs[0].mOffset = 0; - auto createPipelineVariants = [&](PipelineDesc& pipelineDesc, std::array& pipelines) { + auto createPipelineVariants = [&](PipelineDesc& pipelineDesc, + std::array& pipelines) { for (uint32_t i = 0; i < LightPipelineVariants::LightPipelineVariant_Size; ++i) { DepthStateDesc depthStateDec = {}; depthStateDec.mDepthTest = true; @@ -2175,7 +2220,6 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); return true; }); - } }; @@ -2186,11 +2230,11 @@ namespace hpl { blendStateDesc.mSrcAlphaFactors[0] = BC_ONE; blendStateDesc.mDstAlphaFactors[0] = BC_ONE; blendStateDesc.mBlendAlphaModes[0] = BM_ADD; - #ifdef USE_THE_FORGE_LEGACY - blendStateDesc.mMasks[0] = RED | GREEN | BLUE; - #else - blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; - #endif +#ifdef USE_THE_FORGE_LEGACY + blendStateDesc.mMasks[0] = RED | GREEN | BLUE; +#else + blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_RED | ColorMask::COLOR_MASK_GREEN | ColorMask::COLOR_MASK_BLUE; +#endif blendStateDesc.mRenderTargetMask = BLEND_STATE_TARGET_0; blendStateDesc.mIndependentBlend = false; @@ -2246,8 +2290,7 @@ namespace hpl { createPipelineVariants(pipelineDesc, m_spotLightPipeline); } - - m_lightStencilPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** handle){ + { DepthStateDesc stencilDepthTest = {}; stencilDepthTest.mDepthTest = true; stencilDepthTest.mDepthWrite = false; @@ -2285,32 +2328,41 @@ namespace hpl { pipelineSettings.pDepthState = &stencilDepthTest; pipelineSettings.pRasterizerState = &rasterizerStateDesc; pipelineSettings.pShaderProgram = m_stencilLightShader.m_handle; - addPipeline(forgeRenderer->Rend(), &pipelineDesc, handle); - return true; - }); + m_lightStencilPipelineCCW.Load(forgeRenderer->Rend(), [&](Pipeline** handle) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, handle); + return true; + }); + rasterizerStateDesc.mFrontFace = FrontFace::FRONT_FACE_CW; + m_lightStencilPipelineCW.Load(forgeRenderer->Rend(), [&](Pipeline** handle) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, handle); + return true; + }); + } for (auto& lightSet : m_lightPerLightSet) { lightSet.Load(forgeRenderer->Rend(), [&](DescriptorSet** set) { DescriptorSetDesc batchDescriptorSet{ m_lightPassRootSignature.m_handle, - DESCRIPTOR_UPDATE_FREQ_PER_BATCH, - cRendererDeferred::MaxLightUniforms }; + DESCRIPTOR_UPDATE_FREQ_PER_BATCH, + cRendererDeferred::MaxLightUniforms }; addDescriptorSet(forgeRenderer->Rend(), &batchDescriptorSet, set); return true; }); - } - for(size_t setIndex = 0; setIndex < m_lightPerFrameSet.size(); setIndex++) { + for (size_t setIndex = 0; setIndex < m_lightPerFrameSet.size(); setIndex++) { m_lightPerFrameSet[setIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** set) { - DescriptorSetDesc perFrameDescSet{ m_lightPassRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, ForgeRenderer::SwapChainLength }; + DescriptorSetDesc perFrameDescSet{ m_lightPassRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_FRAME, + MaxViewportFrameDescriptors }; addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, set); return true; }); - - std::array params = {}; - params[0].pName = "lightObjectBuffer"; - params[0].ppBuffers = &m_lightPassBuffer[setIndex].m_handle; - updateDescriptorSet(forgeRenderer->Rend(), 0, m_lightPerFrameSet[setIndex].m_handle, params.size(), params.data()); + for(uint32_t i = 0; i < MaxViewportFrameDescriptors; i++) { + std::array params = {}; + params[0].pName = "lightObjectBuffer"; + params[0].ppBuffers = &m_lightPassBuffer[setIndex].m_handle; + updateDescriptorSet(forgeRenderer->Rend(), i, m_lightPerFrameSet[setIndex].m_handle, params.size(), params.data()); + } } } @@ -2340,13 +2392,23 @@ namespace hpl { shadowMapData.m_aspect = 0; shadowMapData.m_light = nullptr; - CmdPoolDesc cmdPoolDesc = {}; - cmdPoolDesc.pQueue = forgeRenderer->GetGraphicsQueue(); - addCmdPool(forgeRenderer->Rend(), &cmdPoolDesc, &shadowMapData.m_pool); - CmdDesc cmdDesc = {}; - cmdDesc.pPool = shadowMapData.m_pool; - addCmd(forgeRenderer->Rend(), &cmdDesc, &shadowMapData.m_cmd); - addFence(forgeRenderer->Rend(), &shadowMapData.m_shadowFence); + shadowMapData.m_pool.Load(forgeRenderer->Rend(), [&](CmdPool** pool) { + CmdPoolDesc cmdPoolDesc = {}; + cmdPoolDesc.pQueue = forgeRenderer->GetGraphicsQueue(); + addCmdPool(forgeRenderer->Rend(), &cmdPoolDesc, pool); + return true; + }); + + shadowMapData.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { + CmdDesc cmdDesc = {}; + cmdDesc.pPool = shadowMapData.m_pool.m_handle; + addCmd(forgeRenderer->Rend(), &cmdDesc, cmd); + return true; + }); + shadowMapData.m_shadowFence.Load(forgeRenderer->Rend(), [&](Fence** fence) { + addFence(forgeRenderer->Rend(), fence); + return true; + }); return shadowMapData; }; @@ -2354,8 +2416,7 @@ namespace hpl { m_shadowMapData[eShadowMapResolution_High].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_High])); } for (size_t i = 0; i < 32; ++i) { - m_shadowMapData[eShadowMapResolution_Medium].emplace_back( - createShadowMap(shadowSizes[startSize + eShadowMapResolution_Medium])); + m_shadowMapData[eShadowMapResolution_Medium].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_Medium])); } for (size_t i = 0; i < 32; ++i) { m_shadowMapData[eShadowMapResolution_Low].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_Low])); @@ -2402,10 +2463,10 @@ namespace hpl { void cRendererDeferred::DestroyData() { } - uint32_t cRendererDeferred::updateFrameDescriptor( const ForgeRenderer::Frame& frame,Cmd* cmd, cWorld* apWorld,const PerFrameOption& options) { - + uint32_t cRendererDeferred::updateFrameDescriptor( + const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options) { uint32_t index = m_materialSet.m_frameIndex; - BufferUpdateDesc updatePerFrameConstantsDesc = { m_perFrameBuffer[index].m_handle, 0}; + BufferUpdateDesc updatePerFrameConstantsDesc = { m_perFrameBuffer[index].m_handle, 0 }; beginUpdateResource(&updatePerFrameConstantsDesc); auto* uniformFrameData = reinterpret_cast(updatePerFrameConstantsDesc.pMappedData); uniformFrameData->m_viewMatrix = cMath::ToForgeMat(options.m_viewMat.GetTranspose()); @@ -2425,735 +2486,659 @@ namespace hpl { uniformFrameData->fogColor = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); endUpdateResource(&updatePerFrameConstantsDesc, NULL); - m_materialSet.m_frameIndex = (m_materialSet.m_frameIndex + 1) % MaxMaterialFrameDescriptors; + m_materialSet.m_frameIndex = (m_materialSet.m_frameIndex + 1) % MaxViewportFrameDescriptors; return index; } - uint32_t cRendererDeferred::cmdBindMaterialAndObject(Cmd* cmd, + void cRendererDeferred::cmdIlluminationPass(Cmd* cmd, const ForgeRenderer::Frame& frame, - cMaterial* apMaterial, - iRenderable* apObject, - const PerObjectOption& option) { - - auto* objectDescSet = m_materialSet.m_perObjectSet[frame.m_frameIndex].m_handle; - auto objectLookup = m_materialSet.m_objectDescriptorLookup.find(apObject); - auto& info = m_materialSet.m_materialInfo[apMaterial->materialID()]; - auto& descInfo = info.m_materialDescInfo[frame.m_frameIndex]; - auto& materialType = apMaterial->type(); - - auto metaInfo = std::find_if(cMaterial::MaterialMetaTable.begin(), cMaterial::MaterialMetaTable.end(), [&](auto& info) { - return info.m_id == materialType.m_id; - }); - - if (descInfo.m_material != apMaterial || - descInfo.m_version != apMaterial->Version()) { - descInfo.m_version = apMaterial->Version(); - descInfo.m_material = apMaterial; - - BufferUpdateDesc updateDesc = { m_materialSet.m_materialUniformBuffer.m_handle, - apMaterial->materialID() * sizeof(cMaterial::MaterialType::MaterialData) }; - beginUpdateResource(&updateDesc); - memcpy(updateDesc.pMappedData, &materialType.m_data, sizeof(cMaterial::MaterialType::MaterialData)); - endUpdateResource(&updateDesc, NULL); - - std::array params{}; - size_t paramCount = 0; - - for (auto& supportedTexture : metaInfo->m_usedTextures) { - static constexpr const char* TextureNameLookup[] = { - "diffuseMap", // eMaterialTexture_Diffuse - "normalMap", // eMaterialTexture_NMap - "specularMap", // eMaterialTexture_Specular - "alphaMap", // eMaterialTexture_Alpha - "heightMap", // eMaterialTexture_Height - "illuminationMap", // eMaterialTexture_Illumination - "cubeMap", // eMaterialTexture_CubeMap - "dissolveAlphaMap", // eMaterialTexture_DissolveAlpha - "cubeMapAlpha", // eMaterialTexture_CubeMapAlpha - }; - - auto* image = apMaterial->GetImage(supportedTexture); - if (image) { - params[paramCount].pName = TextureNameLookup[supportedTexture]; - params[paramCount++].ppTextures = &image->GetTexture().m_handle; - descInfo.m_textureHandles[supportedTexture] = image->GetTexture(); - } - } - updateDescriptorSet( - frame.m_renderer->Rend(), - apMaterial->materialID(), - m_materialSet.m_perBatchSet[frame.m_frameIndex].m_handle, - paramCount, - params.data()); - } - - const bool isFound = objectLookup != m_materialSet.m_objectDescriptorLookup.end(); - uint32_t index = isFound ? objectLookup->second : m_materialSet.m_objectIndex++; - if(!isFound) { - cMatrixf modelMat = option.m_modelMatrix.value_or(apObject->GetModelMatrixPtr() ? *apObject->GetModelMatrixPtr() : cMatrixf::Identity); - - cRendererDeferred::UniformObject uniformObjectData = {}; - uniformObjectData.m_dissolveAmount = apObject->GetCoverageAmount(); - uniformObjectData.m_materialIndex = apMaterial->materialID(); - uniformObjectData.m_modelMat = cMath::ToForgeMat4(modelMat.GetTranspose()); - uniformObjectData.m_invModelMat = cMath::ToForgeMat4(cMath::MatrixInverse(modelMat).GetTranspose()); - if (apMaterial) { - uniformObjectData.m_uvMat = cMath::ToForgeMat4(apMaterial->GetUvMatrix()); + cRenderList& renderList, + uint32_t frameDescriptorIndex, + RenderTarget* depthBuffer, + RenderTarget* outputBuffer, + AdditionalIlluminationPassOptions options + ) { + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + std::array targets = { + outputBuffer, + }; + cmdBindRenderTargets( + cmd, targets.size(), targets.data(), depthBuffer, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(cmd, 0.0f, 0.0f, outputBuffer->mWidth, outputBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, outputBuffer->mWidth, outputBuffer->mHeight); + cmdBindPipeline(cmd, options.m_invert ? m_solidIlluminationPipelineCW.m_handle: m_solidIlluminationPipelineCCW.m_handle); + + cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { + cMaterial* pMaterial = illuminationItem->GetMaterial(); + iVertexBuffer* vertexBuffer = illuminationItem->GetVertexBuffer(); + if (pMaterial == nullptr || vertexBuffer == nullptr) { + continue; } - - BufferUpdateDesc updateDesc = { m_objectUniformBuffer[frame.m_frameIndex].m_handle, sizeof(cRendererDeferred::UniformObject) * index}; - beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = uniformObjectData; - endUpdateResource(&updateDesc, NULL); - - m_materialSet.m_objectDescriptorLookup[apObject] = index; + ASSERT(pMaterial->type().m_id == cMaterial::SolidDiffuse && "Invalid material type"); + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(frame.m_cmd, frame, pMaterial, illuminationItem); + materialConst.objectId = instance; + std::array targets = { + eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + }; + LegacyVertexBuffer::GeometryBinding binding; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); + cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); } - cmdBindDescriptorSet(cmd, - detail::resolveMaterialID(apMaterial->GetTextureAntistropy(), apMaterial->GetTextureWrap(), apMaterial->GetTextureFilter()), - m_materialSet.m_materialConstSet.m_handle); - cmdBindDescriptorSet(cmd, apMaterial->materialID(), m_materialSet.m_perBatchSet[frame.m_frameIndex].m_handle); - return index; } - - void cRendererDeferred::Draw( + void cRendererDeferred::cmdLightPass( + Cmd* cmd, const ForgeRenderer::Frame& frame, - cViewport& viewport, - float afFrameTime, - cFrustum* apFrustum, cWorld* apWorld, - cRenderSettings* apSettings, - bool abSendFrameBufferToPostEffects) { - iRenderer::Draw(frame, viewport, afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); - // keep around for the moment ... - BeginRendering(afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); - - if(frame.m_currentFrame != m_activeFrame) { - m_materialSet.m_objectIndex = 0; - m_materialSet.m_objectDescriptorLookup.clear(); - m_activeFrame = frame.m_currentFrame; - } - - mpCurrentRenderList->Clear(); - mpCurrentRenderList->Setup(mfCurrentFrameTime, apFrustum); - - const cMatrixf mainFrustumViewInv = cMath::MatrixInverse(apFrustum->GetViewMatrix()); - const cMatrixf mainFrustumView = apFrustum->GetViewMatrix(); - const cMatrixf mainFrustumProj = apFrustum->GetProjectionMatrix(); - - // auto& swapChainImage = frame.m_swapChain->ppRenderTargets[frame.m_swapChainIndex]; - auto common = m_boundViewportData.resolve(viewport); - if (!common || common->m_size != viewport.GetSize()) { - auto* forgeRenderer = Interface::Get(); - auto viewportData = std::make_unique(); - viewportData->m_size = viewport.GetSize(); - ClearValue optimizedColorClearBlack = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - auto deferredRenderTargetDesc = [&]() { - RenderTargetDesc renderTarget = {}; - renderTarget.mArraySize = 1; - renderTarget.mClearValue = optimizedColorClearBlack; - renderTarget.mDepth = 1; - renderTarget.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; - renderTarget.mWidth = viewportData->m_size.x; - renderTarget.mHeight = viewportData->m_size.y; - renderTarget.mSampleCount = SAMPLE_COUNT_1; - renderTarget.mSampleQuality = 0; - renderTarget.mStartState = RESOURCE_STATE_SHADER_RESOURCE; - return renderTarget; - }; + cFrustum* apFrustum, + cRenderList& renderList, + uint32_t frameDescriptorIndex, + RenderTarget* colorBuffer, + RenderTarget* normalBuffer, + RenderTarget* positionBuffer, + RenderTarget* specularBuffer, + RenderTarget* depthBuffer, + RenderTarget* outputBuffer, + cMatrixf viewMat, + cMatrixf invViewMat, + cMatrixf projectionMat, + AdditionalLightPassOptions options) { + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); + // -------------------------------------------------------------------- + // Render Light Pass + // -------------------------------------------------------------------- + { - for (auto& b : viewportData->m_gBuffer) { - b.m_hiZMipCount = std::min(std::floor(std::log2(std::max(viewportData->m_size.x, viewportData->m_size.y))), MaxHiZMipLevels); - b.m_hizDepthBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - RenderTargetDesc renderTargetDesc = {}; - renderTargetDesc.mArraySize = 1; - renderTargetDesc.mDepth = 1; - renderTargetDesc.mMipLevels = b.m_hiZMipCount; - renderTargetDesc.mFormat = TinyImageFormat_R32_SFLOAT; - renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - renderTargetDesc.mWidth = viewportData->m_size.x; - renderTargetDesc.mHeight = viewportData->m_size.y; - renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; - renderTargetDesc.mSampleQuality = 0; - renderTargetDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; - renderTargetDesc.pName = "hi-z depth buffer"; - addRenderTarget(forgeRenderer->Rend(), &renderTargetDesc, handle); - return true; - }); + float fScreenArea = (float)(outputBuffer->mWidth * outputBuffer->mHeight); + int mlMinLargeLightArea = (int)(MinLargeLightNormalizedArea * fScreenArea); - b.m_depthBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = DepthBufferFormat; - targetDesc.mStartState = RESOURCE_STATE_DEPTH_WRITE; - targetDesc.pName = "Depth RT"; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); - b.m_normalBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = NormalBufferFormat; - targetDesc.pName = "Normal RT"; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); - b.m_positionBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = PositionBufferFormat; - targetDesc.pName = "Position RT"; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); - b.m_specularBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = SpecularBufferFormat; - targetDesc.pName = "Specular RT"; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); - b.m_colorBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = ColorBufferFormat; - targetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - targetDesc.pName = "Color RT"; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); - b.m_refractionImage.Load([&](Texture** texture) { - TextureLoadDesc loadDesc = {}; - loadDesc.ppTexture = texture; - TextureDesc refractionImageDesc = {}; - refractionImageDesc.mArraySize = 1; - refractionImageDesc.mDepth = 1; - refractionImageDesc.mMipLevels = 1; - refractionImageDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; - refractionImageDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - refractionImageDesc.mWidth = viewportData->m_size.x; - refractionImageDesc.mHeight = viewportData->m_size.y; - refractionImageDesc.mSampleCount = SAMPLE_COUNT_1; - refractionImageDesc.mSampleQuality = 0; - refractionImageDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE; - refractionImageDesc.pName = "Refraction Image"; - loadDesc.pDesc = &refractionImageDesc; - addResource(&loadDesc, nullptr); - return true; - }); - b.m_outputBuffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = ColorBufferFormat; - targetDesc.mDescriptors = DESCRIPTOR_TYPE_RW_TEXTURE | DESCRIPTOR_TYPE_TEXTURE; - addRenderTarget(forgeRenderer->Rend(), &targetDesc, handle); - return true; - }); + // std::array, eDeferredLightList_LastEnum> sortedLights; + // DON'T touch deferredLights after this point + std::vector deferredLights; + std::vector deferredLightRenderBack; + std::vector deferredLightStencilFront; + + for (auto& light : renderList.GetLights()) { + auto lightType = light->GetLightType(); + auto& deferredLightData = deferredLights.emplace_back(detail::DeferredLight()); + deferredLightData.m_light = light; + if (lightType == eLightType_Box) { + continue; + } + switch (lightType) { + case eLightType_Point: + { + deferredLightData.m_insideNearPlane = apFrustum->CheckSphereNearPlaneIntersection( + light->GetWorldPosition(), light->GetRadius() * kLightRadiusMul_Low); + detail::SetupLightMatrix( + deferredLightData.m_mtxViewSpaceRender, + deferredLightData.m_mtxViewSpaceTransform, + light, + apFrustum, + kLightRadiusMul_Medium); + deferredLightData.m_clipRect = cMath::GetClipRectFromSphere( + deferredLightData.m_mtxViewSpaceRender.GetTranslation(), light->GetRadius(), apFrustum, cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), true, 0); + break; + } + case eLightType_Spot: + { + cLightSpot* lightSpot = static_cast(light); + deferredLightData.m_insideNearPlane = apFrustum->CheckFrustumNearPlaneIntersection(lightSpot->GetFrustum()); + detail::SetupLightMatrix( + deferredLightData.m_mtxViewSpaceRender, + deferredLightData.m_mtxViewSpaceTransform, + light, + apFrustum, + kLightRadiusMul_Medium); + cMath::GetClipRectFromBV(deferredLightData.m_clipRect, *light->GetBoundingVolume(), apFrustum, cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), 0); + break; + } + default: + break; + } } - common = m_boundViewportData.update(viewport, std::move(viewportData)); - } + for (auto& deferredLight : deferredLights) { + auto light = deferredLight.m_light; + auto lightType = deferredLight.m_light->GetLightType(); - auto& currentGBuffer = common->m_gBuffer[frame.m_frameIndex]; - uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); + if (lightType == eLightType_Spot && light->GetCastShadows() && mpCurrentSettings->mbRenderShadows) { + cLightSpot* pLightSpot = static_cast(light); - const uint32_t mainFrameIndex = updateFrameDescriptor(frame, frame.m_cmd, apWorld, { - .m_size = float2(common->m_size.x, common->m_size.y), - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj - }); + bool castShadow = false; + eShadowMapResolution shadowMapResolution = eShadowMapResolution_Low; + //////////////////////// + // Inside near plane, use max resolution + if (deferredLight.m_insideNearPlane) { + castShadow = true; - { - std::array params = {}; - params[0].pName = "refractionMap"; - params[0].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; - updateDescriptorSet(frame.m_renderer->Rend(), mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle, params.size(), params.data()); - } + shadowMapResolution = rendering::detail::GetShadowMapResolution( + light->GetShadowMapResolution(), mpCurrentSettings->mMaxShadowMapResolution); + } else { + cVector3f vIntersection = pLightSpot->GetFrustum()->GetOrigin(); + pLightSpot->GetFrustum()->CheckLineIntersection( + apFrustum->GetOrigin(), light->GetBoundingVolume()->GetWorldCenter(), vIntersection); - frame.m_resourcePool->Push(currentGBuffer.m_colorBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_normalBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_positionBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_specularBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_depthBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_outputBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_refractionImage); - // Setup far plane coordinates - m_farPlane = apFrustum->GetFarPlane(); - m_farTop = -tan(apFrustum->GetFOV() * 0.5f) * m_farPlane; - m_farBottom = -m_farTop; - m_farRight = m_farBottom * apFrustum->GetAspect(); - m_farLeft = -m_farRight; - - /////////////////////////// - // Occlusion testing - { - ASSERT(currentGBuffer.m_depthBuffer.m_handle && "Depth buffer not created"); - struct RenderableContainer { - iRenderableContainer* m_continer; - eWorldContainerType m_type; - }; - std::array worldContainers = { - RenderableContainer{ mpCurrentWorld->GetRenderableContainer(eWorldContainerType_Dynamic), eWorldContainerType_Dynamic }, - RenderableContainer{ mpCurrentWorld->GetRenderableContainer(eWorldContainerType_Static), eWorldContainerType_Static } - }; + float fDistToLight = cMath::Vector3Dist(apFrustum->GetOrigin(), vIntersection); - for (auto& container : worldContainers) { - container.m_continer->UpdateBeforeRendering(); - } - std::vector uniformTest; - uint32_t queryIndex = 0; - std::vector occlusionQueryAlpha; - // start pre-z pass - beginCmd(m_prePassCmd.m_handle); - { - std::function walkRenderables; - walkRenderables = [&](iRenderableContainerNode* childNode, eWorldContainerType containerType) { - childNode->UpdateBeforeUse(); - for (auto& childNode : childNode->GetChildNodes()) { - childNode->UpdateBeforeUse(); - eCollision frustumCollision = apFrustum->CollideNode(childNode); - if (frustumCollision == eCollision_Outside) { - continue; + castShadow = true; + shadowMapResolution = rendering::detail::GetShadowMapResolution( + light->GetShadowMapResolution(), mpCurrentSettings->mMaxShadowMapResolution); + + /////////////////////// + // Skip shadow + if (fDistToLight > m_shadowDistanceNone) { + castShadow = false; } - if (apFrustum->CheckAABBNearPlaneIntersection(childNode->GetMin(), childNode->GetMax())) { - cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), childNode->GetCenter()); - childNode->SetViewDistance(vViewSpacePos.z); - childNode->SetInsideView(true); - } else { - // Frustum origin is outside of node. Do intersection test. - cVector3f vIntersection; - cMath::CheckAABBLineIntersection( - childNode->GetMin(), - childNode->GetMax(), - apFrustum->GetOrigin(), - childNode->GetCenter(), - &vIntersection, - NULL); - cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), vIntersection); - childNode->SetViewDistance(vViewSpacePos.z); - childNode->SetInsideView(false); + /////////////////////// + // Use Low + else if (fDistToLight > m_shadowDistanceLow) { + if (shadowMapResolution == eShadowMapResolution_Low) { + castShadow = false; + } + shadowMapResolution = eShadowMapResolution_Low; } - walkRenderables(childNode, containerType); - } - for (auto& pObject : childNode->GetObjects()) { - if (!rendering::detail::IsObjectIsVisible(pObject, eRenderableFlag_VisibleInNonReflection, {})) { - continue; + /////////////////////// + // Use Medium + else if (fDistToLight > m_shadowDistanceMedium) { + if (shadowMapResolution == eShadowMapResolution_High) { + shadowMapResolution = eShadowMapResolution_Medium; + } else { + shadowMapResolution = eShadowMapResolution_Low; + } } - const bool visibleLastFrame = (m_preZPassRenderables.empty() || m_preZPassRenderables.contains(pObject)); - - auto& test = uniformTest.emplace_back(); - test.m_preZPass = visibleLastFrame; - test.m_renderable = pObject; - - cMaterial* pMaterial = pObject->GetMaterial(); - iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); + } - if (pObject && pObject->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { - pObject->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); - pObject->UpdateGraphicsForFrame(afFrameTime); - } + cFrustum* pLightFrustum = pLightSpot->GetFrustum(); + std::vector shadowCasters; + if (castShadow && + detail::SetupShadowMapRendering(shadowCasters, apWorld, pLightFrustum, pLightSpot, mvCurrentOcclusionPlanes)) { + auto findBestShadowMap = [&](eShadowMapResolution resolution, iLight* light) -> cRendererDeferred::ShadowMapData* { + auto& shadowMapVec = m_shadowMapData[resolution]; + uint32_t maxFrameDistance = 0; + size_t bestIndex = 0; + for (size_t i = 0; i < shadowMapVec.size(); ++i) { + auto& shadowMap = shadowMapVec[i]; + if (shadowMap.m_light == light) { + shadowMap.m_frameCount = frame.m_currentFrame; + return &shadowMap; + } - if (pMaterial && pMaterial->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { - pMaterial->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); - pMaterial->UpdateBeforeRendering(afFrameTime); - } - //////////////////////////////////////// - // Update per viewport specific and set amtrix point - // Skip this for non-decal translucent! This is because the water rendering might mess it up otherwise! - if (pMaterial == NULL || pMaterial->GetType()->IsTranslucent() == false || pMaterial->GetType()->IsDecal()) { - // skip rendering if the update return false - if (pObject->UpdateGraphicsForViewport(apFrustum, afFrameTime) == false) { - return; + const uint32_t frameDist = frame.m_currentFrame - shadowMap.m_frameCount; + if (frameDist > maxFrameDistance) { + maxFrameDistance = frameDist; + bestIndex = i; + } } + shadowMapVec[bestIndex].m_frameCount = frame.m_currentFrame; + return &shadowMapVec[bestIndex]; + }; + auto* shadowMapData = findBestShadowMap(shadowMapResolution, pLightSpot); + if (shadowMapData) { + deferredLight.m_shadowMapData = shadowMapData; + // testing if the shadow map needs to be updated + if (shadowMapData->m_transformCount != pLightSpot->GetTransformUpdateCount() || [&]() -> bool { + // Check if texture map and light are valid + if (pLightSpot->GetOcclusionCullShadowCasters()) { + return true; + } - pObject->SetModelMatrixPtr(pObject->GetModelMatrix(apFrustum)); - } - // Only set a matrix used for sorting. Calculate the proper in the trans rendering! - else { - pObject->SetModelMatrixPtr(pObject->GetModelMatrix(NULL)); - } + if (pLightSpot->GetLightType() == eLightType_Spot && + (pLightSpot->GetAspect() != shadowMapData->m_aspect || + pLightSpot->GetFOV() != shadowMapData->m_fov)) { + return true; + } + return !pLightSpot->ShadowCastersAreUnchanged(shadowCasters); + }()) { + shadowMapData->m_light = pLightSpot; + shadowMapData->m_transformCount = pLightSpot->GetTransformUpdateCount(); + shadowMapData->m_radius = pLightSpot->GetRadius(); + shadowMapData->m_aspect = pLightSpot->GetAspect(); + shadowMapData->m_fov = pLightSpot->GetFOV(); - if (visibleLastFrame && pObject->UsesOcclusionQuery()) { - auto& occlusionAlpha = occlusionQueryAlpha.emplace_back(); - occlusionAlpha.m_renderable = pObject; - } - } - }; - for (auto& it : worldContainers) { - iRenderableContainerNode* pNode = it.m_continer->GetRoot(); - pNode->UpdateBeforeUse(); // Make sure node is updated. - pNode->SetInsideView(true); // We never want to check root! Assume player is inside. - walkRenderables(pNode, it.m_type); - } + pLightSpot->SetShadowCasterCacheFromVec(shadowCasters); - std::sort(uniformTest.begin(), uniformTest.end(), [&](UniformTest& apObjectA, UniformTest& apObjectB) { - cMaterial* pMatA = apObjectA.m_renderable->GetMaterial(); - cMaterial* pMatB = apObjectB.m_renderable->GetMaterial(); - if (!(pMatA && pMatB)) { - return false; - } + FenceStatus fenceStatus; + getFenceStatus(frame.m_renderer->Rend(), shadowMapData->m_shadowFence.m_handle, &fenceStatus); + if (fenceStatus == FENCE_STATUS_INCOMPLETE) + waitForFences(frame.m_renderer->Rend(), 1, &shadowMapData->m_shadowFence.m_handle); + resetCmdPool(frame.m_renderer->Rend(), shadowMapData->m_pool.m_handle); - ////////////////////////// - // Alpha mode - if (pMatA->GetAlphaMode() != pMatB->GetAlphaMode()) { - return pMatA->GetAlphaMode() < pMatB->GetAlphaMode(); - } + beginCmd(shadowMapData->m_cmd.m_handle); + { + cmdBindRenderTargets(shadowMapData->m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ + shadowMapData->m_target.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, + }; + cmdResourceBarrier(shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } - ////////////////////////// - // If alpha, sort by texture (we know alpha is same for both materials, so can just test one) - if (pMatA->GetAlphaMode() == eMaterialAlphaMode_Trans) { - if (pMatA->GetImage(eMaterialTexture_Diffuse) != pMatB->GetImage(eMaterialTexture_Diffuse)) { - return pMatA->GetImage(eMaterialTexture_Diffuse) < pMatB->GetImage(eMaterialTexture_Diffuse); + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionDepth = LOAD_ACTION_CLEAR; + loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; + loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; + cmdBindRenderTargets( + shadowMapData->m_cmd.m_handle, 0, NULL, shadowMapData->m_target.m_handle, &loadActions, NULL, NULL, -1, -1); + cmdSetViewport( + shadowMapData->m_cmd.m_handle, + 0.0f, + static_cast(shadowMapData->m_target.m_handle->mHeight), + static_cast(shadowMapData->m_target.m_handle->mWidth), + -static_cast(shadowMapData->m_target.m_handle->mHeight), + 0.0f, + 1.0f); + cmdSetScissor( + shadowMapData->m_cmd.m_handle, + 0, + 0, + shadowMapData->m_target.m_handle->mWidth, + shadowMapData->m_target.m_handle->mHeight); + cmdBindPipeline(shadowMapData->m_cmd.m_handle, options.m_invert ? m_zPassShadowPipelineCCW.m_handle : m_zPassShadowPipelineCW.m_handle); + + uint32_t shadowFrameIndex = updateFrameDescriptor( + frame, + shadowMapData->m_cmd.m_handle, + apWorld, + { .m_size = float2(outputBuffer->mWidth, outputBuffer->mHeight), + .m_viewMat = pLightFrustum->GetViewMatrix(), + .m_projectionMat = pLightFrustum->GetProjectionMatrix() }); + cmdBindDescriptorSet( + shadowMapData->m_cmd.m_handle, shadowFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + for (auto& pObject : shadowCasters) { + eMaterialRenderMode renderMode = + pObject->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; + cMaterial* pMaterial = pObject->GetMaterial(); + iMaterialType* materialType = pMaterial->GetType(); + iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); + if (vertexBuffer == nullptr || materialType == nullptr) { + return; + } + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(shadowMapData->m_cmd.m_handle, frame, pMaterial, pObject); + materialConst.objectId = instance; + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + LegacyVertexBuffer::GeometryBinding binding{}; + static_cast(vertexBuffer) + ->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + detail::cmdDefaultLegacyGeomBinding(shadowMapData->m_cmd.m_handle, frame, binding); + cmdBindPushConstants( + shadowMapData->m_cmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(shadowMapData->m_cmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + } + { + cmdBindRenderTargets(shadowMapData->m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ + shadowMapData->m_target.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + endCmd(shadowMapData->m_cmd.m_handle); + QueueSubmitDesc submitDesc = {}; + submitDesc.mCmdCount = 1; + submitDesc.ppCmds = &shadowMapData->m_cmd.m_handle; + submitDesc.pSignalFence = shadowMapData->m_shadowFence.m_handle; + submitDesc.mSubmitDone = true; + queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); + } } } + // render shadow map + } + } - ////////////////////////// - // View space depth, no need to test further since Z should almost never be the same for two objects. - // use ">" since we want to render things closest to the screen first. - return apObjectA.m_renderable->GetViewSpaceZ() > apObjectB.m_renderable->GetViewSpaceZ(); - // return apObjectA < apObjectB; - }); - - cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 1, 0, "Pre Z"); - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_DONTCARE; - loadActions.mLoadActionDepth = LOAD_ACTION_CLEAR; - loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; - loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; - - cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, currentGBuffer.m_depthBuffer.m_handle, &loadActions, NULL, NULL, -1, -1); - cmdSetViewport(m_prePassCmd.m_handle, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(m_prePassCmd.m_handle, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(m_prePassCmd.m_handle, m_zPassPipeline.m_handle); + mpCurrentSettings->mlNumberOfLightsRendered = 0; + for (auto& deferredLight : deferredLights) { + // cDeferredLight* pLightData = mvTempDeferredLights[i]; + iLight* pLight = deferredLight.m_light; + eLightType lightType = pLight->GetLightType(); - cmdBindDescriptorSet(m_prePassCmd.m_handle, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + //////////////////////// + // If box, we have special case... + if (lightType == eLightType_Box) { + cLightBox* pLightBox = static_cast(pLight); + // Set up matrix + deferredLight.m_mtxViewSpaceRender = cMath::MatrixScale(pLightBox->GetSize()); + deferredLight.m_mtxViewSpaceRender.SetTranslation(pLightBox->GetWorldPosition()); + deferredLight.m_mtxViewSpaceRender = cMath::MatrixMul(apFrustum->GetViewMatrix(), deferredLight.m_mtxViewSpaceRender); - UniformPropBlock uniformPropBlock = {}; - for (size_t i = 0; i < uniformTest.size(); i++) { - auto& test = uniformTest[i]; - cMaterial* pMaterial = test.m_renderable->GetMaterial(); - iVertexBuffer* vertexBuffer = test.m_renderable->GetVertexBuffer(); + mpCurrentSettings->mlNumberOfLightsRendered++; - ASSERT(uniformTest.size() < MaxObjectTest && "Too many renderables"); - auto* pBoundingVolume = test.m_renderable->GetBoundingVolume(); + // Check if near plane is inside box. If so only render back + if (apFrustum->CheckBVNearPlaneIntersection(pLight->GetBoundingVolume())) { + deferredLightRenderBack.push_back(&deferredLight); + } else { + deferredLightStencilFront.push_back(&deferredLight); + } - BufferUpdateDesc updateDesc = { m_hiZBoundBoxBuffer.m_handle, i * (2 * sizeof(float4)), sizeof(float4) * 2}; - auto boundBoxMin = pBoundingVolume->GetMin(); - auto boundBoxMax = pBoundingVolume->GetMax(); - beginUpdateResource(&updateDesc); - reinterpret_cast(updateDesc.pMappedData)[0] = - float4(boundBoxMin.x, boundBoxMin.y, boundBoxMin.z, 0.0f); - reinterpret_cast(updateDesc.pMappedData)[1] = - float4(boundBoxMax.x, boundBoxMax.y, boundBoxMax.z, 0.0f); - endUpdateResource(&updateDesc, nullptr); + continue; + } + mpCurrentSettings->mlNumberOfLightsRendered++; - if (!test.m_preZPass || !vertexBuffer || !pMaterial || pMaterial->GetType()->IsTranslucent()) { - continue; - } + deferredLightRenderBack.emplace_back(&deferredLight); + } + std::sort(deferredLightStencilFront.begin(), deferredLightStencilFront.end(), detail::SortDeferredLightDefault); + std::sort(deferredLightRenderBack.begin(), deferredLightRenderBack.end(), detail::SortDeferredLightDefault); - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - m_prePassCmd.m_handle, - frame, - pMaterial, - test.m_renderable, + { + // updates and binds the light data + auto cmdBindLightDescriptor = [&](detail::DeferredLight* light) { + DescriptorData params[10] = {}; + size_t paramCount = 0; + UniformLightData uniformObjectData = {}; + + const auto modelViewMtx = cMath::MatrixMul(apFrustum->GetViewMatrix(), light->m_light->GetWorldMatrix()); + const auto viewProjectionMat = cMath::MatrixMul(projectionMat, viewMat); + + switch (light->m_light->GetLightType()) { + case eLightType_Point: { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - }); - materialConst.objectId = instance; - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(m_prePassCmd.m_handle, frame, binding); - cmdBindPushConstants(m_prePassCmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); - } + uniformObjectData.m_common.m_mvp = cMath::ToForgeMat4( + cMath::MatrixMul( + viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light))) + .GetTranspose()); - uniformPropBlock.maxMipLevel = currentGBuffer.m_hiZMipCount - 1; - uniformPropBlock.depthDim = uint2(common->m_size.x, common->m_size.y); - uniformPropBlock.numObjects = uniformTest.size(); + cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); + const auto color = light->m_light->GetDiffuseColor(); - BufferUpdateDesc updateDesc = { m_hiZOcclusionUniformBuffer.m_handle, 0, sizeof(UniformPropBlock) }; - beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = uniformPropBlock; - endUpdateResource(&updateDesc, nullptr); - cmdEndDebugMarker(m_prePassCmd.m_handle); - } - { - cmdBeginDebugMarker(m_prePassCmd.m_handle, 1, 1, 0, "Occlusion Query"); - LegacyVertexBuffer::GeometryBinding binding{}; - std::array targets = { eVertexBufferElement_Position }; - static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - - - uint32_t occlusionObjectIndex = getDescriptorIndexFromName(m_rootSignatureOcclusuion.m_handle, "rootConstant"); - uint32_t occlusionIndex = 0; - cMatrixf viewProj = cMath::MatrixMul(mainFrustumProj, mainFrustumView); - cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorOcclusionConstSet.m_handle); - for (auto& query : occlusionQueryAlpha) { - if (TypeInfo::IsType(*query.m_renderable)) { - cBillboard* pBillboard = static_cast(query.m_renderable); - - auto mvp = cMath::ToForgeMat( - cMath::MatrixMul( - viewProj, - cMath::MatrixMul(pBillboard->GetWorldMatrix(), cMath::MatrixScale(pBillboard->GetHaloSourceSize()))) - .GetTranspose()); - - BufferUpdateDesc updateDesc = { m_occlusionUniformBuffer.m_handle, m_occlusionIndex * sizeof(mat4)}; - beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = mvp; - endUpdateResource(&updateDesc, NULL); - - cmdBindPushConstants(m_prePassCmd.m_handle, m_rootSignatureOcclusuion.m_handle, occlusionObjectIndex, &m_occlusionIndex); - - detail::cmdDefaultLegacyGeomBinding(m_prePassCmd.m_handle, frame, binding); - - QueryDesc queryDesc = {}; - queryDesc.mIndex = queryIndex++; - cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineOcclusionQuery.m_handle); - cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); - cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - query.m_queryIndex = queryDesc.mIndex; - - queryDesc.mIndex = queryIndex++; - cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineMaxOcclusionQuery.m_handle); - cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); - cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - query.m_maxQueryIndex = queryDesc.mIndex; - - m_occlusionIndex = (m_occlusionIndex + 1) % MaxOcclusionDescSize; - } - } - cmdEndDebugMarker(m_prePassCmd.m_handle); - } - // hi-z generate pass - { - cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 0, 0, "Generate HI-Z"); - { - cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ - currentGBuffer.m_hizDepthBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_RENDER_TARGET }, - }; - cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_DONTCARE; - loadActions.mClearColorValues[0] = { .r = 1.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f }; - cmdBindRenderTargets( - m_prePassCmd.m_handle, 1, ¤tGBuffer.m_hizDepthBuffer.m_handle, NULL, &loadActions, NULL, NULL, -1, -1); + if (light->m_light->GetGoboTexture()) { + uniformObjectData.m_common.m_config |= LightConfiguration::HasGoboMap; + params[paramCount].pName = "goboCubeMap"; + params[paramCount++].ppTextures = &light->m_light->GetGoboTexture()->GetTexture().m_handle; + m_lightResources[frame.m_frameIndex][m_lightIndex].m_goboCubeMap = + light->m_light->GetGoboTexture()->GetTexture(); + } - std::array params = {}; - params[0].pName = "sourceInput"; - params[0].ppTextures = ¤tGBuffer.m_depthBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), 0, m_descriptorCopyDepth.m_handle, params.size(), params.data()); + auto falloffMap = light->m_light->GetFalloffMap(); + ASSERT(falloffMap && "Point light needs a falloff map"); + params[paramCount].pName = "attenuationLightMap"; + params[paramCount++].ppTextures = &falloffMap->GetTexture().m_handle; + m_lightResources[frame.m_frameIndex][m_lightIndex].m_attenuationLightMap = falloffMap->GetTexture(); + + uniformObjectData.m_pointLight.m_radius = light->m_light->GetRadius(); + uniformObjectData.m_pointLight.m_lightPos = float3(lightViewPos.x, lightViewPos.y, lightViewPos.z); + uniformObjectData.m_pointLight.m_lightColor = float4(color.r, color.g, color.b, color.a); + cMatrixf mtxInvViewRotation = + cMath::MatrixMul(light->m_light->GetWorldMatrix(), invViewMat).GetTranspose(); + uniformObjectData.m_pointLight.m_invViewRotation = cMath::ToForgeMat4(mtxInvViewRotation); + break; + } + case eLightType_Spot: + { + cLightSpot* pLightSpot = static_cast(light->m_light); - cmdSetViewport( - m_prePassCmd.m_handle, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); - cmdSetScissor(m_prePassCmd.m_handle, 0, 0, static_cast(common->m_size.x), static_cast(common->m_size.y)); - cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineCopyDepth.m_handle); + cMatrixf spotViewProj = cMath::MatrixMul(pLightSpot->GetViewProjMatrix(), invViewMat).GetTranspose(); + cVector3f forward = cMath::MatrixMul3x3(light->m_mtxViewSpaceTransform, cVector3f(0, 0, 1)); + cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); + const auto color = pLightSpot->GetDiffuseColor(); - cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorCopyDepth.m_handle); - cmdDraw(m_prePassCmd.m_handle, 3, 0); - } + uniformObjectData.m_common.m_mvp = cMath::ToForgeMat4( + cMath::MatrixMul( + viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light))) + .GetTranspose()); - { - cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, - RenderTargetBarrier{ - currentGBuffer.m_hizDepthBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_UNORDERED_ACCESS }, - }; - cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - uint32_t rootConstantIndex = getDescriptorIndexFromName(m_rootSignatureHIZOcclusion.m_handle, "uRootConstants"); - uint32_t width = static_cast(common->m_size.x); - uint32_t height = static_cast(common->m_size.y); - for (uint32_t lod = 1; lod < currentGBuffer.m_hiZMipCount; ++lod) { - std::array params = {}; - params[0].pName = "depthInput"; - params[0].mBindMipChain = true; - params[0].ppTextures = ¤tGBuffer.m_hizDepthBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), lod, m_descriptorSetHIZGenerate.m_handle, params.size(), params.data()); - - width /= 2; - height /= 2; - struct { - uint2 screenDim; - uint32_t mipLevel; - } pushConstants = {}; - - pushConstants.mipLevel = lod; - pushConstants.screenDim = uint2(common->m_size.x, common->m_size.y); - - // bind lod to push constant - cmdBindPushConstants(m_prePassCmd.m_handle, m_rootSignatureHIZOcclusion.m_handle, rootConstantIndex, &pushConstants); - cmdBindDescriptorSet(m_prePassCmd.m_handle, lod, m_descriptorSetHIZGenerate.m_handle); - cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineHIZGenerate.m_handle); - cmdDispatch(m_prePassCmd.m_handle, static_cast(width / 16) + 1, static_cast(height / 16) + 1, 1); - - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_hizDepthBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_UNORDERED_ACCESS }, - }; - cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - { - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_hizDepthBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE} - }; - cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - cmdEndDebugMarker(m_prePassCmd.m_handle); + if (light->m_shadowMapData) { + uniformObjectData.m_common.m_config |= LightConfiguration::HasShadowMap; + params[paramCount].pName = "shadowMap"; + params[paramCount++].ppTextures = &light->m_shadowMapData->m_target.m_handle->pTexture; + } + if (m_shadowJitterTexture.IsValid()) { + params[paramCount].pName = "shadowOffsetMap"; + params[paramCount++].ppTextures = &m_shadowJitterTexture.m_handle; + } + uniformObjectData.m_spotLight.m_spotViewProj = cMath::ToForgeMat4(spotViewProj); + uniformObjectData.m_spotLight.m_oneMinusCosHalfSpotFOV = 1 - pLightSpot->GetCosHalfFOV(); + uniformObjectData.m_spotLight.m_radius = light->m_light->GetRadius(); + uniformObjectData.m_spotLight.m_forward = float3(forward.x, forward.y, forward.z); + uniformObjectData.m_spotLight.m_color = float4(color.r, color.g, color.b, color.a); + uniformObjectData.m_spotLight.m_pos = float3(lightViewPos.x, lightViewPos.y, lightViewPos.z); - cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 1, 0, "AABB Hi-Z"); - { - std::array params = {}; - params[0].pName = "perFrameConstants"; - params[0].ppBuffers = &m_perFrameBuffer[mainFrameIndex].m_handle; - params[1].pName = "objectUniformBlock"; - params[1].ppBuffers = &m_hiZOcclusionUniformBuffer.m_handle; - params[2].pName = "occlusionTest"; - params[2].ppBuffers = &m_occlusionTestBuffer.m_handle; - params[3].pName = "occlusionBoxBuffer"; - params[3].ppBuffers = &m_hiZBoundBoxBuffer.m_handle; - params[4].pName = "depthTest"; - params[4].ppTextures = ¤tGBuffer.m_hizDepthBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), 0, m_descriptorAABBOcclusionTest.m_handle, params.size(), params.data()); - - cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorAABBOcclusionTest.m_handle); - cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineAABBOcclusionTest.m_handle); - cmdDispatch(m_prePassCmd.m_handle, static_cast(uniformTest.size() / 128) + 1, 1, 1); - { - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_hizDepthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS} - }; - cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - } - cmdEndDebugMarker(m_prePassCmd.m_handle); - cmdResolveQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, m_occlusionReadBackBuffer.m_handle, 0, queryIndex); - endCmd(m_prePassCmd.m_handle); - - // Submit the gpu work. - QueueSubmitDesc submitDesc = {}; - submitDesc.mCmdCount = 1; - submitDesc.ppCmds = &m_prePassCmd.m_handle; - submitDesc.pSignalFence = m_prePassFence.m_handle; - submitDesc.mSubmitDone = true; - queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); - FenceStatus fenceStatus; - getFenceStatus(frame.m_renderer->Rend(), m_prePassFence.m_handle, &fenceStatus); - if (fenceStatus == FENCE_STATUS_INCOMPLETE) { - waitForFences(frame.m_renderer->Rend(), 1, &m_prePassFence.m_handle); - } - resetCmdPool(frame.m_renderer->Rend(), m_prePassPool.m_handle); - - uint64_t* occlusionCount = reinterpret_cast(m_occlusionReadBackBuffer.m_handle->pCpuMappedAddress); - for (auto& query : occlusionQueryAlpha) { - if (TypeInfo::IsType(*query.m_renderable)) { - cBillboard* pBillboard = static_cast(query.m_renderable); - float maxSamples = static_cast(occlusionCount[query.m_maxQueryIndex]); - float samples = static_cast(occlusionCount[query.m_queryIndex]); - float billboardCoverage = pBillboard->getAreaOfScreenSpace(apFrustum); - if (maxSamples > 0.0f) { - pBillboard->SetHaloAlpha(billboardCoverage * (samples / maxSamples)); - } else { - pBillboard->SetHaloAlpha(0.0f); + auto goboImage = light->m_light->GetGoboTexture(); + auto spotFallOffImage = pLightSpot->GetSpotFalloffMap(); + auto spotAttenuationImage = pLightSpot->GetFalloffMap(); + if (goboImage) { + uniformObjectData.m_common.m_config |= LightConfiguration::HasGoboMap; + params[paramCount].pName = "goboMap"; + params[paramCount++].ppTextures = &light->m_light->GetGoboTexture()->GetTexture().m_handle; + frame.m_resourcePool->Push(light->m_light->GetGoboTexture()->GetTexture()); + m_lightResources[frame.m_frameIndex][m_lightIndex].m_goboMap = light->m_light->GetGoboTexture()->GetTexture(); + } else { + params[paramCount].pName = "falloffMap"; + params[paramCount++].ppTextures = &spotFallOffImage->GetTexture().m_handle; + frame.m_resourcePool->Push(spotFallOffImage->GetTexture()); + m_lightResources[frame.m_frameIndex][m_lightIndex].m_falloffMap = spotFallOffImage->GetTexture(); + } + m_lightResources[frame.m_frameIndex][m_lightIndex].m_attenuationLightMap = spotAttenuationImage->GetTexture(); + params[paramCount].pName = "attenuationLightMap"; + params[paramCount++].ppTextures = &spotAttenuationImage->GetTexture().m_handle; + frame.m_resourcePool->Push(spotAttenuationImage->GetTexture()); + break; + } + case eLightType_Box: + { + uniformObjectData.m_common.m_mvp = + cMath::ToForgeMat4(cMath::MatrixMul(viewProjectionMat, detail::GetLightMtx(*light)).GetTranspose()); + + cLightBox* pLightBox = static_cast(light->m_light); + const auto& color = light->m_light->GetDiffuseColor(); + uniformObjectData.m_boxLight.m_lightColor = float4(color.r, color.g, color.b, color.a); + break; + } + default: + { + ASSERT(false && "Unsupported light type"); + break; } } + + BufferUpdateDesc updateDesc = { m_lightPassBuffer[frame.m_frameIndex].m_handle, m_lightIndex* sizeof(UniformLightData) }; + beginUpdateResource(&updateDesc); + memcpy(updateDesc.pMappedData, &uniformObjectData, sizeof(UniformLightData)); + endUpdateResource(&updateDesc, NULL); + + updateDescriptorSet( + frame.m_renderer->Rend(), m_lightIndex, m_lightPerLightSet[frame.m_frameIndex].m_handle, paramCount, params); + cmdBindDescriptorSet(cmd, m_lightIndex, m_lightPerLightSet[frame.m_frameIndex].m_handle); + uint32_t index = m_lightIndex; + m_lightIndex++; + return index; + }; + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_CLEAR; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + loadActions.mLoadActionStencil = LOAD_ACTION_CLEAR; + std::array targets = { + outputBuffer, + }; + cmdBindRenderTargets( + cmd, + targets.size(), + targets.data(), + depthBuffer, + &loadActions, + nullptr, + nullptr, + -1, + -1); } - } + cmdSetViewport(cmd, 0.0f, 0.0f, outputBuffer->mWidth, outputBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, outputBuffer->mWidth, outputBuffer->mHeight); - m_preZPassRenderables.clear(); + { + DescriptorData params[15] = {}; + size_t paramCount = 0; - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_DONTCARE; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; - loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; + DescriptorDataRange range = { (uint32_t)(frame.m_frameIndex * sizeof(UniformLightPerFrameSet)), + sizeof(UniformLightPerFrameSet) }; + params[paramCount].pName = "diffuseMap"; + params[paramCount++].ppTextures = &colorBuffer->pTexture; + params[paramCount].pName = "normalMap"; + params[paramCount++].ppTextures = &normalBuffer->pTexture; + params[paramCount].pName = "positionMap"; + params[paramCount++].ppTextures = &positionBuffer->pTexture; + params[paramCount].pName = "specularMap"; + params[paramCount++].ppTextures = &specularBuffer->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), frameDescriptorIndex, m_lightPerFrameSet[frame.m_frameIndex].m_handle, paramCount, params); + } - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Post Z"); - cmdBindRenderTargets(frame.m_cmd, 0, NULL, currentGBuffer.m_depthBuffer.m_handle, &loadActions, NULL, NULL, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_lightPerFrameSet[frame.m_frameIndex].m_handle); - cmdBindPipeline(frame.m_cmd, m_zPassPipeline.m_handle); + // -------------------------------------------------------- + // Draw Point Lights + // Draw Spot Lights + // Draw Box Lights + // -------------------------------------------------------- + cmdBeginDebugMarker(cmd, 0, 1, 0, "Point Light Deferred Stencil front"); + uint32_t lightRootConstantIndex = getDescriptorIndexFromName(m_lightPassRootSignature.m_handle, "lightPushConstant"); + for (auto& light : deferredLightStencilFront) { + cmdSetStencilReferenceValue(cmd, 0xff); - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + std::array elements = { eVertexBufferElement_Position }; + LegacyVertexBuffer::GeometryBinding binding{}; + auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); + ASSERT(lightShape && "Light shape not found"); + static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements, &binding); + detail::cmdDefaultLegacyGeomBinding(cmd, frame, binding); - auto* testResult = reinterpret_cast(m_occlusionTestBuffer.m_handle->pCpuMappedAddress); - for (size_t i = 0; i < uniformTest.size(); ++i) { - if (testResult[i] == 1) { - mpCurrentRenderList->AddObject(uniformTest[i].m_renderable); - m_preZPassRenderables.insert(uniformTest[i].m_renderable); - if (!uniformTest[i].m_preZPass) { - auto* renderable = uniformTest[i].m_renderable; - eMaterialRenderMode renderMode = - renderable->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; + cmdBindPipeline(cmd, options.m_invert ? m_lightStencilPipelineCW.m_handle : m_lightStencilPipelineCCW.m_handle); + uint32_t instance = cmdBindLightDescriptor(light); // bind light descriptor light uniforms + cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); - cMaterial* pMaterial = renderable->GetMaterial(); - iVertexBuffer* vertexBuffer = renderable->GetVertexBuffer(); - if (!vertexBuffer || !pMaterial || pMaterial->GetType()->IsTranslucent()) { - continue; + switch (light->m_light->GetLightType()) { + case eLightType_Point: + cmdBindPipeline( + cmd, + m_pointLightPipeline + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + .m_handle); + break; + case eLightType_Spot: + cmdBindPipeline( + cmd, + m_spotLightPipeline + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + .m_handle); + break; + case eLightType_Box: + cmdBindPipeline( + cmd, + m_boxLightPipeline + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + .m_handle); + break; + default: + ASSERT(false && "Unsupported light type"); + break; + } + cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + loadActions.mLoadActionStencil = LOAD_ACTION_CLEAR; + std::array targets = { + outputBuffer, + }; + cmdBindRenderTargets(cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + { + std::array rtBarriers = { + RenderTargetBarrier{ + depthBuffer, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_PRESENT }, + }; + cmdResourceBarrier(cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); + } + { + std::array rtBarriers = { + RenderTargetBarrier{ + depthBuffer, RESOURCE_STATE_PRESENT, RESOURCE_STATE_DEPTH_WRITE }, + }; + cmdResourceBarrier(cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); } - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, - frame, - pMaterial, - renderable, - { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - }); - materialConst.objectId = instance; - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdBindRenderTargets( + cmd, + targets.size(), + targets.data(), + depthBuffer, + &loadActions, + nullptr, + nullptr, + -1, + -1); } } - } + cmdEndDebugMarker(cmd); - cmdEndDebugMarker(frame.m_cmd); - - mpCurrentRenderList->Compile( - eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | - eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); - } - - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ - currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ - currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + cmdBeginDebugMarker(cmd, 0, 1, 0, "Point Light Deferred Back"); + for (auto& light : deferredLightRenderBack) { + switch (light->m_light->GetLightType()) { + case eLightType_Point: + cmdBindPipeline( + cmd, + m_pointLightPipeline + [options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW] + .m_handle); + break; + case eLightType_Spot: + cmdBindPipeline(cmd, m_spotLightPipeline[options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW].m_handle); + break; + case eLightType_Box: + cmdBindPipeline(cmd, m_boxLightPipeline[options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW].m_handle); + break; + default: + ASSERT(false && "Unsupported light type"); + break; + } + + std::array targets = { eVertexBufferElement_Position }; + LegacyVertexBuffer::GeometryBinding binding{}; + auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); + ASSERT(lightShape && "Light shape not found"); + static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + + uint32_t instance = cmdBindLightDescriptor(light); + detail::cmdDefaultLegacyGeomBinding(cmd, frame, binding); + cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + } + cmdEndDebugMarker(cmd); + } } + } + void cRendererDeferred::cmdBuildPrimaryGBuffer( + const ForgeRenderer::Frame& frame, + Cmd* cmd, + uint32_t frameDescriptorIndex, + RenderTarget* colorBuffer, + RenderTarget* normalBuffer, + RenderTarget* positionBuffer, + RenderTarget* specularBuffer, + RenderTarget* depthBuffer, + AdditionalGbufferPassOptions options) { + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); { - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Build GBuffer"); + cmdBeginDebugMarker(cmd, 0, 1, 0, "Build GBuffer"); LoadActionsDesc loadActions = {}; loadActions.mLoadActionsColor[0] = LOAD_ACTION_CLEAR; loadActions.mLoadActionsColor[1] = LOAD_ACTION_CLEAR; @@ -3161,19 +3146,15 @@ namespace hpl { loadActions.mLoadActionsColor[3] = LOAD_ACTION_CLEAR; loadActions.mClearColorValues[0] = { .r = 0.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f }; loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - std::array targets = { currentGBuffer.m_colorBuffer.m_handle, - currentGBuffer.m_normalBuffer.m_handle, - currentGBuffer.m_positionBuffer.m_handle, - currentGBuffer.m_specularBuffer.m_handle }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, NULL, NULL, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(frame.m_cmd, m_materialSolidPass.m_solidDiffuseParallaxPipeline.m_handle); - - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - - for (auto& diffuseItem : mpCurrentRenderList->GetRenderableItems(eRenderListType_Diffuse)) { + std::array targets = { colorBuffer, normalBuffer, positionBuffer, specularBuffer }; + cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, NULL, NULL, -1, -1); + cmdSetViewport(cmd, 0.0f, 0.0f, colorBuffer->mWidth, colorBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, colorBuffer->mWidth, colorBuffer->mHeight); + cmdBindPipeline(cmd, options.m_invert ? m_materialSolidPass.m_solidDiffuseParallaxPipelineCW.m_handle: m_materialSolidPass.m_solidDiffuseParallaxPipeline.m_handle); + + cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + for (auto& diffuseItem : m_rendererList.GetRenderableItems(eRenderListType_Diffuse)) { cMaterial* pMaterial = diffuseItem->GetMaterial(); iVertexBuffer* vertexBuffer = diffuseItem->GetVertexBuffer(); if (pMaterial == nullptr || vertexBuffer == nullptr) { @@ -3182,15 +3163,7 @@ namespace hpl { ASSERT(pMaterial->type().m_id == cMaterial::SolidDiffuse && "Invalid material type"); MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, - frame, - pMaterial, - diffuseItem, - { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - }); + uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, diffuseItem); materialConst.objectId = instance; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, @@ -3198,1160 +3171,1550 @@ namespace hpl { eVertexBufferElement_Texture1Tangent }; LegacyVertexBuffer::GeometryBinding binding; static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + detail::cmdDefaultLegacyGeomBinding(cmd, frame, binding); + cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); } - cmdEndDebugMarker(frame.m_cmd); + cmdEndDebugMarker(cmd); } // ------------------------------------------------------------------------------------ // Render Decal Pass render to color and depth // ------------------------------------------------------------------------------------ { - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Build Decal"); + cmdBeginDebugMarker(cmd, 0, 1, 0, "Build Decal"); LoadActionsDesc loadActions = {}; loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; std::array targets = { - currentGBuffer.m_colorBuffer.m_handle, + colorBuffer, }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, NULL, NULL, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, NULL, NULL, -1, -1); + cmdSetViewport(cmd, 0.0f, 0.0f, colorBuffer->mWidth, colorBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, colorBuffer->mWidth, colorBuffer->mHeight); - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - for (auto& decalItem : mpCurrentRenderList->GetRenderableItems(eRenderListType_Decal)) { + cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + for (auto& decalItem : m_rendererList.GetRenderableItems(eRenderListType_Decal)) { cMaterial* pMaterial = decalItem->GetMaterial(); iVertexBuffer* vertexBuffer = decalItem->GetVertexBuffer(); if (pMaterial == nullptr || vertexBuffer == nullptr) { continue; } ASSERT(pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && "Invalid blend mode"); - ; ASSERT(pMaterial->type().m_id == cMaterial::Decal && "Invalid material type"); - cmdBindPipeline(frame.m_cmd, m_decalPipeline[pMaterial->GetBlendMode()].m_handle); + cmdBindPipeline(cmd, options.m_invert ? m_decalPipelineCW[pMaterial->GetBlendMode()].m_handle : m_decalPipeline[pMaterial->GetBlendMode()].m_handle); std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, - frame, - pMaterial, - decalItem, - { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - }); + uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, decalItem); materialConst.objectId = instance; LegacyVertexBuffer::GeometryBinding binding; static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + detail::cmdDefaultLegacyGeomBinding(cmd, frame, binding); + cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); } - cmdEndDebugMarker(frame.m_cmd); + cmdEndDebugMarker(cmd); + } + } + + void cRendererDeferred::cmdPreAndPostZ( + Cmd* cmd, + std::set& prePassRenderables, + const ForgeRenderer::Frame& frame, + cRenderList& renderList, + float frameTime, + RenderTarget* depthBuffer, + RenderTarget* hiZBuffer, + cFrustum* apFrustum, + uint32_t frameDescriptorIndex, + cMatrixf viewMat, + cMatrixf projectionMat, + AdditionalZPassOptions options) { + + ASSERT(depthBuffer && "Depth buffer not created"); + ASSERT(hiZBuffer && "Depth buffer not created"); + + FenceStatus fenceStatus; + getFenceStatus(frame.m_renderer->Rend(), m_prePassFence.m_handle, &fenceStatus); + if (fenceStatus == FENCE_STATUS_INCOMPLETE) { + waitForFences(frame.m_renderer->Rend(), 1, &m_prePassFence.m_handle); } + resetCmdPool(frame.m_renderer->Rend(), m_prePassPool.m_handle); + + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); + + struct RenderableContainer { + iRenderableContainer* m_continer; + eWorldContainerType m_type; + }; + std::array worldContainers = { + RenderableContainer{ mpCurrentWorld->GetRenderableContainer(eWorldContainerType_Dynamic), eWorldContainerType_Dynamic }, + RenderableContainer{ mpCurrentWorld->GetRenderableContainer(eWorldContainerType_Static), eWorldContainerType_Static } + }; + for (auto& container : worldContainers) { + container.m_continer->UpdateBeforeRendering(); + } + std::vector uniformTest; + uint32_t queryIndex = 0; + std::vector occlusionQueryAlpha; + // start pre-z pass + beginCmd(m_prePassCmd.m_handle); { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + std::function walkRenderables; + walkRenderables = [&](iRenderableContainerNode* childNode, eWorldContainerType containerType) { + childNode->UpdateBeforeUse(); + for (auto& childNode : childNode->GetChildNodes()) { + childNode->UpdateBeforeUse(); + eCollision frustumCollision = apFrustum->CollideNode(childNode); + if (frustumCollision == eCollision_Outside) { + continue; + } + if (apFrustum->CheckAABBNearPlaneIntersection(childNode->GetMin(), childNode->GetMax())) { + cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), childNode->GetCenter()); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(true); + } else { + // Frustum origin is outside of node. Do intersection test. + cVector3f vIntersection; + cMath::CheckAABBLineIntersection( + childNode->GetMin(), childNode->GetMax(), apFrustum->GetOrigin(), childNode->GetCenter(), &vIntersection, NULL); + cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), vIntersection); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(false); + } + walkRenderables(childNode, containerType); + } + for (auto& pObject : childNode->GetObjects()) { + if (!rendering::detail::IsObjectIsVisible(pObject, options.objectVisibilityFlags, options.clipPlanes)) { + continue; + } + const bool visibleLastFrame = (prePassRenderables.empty() || prePassRenderables.contains(pObject)); + + auto& test = uniformTest.emplace_back(); + test.m_preZPass = visibleLastFrame; + test.m_renderable = pObject; + + cMaterial* pMaterial = pObject->GetMaterial(); + iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); + + if (pObject && pObject->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { + pObject->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); + pObject->UpdateGraphicsForFrame(frameTime); + } + + if (pMaterial && pMaterial->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { + pMaterial->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); + pMaterial->UpdateBeforeRendering(frameTime); + } + //////////////////////////////////////// + // Update per viewport specific and set amtrix point + // Skip this for non-decal translucent! This is because the water rendering might mess it up otherwise! + if (pMaterial == NULL || pMaterial->GetType()->IsTranslucent() == false || pMaterial->GetType()->IsDecal()) { + // skip rendering if the update return false + if (pObject->UpdateGraphicsForViewport(apFrustum, frameTime) == false) { + return; + } + + pObject->SetModelMatrixPtr(pObject->GetModelMatrix(apFrustum)); + } + // Only set a matrix used for sorting. Calculate the proper in the trans rendering! + else { + pObject->SetModelMatrixPtr(pObject->GetModelMatrix(NULL)); + } + if (visibleLastFrame && pObject->UsesOcclusionQuery() && !options.m_disableOcclusionQueries) { + auto& occlusionAlpha = occlusionQueryAlpha.emplace_back(); + occlusionAlpha.m_renderable = pObject; + } + } }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + for (auto& it : worldContainers) { + iRenderableContainerNode* pNode = it.m_continer->GetRoot(); + pNode->UpdateBeforeUse(); // Make sure node is updated. + pNode->SetInsideView(true); // We never want to check root! Assume player is inside. + walkRenderables(pNode, it.m_type); + } + + std::sort(uniformTest.begin(), uniformTest.end(), [&](UniformTest& apObjectA, UniformTest& apObjectB) { + cMaterial* pMatA = apObjectA.m_renderable->GetMaterial(); + cMaterial* pMatB = apObjectB.m_renderable->GetMaterial(); + if (!(pMatA && pMatB)) { + return false; + } + + ////////////////////////// + // Alpha mode + if (pMatA->GetAlphaMode() != pMatB->GetAlphaMode()) { + return pMatA->GetAlphaMode() < pMatB->GetAlphaMode(); + } + + ////////////////////////// + // If alpha, sort by texture (we know alpha is same for both materials, so can just test one) + if (pMatA->GetAlphaMode() == eMaterialAlphaMode_Trans) { + if (pMatA->GetImage(eMaterialTexture_Diffuse) != pMatB->GetImage(eMaterialTexture_Diffuse)) { + return pMatA->GetImage(eMaterialTexture_Diffuse) < pMatB->GetImage(eMaterialTexture_Diffuse); + } + } + + ////////////////////////// + // View space depth, no need to test further since Z should almost never be the same for two objects. + // use ">" since we want to render things closest to the screen first. + return apObjectA.m_renderable->GetViewSpaceZ() > apObjectB.m_renderable->GetViewSpaceZ(); + // return apObjectA < apObjectB; + }); + + cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 1, 0, "Pre Z"); + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_DONTCARE; + loadActions.mLoadActionDepth = LOAD_ACTION_CLEAR; + loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; + loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; + + cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, depthBuffer, &loadActions, NULL, NULL, -1, -1); + + cmdSetViewport( + m_prePassCmd.m_handle, + 0.0f, + 0.0f, + static_cast(depthBuffer->mWidth), + static_cast(depthBuffer->mHeight), + 0.0f, + 1.0f); + cmdSetScissor( + m_prePassCmd.m_handle, + 0, + 0, + static_cast(depthBuffer->mWidth), + static_cast(depthBuffer->mHeight)); + cmdBindPipeline(m_prePassCmd.m_handle, options.m_invert ? m_zPassPipelineCW.m_handle : m_zPassPipelineCCW.m_handle); + + cmdBindDescriptorSet(m_prePassCmd.m_handle, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + UniformPropBlock uniformPropBlock = {}; + for (size_t i = 0; i < uniformTest.size(); i++) { + auto& test = uniformTest[i]; + cMaterial* pMaterial = test.m_renderable->GetMaterial(); + iVertexBuffer* vertexBuffer = test.m_renderable->GetVertexBuffer(); + + ASSERT(uniformTest.size() < MaxObjectTest && "Too many renderables"); + auto* pBoundingVolume = test.m_renderable->GetBoundingVolume(); + + BufferUpdateDesc updateDesc = { m_hiZBoundBoxBuffer.m_handle, i * (2 * sizeof(float4)), sizeof(float4) * 2 }; + auto boundBoxMin = pBoundingVolume->GetMin(); + auto boundBoxMax = pBoundingVolume->GetMax(); + beginUpdateResource(&updateDesc); + reinterpret_cast(updateDesc.pMappedData)[0] = float4(boundBoxMin.x, boundBoxMin.y, boundBoxMin.z, 0.0f); + reinterpret_cast(updateDesc.pMappedData)[1] = float4(boundBoxMax.x, boundBoxMax.y, boundBoxMax.z, 0.0f); + endUpdateResource(&updateDesc, nullptr); + + if (!test.m_preZPass || !vertexBuffer || !pMaterial || pMaterial->GetType()->IsTranslucent()) { + continue; + } + + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(m_prePassCmd.m_handle, frame, pMaterial, test.m_renderable, {}); + materialConst.objectId = instance; + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + LegacyVertexBuffer::GeometryBinding binding{}; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + detail::cmdDefaultLegacyGeomBinding(m_prePassCmd.m_handle, frame, binding); + cmdBindPushConstants(m_prePassCmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + } + + uniformPropBlock.maxMipLevel = hiZBuffer->mMipLevels - 1; + uniformPropBlock.depthDim = uint2(depthBuffer->mWidth, depthBuffer->mHeight); + uniformPropBlock.numObjects = uniformTest.size(); + + BufferUpdateDesc updateDesc = { m_hiZOcclusionUniformBuffer.m_handle, 0, sizeof(UniformPropBlock) }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = uniformPropBlock; + endUpdateResource(&updateDesc, nullptr); + cmdEndDebugMarker(m_prePassCmd.m_handle); } + { + cmdBeginDebugMarker(m_prePassCmd.m_handle, 1, 1, 0, "Occlusion Query"); + LegacyVertexBuffer::GeometryBinding binding{}; + std::array targets = { eVertexBufferElement_Position }; + static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + + uint32_t occlusionObjectIndex = getDescriptorIndexFromName(m_rootSignatureOcclusuion.m_handle, "rootConstant"); + uint32_t occlusionIndex = 0; + cMatrixf viewProj = cMath::MatrixMul(projectionMat, viewMat); + + cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorOcclusionConstSet.m_handle); + for (auto& query : occlusionQueryAlpha) { + if (TypeInfo::IsType(*query.m_renderable)) { + cBillboard* pBillboard = static_cast(query.m_renderable); + + auto mvp = cMath::ToForgeMat( + cMath::MatrixMul( + viewProj, cMath::MatrixMul(pBillboard->GetWorldMatrix(), cMath::MatrixScale(pBillboard->GetHaloSourceSize()))) + .GetTranspose()); - if (mpCurrentSettings->mbSSAOActive) { - ASSERT(m_hbaoPlusPipeline && "Invalid pipeline"); - ASSERT(currentGBuffer.m_depthBuffer.IsValid() && "Invalid depth buffer"); - ASSERT(currentGBuffer.m_normalBuffer.IsValid() && "Invalid depth buffer"); - ASSERT(currentGBuffer.m_colorBuffer.IsValid() && "Invalid depth buffer"); + BufferUpdateDesc updateDesc = { m_occlusionUniformBuffer.m_handle, m_occlusionIndex * sizeof(mat4) }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = mvp; + endUpdateResource(&updateDesc, NULL); + + cmdBindPushConstants( + m_prePassCmd.m_handle, m_rootSignatureOcclusuion.m_handle, occlusionObjectIndex, &m_occlusionIndex); + + detail::cmdDefaultLegacyGeomBinding(m_prePassCmd.m_handle, frame, binding); + + QueryDesc queryDesc = {}; + queryDesc.mIndex = queryIndex++; + cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineOcclusionQuery.m_handle); + cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); + cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); + query.m_queryIndex = queryDesc.mIndex; + + queryDesc.mIndex = queryIndex++; + cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineMaxOcclusionQuery.m_handle); + cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); + cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); + query.m_maxQueryIndex = queryDesc.mIndex; + + m_occlusionIndex = (m_occlusionIndex + 1) % MaxOcclusionDescSize; + } + } + cmdEndDebugMarker(m_prePassCmd.m_handle); + } + // hi-z generate pass + { + cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 0, 0, "Generate HI-Z"); { + cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ - currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + RenderTargetBarrier{ depthBuffer, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ hiZBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_RENDER_TARGET }, }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_DONTCARE; + loadActions.mClearColorValues[0] = { .r = 1.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f }; + cmdBindRenderTargets(m_prePassCmd.m_handle, 1, &hiZBuffer, NULL, &loadActions, NULL, NULL, -1, -1); + + std::array params = {}; + params[0].pName = "sourceInput"; + params[0].ppTextures = &depthBuffer->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), 0, m_descriptorCopyDepth.m_handle, params.size(), params.data()); + + cmdSetViewport(m_prePassCmd.m_handle, 0.0f, 0.0f, depthBuffer->mWidth, depthBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(m_prePassCmd.m_handle, 0, 0, depthBuffer->mWidth, depthBuffer->mHeight); + cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineCopyDepth.m_handle); + + cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorCopyDepth.m_handle); + cmdDraw(m_prePassCmd.m_handle, 3, 0); } - m_hbaoPlusPipeline->cmdDraw( - frame, - apFrustum, - &viewport, - currentGBuffer.m_depthBuffer.m_handle->pTexture, - currentGBuffer.m_normalBuffer.m_handle->pTexture, - currentGBuffer.m_colorBuffer.m_handle->pTexture); + { + cmdBindRenderTargets(m_prePassCmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, - RenderTargetBarrier{ - currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ depthBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, + RenderTargetBarrier{ hiZBuffer, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_UNORDERED_ACCESS }, }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - } - - // -------------------------------------------------------------------- - // Render Light Pass - // -------------------------------------------------------------------- - { - cVector2l screenSize = viewport.GetSize(); - - float fScreenArea = (float)(screenSize.x * screenSize.y); - int mlMinLargeLightArea = (int)(MinLargeLightNormalizedArea * fScreenArea); + uint32_t rootConstantIndex = getDescriptorIndexFromName(m_rootSignatureHIZOcclusion.m_handle, "uRootConstants"); + uint32_t width = static_cast(depthBuffer->mWidth); + uint32_t height = static_cast(depthBuffer->mHeight); + for (uint32_t lod = 1; lod < hiZBuffer->mMipLevels; ++lod) { + std::array params = {}; + params[0].pName = "depthInput"; + params[0].mBindMipChain = true; + params[0].ppTextures = &hiZBuffer->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), lod, m_descriptorSetHIZGenerate.m_handle, params.size(), params.data()); + + width /= 2; + height /= 2; + struct { + uint2 screenDim; + uint32_t mipLevel; + } pushConstants = {}; + + pushConstants.mipLevel = lod; + pushConstants.screenDim = uint2(depthBuffer->mWidth, depthBuffer->mHeight); + + // bind lod to push constant + cmdBindPushConstants(m_prePassCmd.m_handle, m_rootSignatureHIZOcclusion.m_handle, rootConstantIndex, &pushConstants); + cmdBindDescriptorSet(m_prePassCmd.m_handle, lod, m_descriptorSetHIZGenerate.m_handle); + cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineHIZGenerate.m_handle); + cmdDispatch(m_prePassCmd.m_handle, static_cast(width / 16) + 1, static_cast(height / 16) + 1, 1); - // std::array, eDeferredLightList_LastEnum> sortedLights; - // DON'T touch deferredLights after this point - std::vector deferredLights; - std::vector deferredLightRenderBack; - std::vector deferredLightStencilFront; + std::array rtBarriers = { + RenderTargetBarrier{ hiZBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_UNORDERED_ACCESS }, + }; + cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + { + std::array rtBarriers = { RenderTargetBarrier { hiZBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE } }; + cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + cmdEndDebugMarker(m_prePassCmd.m_handle); - for (auto& light : mpCurrentRenderList->GetLights()) { - auto lightType = light->GetLightType(); - auto& deferredLightData = deferredLights.emplace_back(detail::DeferredLight()); - deferredLightData.m_light = light; - if (lightType == eLightType_Box) { - continue; + cmdBeginDebugMarker(m_prePassCmd.m_handle, 0, 1, 0, "AABB Hi-Z"); + { + std::array params = {}; + params[0].pName = "perFrameConstants"; + params[0].ppBuffers = &m_perFrameBuffer[frameDescriptorIndex].m_handle; + params[1].pName = "objectUniformBlock"; + params[1].ppBuffers = &m_hiZOcclusionUniformBuffer.m_handle; + params[2].pName = "occlusionTest"; + params[2].ppBuffers = &m_occlusionTestBuffer.m_handle; + params[3].pName = "occlusionBoxBuffer"; + params[3].ppBuffers = &m_hiZBoundBoxBuffer.m_handle; + params[4].pName = "depthTest"; + params[4].ppTextures = &hiZBuffer->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), 0, m_descriptorAABBOcclusionTest.m_handle, params.size(), params.data()); + + cmdBindDescriptorSet(m_prePassCmd.m_handle, 0, m_descriptorAABBOcclusionTest.m_handle); + cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineAABBOcclusionTest.m_handle); + cmdDispatch(m_prePassCmd.m_handle, static_cast(uniformTest.size() / 128) + 1, 1, 1); + { + std::array rtBarriers = { RenderTargetBarrier { hiZBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS } }; + cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - switch (lightType) { - case eLightType_Point: - { - deferredLightData.m_insideNearPlane = apFrustum->CheckSphereNearPlaneIntersection( - light->GetWorldPosition(), light->GetRadius() * kLightRadiusMul_Low); - detail::SetupLightMatrix( - deferredLightData.m_mtxViewSpaceRender, - deferredLightData.m_mtxViewSpaceTransform, - light, - apFrustum, - kLightRadiusMul_Medium); - deferredLightData.m_clipRect = cMath::GetClipRectFromSphere( - deferredLightData.m_mtxViewSpaceRender.GetTranslation(), light->GetRadius(), apFrustum, screenSize, true, 0); - break; + } + cmdEndDebugMarker(m_prePassCmd.m_handle); + cmdResolveQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, m_occlusionReadBackBuffer.m_handle, 0, queryIndex); + endCmd(m_prePassCmd.m_handle); + + + // Submit the gpu work. + QueueSubmitDesc submitDesc = {}; + submitDesc.mCmdCount = 1; + submitDesc.ppCmds = &m_prePassCmd.m_handle; + submitDesc.pSignalFence = m_prePassFence.m_handle; + submitDesc.mSubmitDone = true; + queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); + + FenceStatus fenceStatus; + getFenceStatus(frame.m_renderer->Rend(), m_prePassFence.m_handle, &fenceStatus); + if (fenceStatus == FENCE_STATUS_INCOMPLETE) { + waitForFences(frame.m_renderer->Rend(), 1, &m_prePassFence.m_handle); + } + + uint64_t* occlusionCount = reinterpret_cast(m_occlusionReadBackBuffer.m_handle->pCpuMappedAddress); + for (auto& query : occlusionQueryAlpha) { + if (TypeInfo::IsType(*query.m_renderable)) { + cBillboard* pBillboard = static_cast(query.m_renderable); + float maxSamples = static_cast(occlusionCount[query.m_maxQueryIndex]); + float samples = static_cast(occlusionCount[query.m_queryIndex]); + float billboardCoverage = pBillboard->getAreaOfScreenSpace(apFrustum); + if (maxSamples > 0.0f) { + pBillboard->SetHaloAlpha(billboardCoverage * (samples / maxSamples)); + } else { + pBillboard->SetHaloAlpha(0.0f); } - case eLightType_Spot: - { - cLightSpot* lightSpot = static_cast(light); - deferredLightData.m_insideNearPlane = apFrustum->CheckFrustumNearPlaneIntersection(lightSpot->GetFrustum()); - detail::SetupLightMatrix( - deferredLightData.m_mtxViewSpaceRender, - deferredLightData.m_mtxViewSpaceTransform, - light, - apFrustum, - kLightRadiusMul_Medium); - cMath::GetClipRectFromBV(deferredLightData.m_clipRect, *light->GetBoundingVolume(), apFrustum, screenSize, 0); - break; + } + } + } + + prePassRenderables.clear(); + + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_DONTCARE; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; + loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; + + cmdBeginDebugMarker(cmd, 0, 1, 0, "Post Z"); + cmdBindRenderTargets(cmd, 0, NULL, depthBuffer, &loadActions, NULL, NULL, -1, -1); + cmdSetViewport(cmd, 0.0f, 0.0f, depthBuffer->mWidth, depthBuffer->mHeight, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, depthBuffer->mWidth, depthBuffer->mHeight); + + cmdBindPipeline(cmd, options.m_invert ? m_zPassPipelineCW.m_handle : m_zPassPipelineCCW.m_handle); + cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + auto* testResult = reinterpret_cast(m_occlusionTestBuffer.m_handle->pCpuMappedAddress); + for (size_t i = 0; i < uniformTest.size(); ++i) { + if (testResult[i] == 1) { + renderList.AddObject(uniformTest[i].m_renderable); + prePassRenderables.insert(uniformTest[i].m_renderable); + if (!uniformTest[i].m_preZPass) { + auto* renderable = uniformTest[i].m_renderable; + eMaterialRenderMode renderMode = + renderable->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; + + cMaterial* pMaterial = renderable->GetMaterial(); + iVertexBuffer* vertexBuffer = renderable->GetVertexBuffer(); + if (!vertexBuffer || !pMaterial || pMaterial->GetType()->IsTranslucent()) { + continue; } - default: - break; + + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, renderable); + materialConst.objectId = instance; + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + LegacyVertexBuffer::GeometryBinding binding{}; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + detail::cmdDefaultLegacyGeomBinding(cmd, frame, binding); + cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); } } + } - for (auto& deferredLight : deferredLights) { - auto light = deferredLight.m_light; - auto lightType = deferredLight.m_light->GetLightType(); + cmdEndDebugMarker(cmd); + } - if (lightType == eLightType_Spot && light->GetCastShadows() && mpCurrentSettings->mbRenderShadows) { - cLightSpot* pLightSpot = static_cast(light); + uint32_t cRendererDeferred::cmdBindMaterialAndObject( + Cmd* cmd, const ForgeRenderer::Frame& frame, cMaterial* apMaterial, iRenderable* apObject, std::optional modelMatrix) { + uint32_t id = folly::hash::fnv32_buf( + reinterpret_cast(apObject), + sizeof(apObject), + modelMatrix.has_value() ? folly::hash::fnv32_buf(modelMatrix->v, sizeof(modelMatrix->v)) : folly::hash::fnv32_hash_start); - bool castShadow = false; - eShadowMapResolution shadowMapResolution = eShadowMapResolution_Low; - //////////////////////// - // Inside near plane, use max resolution - if (deferredLight.m_insideNearPlane) { - castShadow = true; + auto* objectDescSet = m_materialSet.m_perObjectSet[frame.m_frameIndex].m_handle; + auto objectLookup = m_materialSet.m_objectDescriptorLookup.find(apObject); + auto& info = m_materialSet.m_materialInfo[apMaterial->materialID()]; + auto& descInfo = info.m_materialDescInfo[frame.m_frameIndex]; + auto& materialType = apMaterial->type(); - shadowMapResolution = rendering::detail::GetShadowMapResolution( - light->GetShadowMapResolution(), mpCurrentSettings->mMaxShadowMapResolution); - } else { - cVector3f vIntersection = pLightSpot->GetFrustum()->GetOrigin(); - pLightSpot->GetFrustum()->CheckLineIntersection( - apFrustum->GetOrigin(), light->GetBoundingVolume()->GetWorldCenter(), vIntersection); + auto metaInfo = std::find_if(cMaterial::MaterialMetaTable.begin(), cMaterial::MaterialMetaTable.end(), [&](auto& info) { + return info.m_id == materialType.m_id; + }); - float fDistToLight = cMath::Vector3Dist(apFrustum->GetOrigin(), vIntersection); + if (descInfo.m_material != apMaterial || descInfo.m_version != apMaterial->Version()) { + descInfo.m_version = apMaterial->Version(); + descInfo.m_material = apMaterial; - castShadow = true; - shadowMapResolution = rendering::detail::GetShadowMapResolution( - light->GetShadowMapResolution(), mpCurrentSettings->mMaxShadowMapResolution); + BufferUpdateDesc updateDesc = { m_materialSet.m_materialUniformBuffer.m_handle, + apMaterial->materialID() * sizeof(cMaterial::MaterialType::MaterialData) }; + beginUpdateResource(&updateDesc); + memcpy(updateDesc.pMappedData, &materialType.m_data, sizeof(cMaterial::MaterialType::MaterialData)); + endUpdateResource(&updateDesc, NULL); - /////////////////////// - // Skip shadow - if (fDistToLight > m_shadowDistanceNone) { - castShadow = false; - } - /////////////////////// - // Use Low - else if (fDistToLight > m_shadowDistanceLow) { - if (shadowMapResolution == eShadowMapResolution_Low) { - castShadow = false; - } - shadowMapResolution = eShadowMapResolution_Low; - } - /////////////////////// - // Use Medium - else if (fDistToLight > m_shadowDistanceMedium) { - if (shadowMapResolution == eShadowMapResolution_High) { - shadowMapResolution = eShadowMapResolution_Medium; - } else { - shadowMapResolution = eShadowMapResolution_Low; - } - } - } - - cFrustum* pLightFrustum = pLightSpot->GetFrustum(); - std::vector shadowCasters; - if (castShadow && - detail::SetupShadowMapRendering(shadowCasters, apWorld, pLightFrustum, pLightSpot, mvCurrentOcclusionPlanes)) { - auto findBestShadowMap = [&](eShadowMapResolution resolution, iLight* light) -> cRendererDeferred::ShadowMapData* { - auto& shadowMapVec = m_shadowMapData[resolution]; - uint32_t maxFrameDistance = 0; - size_t bestIndex = 0; - for (size_t i = 0; i < shadowMapVec.size(); ++i) { - auto& shadowMap = shadowMapVec[i]; - if (shadowMap.m_light == light) { - shadowMap.m_frameCount = frame.m_currentFrame; - return &shadowMap; - } - - const uint32_t frameDist = frame.m_currentFrame - shadowMap.m_frameCount; - if (frameDist > maxFrameDistance) { - maxFrameDistance = frameDist; - bestIndex = i; - } - } - shadowMapVec[bestIndex].m_frameCount = frame.m_currentFrame; - return &shadowMapVec[bestIndex]; - }; - auto* shadowMapData = findBestShadowMap(shadowMapResolution, pLightSpot); - if (shadowMapData) { - deferredLight.m_shadowMapData = shadowMapData; - // testing if the shadow map needs to be updated - if (shadowMapData->m_transformCount != pLightSpot->GetTransformUpdateCount() || [&]() -> bool { - // Check if texture map and light are valid - if (pLightSpot->GetOcclusionCullShadowCasters()) { - return true; - } - - if (pLightSpot->GetLightType() == eLightType_Spot && - (pLightSpot->GetAspect() != shadowMapData->m_aspect || - pLightSpot->GetFOV() != shadowMapData->m_fov)) { - return true; - } - return !pLightSpot->ShadowCastersAreUnchanged(shadowCasters); - }()) { - shadowMapData->m_light = pLightSpot; - shadowMapData->m_transformCount = pLightSpot->GetTransformUpdateCount(); - shadowMapData->m_radius = pLightSpot->GetRadius(); - shadowMapData->m_aspect = pLightSpot->GetAspect(); - shadowMapData->m_fov = pLightSpot->GetFOV(); - - pLightSpot->SetShadowCasterCacheFromVec(shadowCasters); - - FenceStatus fenceStatus; - getFenceStatus(frame.m_renderer->Rend(), shadowMapData->m_shadowFence, &fenceStatus); - if (fenceStatus == FENCE_STATUS_INCOMPLETE) - waitForFences(frame.m_renderer->Rend(), 1, &shadowMapData->m_shadowFence); - resetCmdPool(frame.m_renderer->Rend(), shadowMapData->m_pool); + std::array params{}; + size_t paramCount = 0; - beginCmd(shadowMapData->m_cmd); - { - cmdBindRenderTargets(shadowMapData->m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ - shadowMapData->m_target.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, - }; - cmdResourceBarrier(shadowMapData->m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } + for (auto& supportedTexture : metaInfo->m_usedTextures) { + static constexpr const char* TextureNameLookup[] = { + "diffuseMap", // eMaterialTexture_Diffuse + "normalMap", // eMaterialTexture_NMap + "specularMap", // eMaterialTexture_Specular + "alphaMap", // eMaterialTexture_Alpha + "heightMap", // eMaterialTexture_Height + "illuminationMap", // eMaterialTexture_Illumination + "cubeMap", // eMaterialTexture_CubeMap + "dissolveAlphaMap", // eMaterialTexture_DissolveAlpha + "cubeMapAlpha", // eMaterialTexture_CubeMapAlpha + }; - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionDepth = LOAD_ACTION_CLEAR; - loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; - loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; - cmdBindRenderTargets( - shadowMapData->m_cmd, 0, NULL, shadowMapData->m_target.m_handle, &loadActions, NULL, NULL, -1, -1); - cmdSetViewport( - shadowMapData->m_cmd, - 0.0f, - static_cast(shadowMapData->m_target.m_handle->mHeight), - static_cast(shadowMapData->m_target.m_handle->mWidth), - -static_cast(shadowMapData->m_target.m_handle->mHeight), - 0.0f, - 1.0f); - cmdSetScissor( - shadowMapData->m_cmd, - 0, - 0, - shadowMapData->m_target.m_handle->mWidth, - shadowMapData->m_target.m_handle->mHeight); - cmdBindPipeline(shadowMapData->m_cmd, m_zPassShadowPipelineCW.m_handle); - - uint32_t shadowFrameIndex = updateFrameDescriptor(frame, shadowMapData->m_cmd, apWorld, { - .m_size = float2(common->m_size.x, common->m_size.y), - .m_viewMat = pLightFrustum->GetViewMatrix(), - .m_projectionMat = pLightFrustum->GetProjectionMatrix() - }); - cmdBindDescriptorSet(shadowMapData->m_cmd, shadowFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - for (auto& pObject : shadowCasters) { - eMaterialRenderMode renderMode = - pObject->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; - cMaterial* pMaterial = pObject->GetMaterial(); - iMaterialType* materialType = pMaterial->GetType(); - iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); - if (vertexBuffer == nullptr || materialType == nullptr) { - return; - } - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - shadowMapData->m_cmd, - frame, - pMaterial, - pObject, - { - .m_viewMat = pLightFrustum->GetViewMatrix(), - .m_projectionMat = pLightFrustum->GetProjectionMatrix(), - }); - materialConst.objectId = instance; - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer) - ->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(shadowMapData->m_cmd, frame, binding); - cmdBindPushConstants( - shadowMapData->m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(shadowMapData->m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - } - { - cmdBindRenderTargets(shadowMapData->m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ - shadowMapData->m_target.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, - }; - cmdResourceBarrier(shadowMapData->m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - endCmd(shadowMapData->m_cmd); - QueueSubmitDesc submitDesc = {}; - submitDesc.mCmdCount = 1; - submitDesc.ppCmds = &shadowMapData->m_cmd; - submitDesc.pSignalFence = shadowMapData->m_shadowFence; - submitDesc.mSubmitDone = true; - queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); - } - } - } - // render shadow map + auto* image = apMaterial->GetImage(supportedTexture); + if (image) { + params[paramCount].pName = TextureNameLookup[supportedTexture]; + params[paramCount++].ppTextures = &image->GetTexture().m_handle; + descInfo.m_textureHandles[supportedTexture] = image->GetTexture(); } } + updateDescriptorSet( + frame.m_renderer->Rend(), + apMaterial->materialID(), + m_materialSet.m_perBatchSet[frame.m_frameIndex].m_handle, + paramCount, + params.data()); + } - mpCurrentSettings->mlNumberOfLightsRendered = 0; - for (auto& deferredLight : deferredLights) { - // cDeferredLight* pLightData = mvTempDeferredLights[i]; - iLight* pLight = deferredLight.m_light; - eLightType lightType = pLight->GetLightType(); - - //////////////////////// - // If box, we have special case... - if (lightType == eLightType_Box) { - cLightBox* pLightBox = static_cast(pLight); - - // Set up matrix - deferredLight.m_mtxViewSpaceRender = cMath::MatrixScale(pLightBox->GetSize()); - deferredLight.m_mtxViewSpaceRender.SetTranslation(pLightBox->GetWorldPosition()); - deferredLight.m_mtxViewSpaceRender = cMath::MatrixMul(apFrustum->GetViewMatrix(), deferredLight.m_mtxViewSpaceRender); - - mpCurrentSettings->mlNumberOfLightsRendered++; - - // Check if near plane is inside box. If so only render back - if (apFrustum->CheckBVNearPlaneIntersection(pLight->GetBoundingVolume())) { - deferredLightRenderBack.push_back(&deferredLight); - } else { - deferredLightStencilFront.push_back(&deferredLight); - } - - continue; - } - - mpCurrentSettings->mlNumberOfLightsRendered++; + const bool isFound = objectLookup != m_materialSet.m_objectDescriptorLookup.end(); + uint32_t index = isFound ? objectLookup->second : m_materialSet.m_objectIndex++; + if (!isFound) { + cMatrixf modelMat = modelMatrix.value_or(apObject->GetModelMatrixPtr() ? *apObject->GetModelMatrixPtr() : cMatrixf::Identity); - deferredLightRenderBack.emplace_back(&deferredLight); + cRendererDeferred::UniformObject uniformObjectData = {}; + uniformObjectData.m_dissolveAmount = apObject->GetCoverageAmount(); + uniformObjectData.m_materialIndex = apMaterial->materialID(); + uniformObjectData.m_modelMat = cMath::ToForgeMat4(modelMat.GetTranspose()); + uniformObjectData.m_invModelMat = cMath::ToForgeMat4(cMath::MatrixInverse(modelMat).GetTranspose()); + if (apMaterial) { + uniformObjectData.m_uvMat = cMath::ToForgeMat4(apMaterial->GetUvMatrix()); } - std::sort(deferredLightStencilFront.begin(), deferredLightStencilFront.end(), detail::SortDeferredLightDefault); - std::sort(deferredLightRenderBack.begin(), deferredLightRenderBack.end(), detail::SortDeferredLightDefault); - - { - uint32_t lightIndex = 0; - // updates and binds the light data - auto cmdBindLightDescriptor = [&](detail::DeferredLight* light) { - DescriptorData params[10] = {}; - size_t paramCount = 0; - UniformLightData uniformObjectData = {}; - - const auto modelViewMtx = cMath::MatrixMul(apFrustum->GetViewMatrix(), light->m_light->GetWorldMatrix()); - const auto viewProjectionMat = cMath::MatrixMul(mainFrustumProj, mainFrustumView); - - switch (light->m_light->GetLightType()) { - case eLightType_Point: - { - uniformObjectData.m_common.m_mvp = cMath::ToForgeMat4( - cMath::MatrixMul( - viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light))) - .GetTranspose()); - - cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); - const auto color = light->m_light->GetDiffuseColor(); - - if (light->m_light->GetGoboTexture()) { - uniformObjectData.m_common.m_config |= LightConfiguration::HasGoboMap; - params[paramCount].pName = "goboCubeMap"; - params[paramCount++].ppTextures = &light->m_light->GetGoboTexture()->GetTexture().m_handle; - m_lightResources[frame.m_frameIndex][lightIndex].m_goboCubeMap = - light->m_light->GetGoboTexture()->GetTexture(); - } - - auto falloffMap = light->m_light->GetFalloffMap(); - ASSERT(falloffMap && "Point light needs a falloff map"); - params[paramCount].pName = "attenuationLightMap"; - params[paramCount++].ppTextures = &falloffMap->GetTexture().m_handle; - m_lightResources[frame.m_frameIndex][lightIndex].m_attenuationLightMap = falloffMap->GetTexture(); - - uniformObjectData.m_pointLight.m_radius = light->m_light->GetRadius(); - uniformObjectData.m_pointLight.m_lightPos = float3(lightViewPos.x, lightViewPos.y, lightViewPos.z); - uniformObjectData.m_pointLight.m_lightColor = float4(color.r, color.g, color.b, color.a); - cMatrixf mtxInvViewRotation = - cMath::MatrixMul(light->m_light->GetWorldMatrix(), mainFrustumViewInv).GetTranspose(); - uniformObjectData.m_pointLight.m_invViewRotation = cMath::ToForgeMat4(mtxInvViewRotation); - break; - } - case eLightType_Spot: - { - cLightSpot* pLightSpot = static_cast(light->m_light); - - cMatrixf spotViewProj = cMath::MatrixMul(pLightSpot->GetViewProjMatrix(), mainFrustumViewInv).GetTranspose(); - cVector3f forward = cMath::MatrixMul3x3(light->m_mtxViewSpaceTransform, cVector3f(0, 0, 1)); - cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); - const auto color = pLightSpot->GetDiffuseColor(); - - uniformObjectData.m_common.m_mvp = cMath::ToForgeMat4( - cMath::MatrixMul( - viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light))) - .GetTranspose()); - - if (light->m_shadowMapData) { - uniformObjectData.m_common.m_config |= LightConfiguration::HasShadowMap; - params[paramCount].pName = "shadowMap"; - params[paramCount++].ppTextures = &light->m_shadowMapData->m_target.m_handle->pTexture; - } - if (m_shadowJitterTexture.IsValid()) { - params[paramCount].pName = "shadowOffsetMap"; - params[paramCount++].ppTextures = &m_shadowJitterTexture.m_handle; - } - uniformObjectData.m_spotLight.m_spotViewProj = cMath::ToForgeMat4(spotViewProj); - uniformObjectData.m_spotLight.m_oneMinusCosHalfSpotFOV = 1 - pLightSpot->GetCosHalfFOV(); - uniformObjectData.m_spotLight.m_radius = light->m_light->GetRadius(); - uniformObjectData.m_spotLight.m_forward = float3(forward.x, forward.y, forward.z); - uniformObjectData.m_spotLight.m_color = float4(color.r, color.g, color.b, color.a); - uniformObjectData.m_spotLight.m_pos = float3(lightViewPos.x, lightViewPos.y, lightViewPos.z); - - auto goboImage = light->m_light->GetGoboTexture(); - auto spotFallOffImage = pLightSpot->GetSpotFalloffMap(); - auto spotAttenuationImage = pLightSpot->GetFalloffMap(); - if (goboImage) { - uniformObjectData.m_common.m_config |= LightConfiguration::HasGoboMap; - params[paramCount].pName = "goboMap"; - params[paramCount++].ppTextures = &light->m_light->GetGoboTexture()->GetTexture().m_handle; - frame.m_resourcePool->Push(light->m_light->GetGoboTexture()->GetTexture()); - m_lightResources[frame.m_frameIndex][lightIndex].m_goboMap = light->m_light->GetGoboTexture()->GetTexture(); - } else { - params[paramCount].pName = "falloffMap"; - params[paramCount++].ppTextures = &spotFallOffImage->GetTexture().m_handle; - frame.m_resourcePool->Push(spotFallOffImage->GetTexture()); - m_lightResources[frame.m_frameIndex][lightIndex].m_falloffMap = spotFallOffImage->GetTexture(); - } - m_lightResources[frame.m_frameIndex][lightIndex].m_attenuationLightMap = spotAttenuationImage->GetTexture(); - params[paramCount].pName = "attenuationLightMap"; - params[paramCount++].ppTextures = &spotAttenuationImage->GetTexture().m_handle; - frame.m_resourcePool->Push(spotAttenuationImage->GetTexture()); - break; - } - case eLightType_Box: - { - uniformObjectData.m_common.m_mvp = - cMath::ToForgeMat4(cMath::MatrixMul(viewProjectionMat, detail::GetLightMtx(*light)).GetTranspose()); - - cLightBox* pLightBox = static_cast(light->m_light); - const auto& color = light->m_light->GetDiffuseColor(); - uniformObjectData.m_boxLight.m_lightColor = float4(color.r, color.g, color.b, color.a); - break; - } - default: - { - ASSERT(false && "Unsupported light type"); - break; - } - } - - BufferUpdateDesc updateDesc = { m_lightPassBuffer[frame.m_frameIndex].m_handle, lightIndex * sizeof(UniformLightData) }; - beginUpdateResource(&updateDesc); - memcpy(updateDesc.pMappedData, &uniformObjectData, sizeof(UniformLightData)); - endUpdateResource(&updateDesc, NULL); - - updateDescriptorSet(frame.m_renderer->Rend(), lightIndex, m_lightPerLightSet[frame.m_frameIndex].m_handle, paramCount, params); - cmdBindDescriptorSet(frame.m_cmd, lightIndex, m_lightPerLightSet[frame.m_frameIndex].m_handle); - uint32_t index = lightIndex; - lightIndex++; - return index; - }; - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_CLEAR; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - loadActions.mLoadActionStencil = LOAD_ACTION_CLEAR; - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, - }; - cmdBindRenderTargets( - frame.m_cmd, - targets.size(), - targets.data(), - currentGBuffer.m_depthBuffer.m_handle, - &loadActions, - nullptr, - nullptr, - -1, - -1); - } - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - { - DescriptorData params[15] = {}; - size_t paramCount = 0; - - DescriptorDataRange range = { (uint32_t)(frame.m_frameIndex * sizeof(UniformLightPerFrameSet)), - sizeof(UniformLightPerFrameSet) }; - params[paramCount].pName = "diffuseMap"; - params[paramCount++].ppTextures = ¤tGBuffer.m_colorBuffer.m_handle->pTexture; - params[paramCount].pName = "normalMap"; - params[paramCount++].ppTextures = ¤tGBuffer.m_normalBuffer.m_handle->pTexture; - params[paramCount].pName = "positionMap"; - params[paramCount++].ppTextures = ¤tGBuffer.m_positionBuffer.m_handle->pTexture; - params[paramCount].pName = "specularMap"; - params[paramCount++].ppTextures = ¤tGBuffer.m_specularBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), 0, m_lightPerFrameSet[frame.m_frameIndex].m_handle, paramCount, params); - } - - cmdBindDescriptorSet(frame.m_cmd, 0, m_lightPerFrameSet[frame.m_frameIndex].m_handle); - - // -------------------------------------------------------- - // Draw Point Lights - // Draw Spot Lights - // Draw Box Lights - // -------------------------------------------------------- - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Point Light Deferred Stencil front"); - uint32_t lightRootConstantIndex = getDescriptorIndexFromName(m_lightPassRootSignature.m_handle, "lightPushConstant"); - for (auto& light : deferredLightStencilFront) { - cmdSetStencilReferenceValue(frame.m_cmd, 0xff); - - std::array elements = { eVertexBufferElement_Position }; - LegacyVertexBuffer::GeometryBinding binding{}; - auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); - ASSERT(lightShape && "Light shape not found"); - static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements, &binding); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - - cmdBindPipeline(frame.m_cmd, m_lightStencilPipeline.m_handle); - uint32_t instance = cmdBindLightDescriptor(light); // bind light descriptor light uniforms - cmdBindPushConstants(frame.m_cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - - switch (light->m_light->GetLightType()) { - case eLightType_Point: - cmdBindPipeline( - frame.m_cmd, - m_pointLightPipeline - [LightPipelineVariants::LightPipelineVariant_CW | LightPipelineVariants::LightPipelineVariant_StencilTest].m_handle); - break; - case eLightType_Spot: - cmdBindPipeline( - frame.m_cmd, - m_spotLightPipeline - [LightPipelineVariants::LightPipelineVariant_CW | LightPipelineVariants::LightPipelineVariant_StencilTest].m_handle); - break; - case eLightType_Box: - cmdBindPipeline( - frame.m_cmd, - m_boxLightPipeline - [LightPipelineVariants::LightPipelineVariant_CW | LightPipelineVariants::LightPipelineVariant_StencilTest].m_handle); - break; - default: - ASSERT(false && "Unsupported light type"); - break; - } - cmdBindPushConstants(frame.m_cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - loadActions.mLoadActionStencil = LOAD_ACTION_CLEAR; - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, - }; - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - { - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_PRESENT }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); - } - { - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_PRESENT, RESOURCE_STATE_DEPTH_WRITE }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); - } - - cmdBindRenderTargets( - frame.m_cmd, - targets.size(), - targets.data(), - currentGBuffer.m_depthBuffer.m_handle, - &loadActions, - nullptr, - nullptr, - -1, - -1); - } - } - cmdEndDebugMarker(frame.m_cmd); + BufferUpdateDesc updateDesc = { m_objectUniformBuffer[frame.m_frameIndex].m_handle, + sizeof(cRendererDeferred::UniformObject) * index }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = uniformObjectData; + endUpdateResource(&updateDesc, NULL); - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Point Light Deferred Back"); - for (auto& light : deferredLightRenderBack) { - switch (light->m_light->GetLightType()) { - case eLightType_Point: - cmdBindPipeline(frame.m_cmd, m_pointLightPipeline[LightPipelineVariants::LightPipelineVariant_CW].m_handle); - break; - case eLightType_Spot: - cmdBindPipeline(frame.m_cmd, m_spotLightPipeline[LightPipelineVariants::LightPipelineVariant_CW].m_handle); - break; - case eLightType_Box: - cmdBindPipeline(frame.m_cmd, m_boxLightPipeline[LightPipelineVariants::LightPipelineVariant_CW].m_handle); - break; - default: - ASSERT(false && "Unsupported light type"); - break; - } + m_materialSet.m_objectDescriptorLookup[apObject] = index; + } + cmdBindDescriptorSet( + cmd, + detail::resolveMaterialID(apMaterial->GetTextureAntistropy(), apMaterial->GetTextureWrap(), apMaterial->GetTextureFilter()), + m_materialSet.m_materialConstSet.m_handle); + cmdBindDescriptorSet(cmd, apMaterial->materialID(), m_materialSet.m_perBatchSet[frame.m_frameIndex].m_handle); + return index; + } - std::array targets = { eVertexBufferElement_Position }; - LegacyVertexBuffer::GeometryBinding binding{}; - auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); - ASSERT(lightShape && "Light shape not found"); - static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); +void cRendererDeferred::RebuildGBuffer(ForgeRenderer& renderer, GBuffer& buffer, uint32_t width, uint32_t height) { + ClearValue optimizedColorClearBlack = { { 0.0f, 0.0f, 0.0f, 0.0f } }; + auto deferredRenderTargetDesc = [&]() { + RenderTargetDesc renderTarget = {}; + renderTarget.mArraySize = 1; + renderTarget.mClearValue = optimizedColorClearBlack; + renderTarget.mDepth = 1; + renderTarget.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + renderTarget.mWidth = width; + renderTarget.mHeight = height; + renderTarget.mSampleCount = SAMPLE_COUNT_1; + renderTarget.mSampleQuality = 0; + renderTarget.mStartState = RESOURCE_STATE_SHADER_RESOURCE; + return renderTarget; + }; + buffer.m_hizDepthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + RenderTargetDesc renderTargetDesc = {}; + renderTargetDesc.mArraySize = 1; + renderTargetDesc.mDepth = 1; + renderTargetDesc.mMipLevels = std::min(std::floor(std::log2(std::max(width, height))), MaxHiZMipLevels); + renderTargetDesc.mFormat = TinyImageFormat_R32_SFLOAT; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + renderTargetDesc.mWidth = width; + renderTargetDesc.mHeight = height; + renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; + renderTargetDesc.mSampleQuality = 0; + renderTargetDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; + renderTargetDesc.pName = "hi-z depth buffer"; + addRenderTarget(renderer.Rend(), &renderTargetDesc, handle); + return true; + }); + + buffer.m_depthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = DepthBufferFormat; + targetDesc.mStartState = RESOURCE_STATE_DEPTH_WRITE; + targetDesc.pName = "Depth RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_normalBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = NormalBufferFormat; + targetDesc.pName = "Normal RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_positionBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = PositionBufferFormat; + targetDesc.pName = "Position RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_specularBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = SpecularBufferFormat; + targetDesc.pName = "Specular RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_colorBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = ColorBufferFormat; + targetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + targetDesc.pName = "Color RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_refractionImage.Load([&](Texture** texture) { + TextureLoadDesc loadDesc = {}; + loadDesc.ppTexture = texture; + TextureDesc refractionImageDesc = {}; + refractionImageDesc.mArraySize = 1; + refractionImageDesc.mDepth = 1; + refractionImageDesc.mMipLevels = 1; + refractionImageDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; + refractionImageDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + refractionImageDesc.mWidth = width; + refractionImageDesc.mHeight = height; + refractionImageDesc.mSampleCount = SAMPLE_COUNT_1; + refractionImageDesc.mSampleQuality = 0; + refractionImageDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE; + refractionImageDesc.pName = "Refraction Image"; + loadDesc.pDesc = &refractionImageDesc; + addResource(&loadDesc, nullptr); + return true; + }); + buffer.m_outputBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = ColorBufferFormat; + targetDesc.mDescriptors = DESCRIPTOR_TYPE_RW_TEXTURE | DESCRIPTOR_TYPE_TEXTURE; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); +} + +void cRendererDeferred::Draw( + const ForgeRenderer::Frame& frame, + cViewport& viewport, + float afFrameTime, + cFrustum* apFrustum, + cWorld* apWorld, + cRenderSettings* apSettings, + bool abSendFrameBufferToPostEffects) { + iRenderer::Draw(frame, viewport, afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); + // keep around for the moment ... + BeginRendering(afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); + + if (frame.m_currentFrame != m_activeFrame) { + m_materialSet.m_objectIndex = 0; + m_materialSet.m_objectDescriptorLookup.clear(); + m_lightIndex = 0; + m_lightDescriptorLookup.clear(); + m_activeFrame = frame.m_currentFrame; + } - uint32_t instance = cmdBindLightDescriptor(light); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - cmdBindPushConstants(frame.m_cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - } - cmdEndDebugMarker(frame.m_cmd); + const cMatrixf mainFrustumViewInv = cMath::MatrixInverse(apFrustum->GetViewMatrix()); + const cMatrixf mainFrustumView = apFrustum->GetViewMatrix(); + const cMatrixf mainFrustumProj = apFrustum->GetProjectionMatrix(); + + // auto& swapChainImage = frame.m_swapChain->ppRenderTargets[frame.m_swapChainIndex]; + auto common = m_boundViewportData.resolve(viewport); + if (!common || common->m_size != viewport.GetSize()) { + auto* forgeRenderer = Interface::Get(); + auto viewportData = std::make_unique(); + viewportData->m_size = viewport.GetSize(); + for (auto& b : viewportData->m_gBuffer) { + RebuildGBuffer(*forgeRenderer, b, viewportData->m_size.x, viewportData->m_size.y); + } + if(common) { // reusing state from gbuffer + viewportData->m_reflectionBuffer = std::move(common->m_reflectionBuffer); + } + for(auto& reflection: viewportData->m_reflectionBuffer) { + RebuildGBuffer(*forgeRenderer, reflection.m_buffer, viewportData->m_size.x, viewportData->m_size.y); + reflection.m_target = nullptr;// we are clearing targets they are irrelevant when the gbuffer is discarded + if(!reflection.m_pool.IsValid() || + !reflection.m_cmd.IsValid() || + !reflection.m_fence.IsValid()) { + reflection.m_pool.Load(forgeRenderer->Rend(), [&](CmdPool** pool) { + CmdPoolDesc cmdPoolDesc = {}; + cmdPoolDesc.pQueue = forgeRenderer->GetGraphicsQueue(); + addCmdPool(forgeRenderer->Rend(), &cmdPoolDesc, pool); + return true; + }); + reflection.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { + CmdDesc cmdDesc = {}; + cmdDesc.pPool = reflection.m_pool.m_handle; + addCmd(forgeRenderer->Rend(), &cmdDesc, cmd); + return true; + }); + reflection.m_fence.Load(forgeRenderer->Rend(), [&](Fence** fence) { + addFence(forgeRenderer->Rend(), fence); + return true; + }); } } - // ------------------------------------------------------------------------ - // Render Illumination Pass --> renders to output target - // ------------------------------------------------------------------------ - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, - }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(frame.m_cmd, m_solidIlluminationPipeline.m_handle); + common = m_boundViewportData.update(viewport, std::move(viewportData)); + } - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + auto& currentGBuffer = common->m_gBuffer[frame.m_frameIndex]; + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); - for (auto& illuminationItem : mpCurrentRenderList->GetRenderableItems(eRenderListType_Illumination)) { - cMaterial* pMaterial = illuminationItem->GetMaterial(); - iVertexBuffer* vertexBuffer = illuminationItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { - continue; - } - ASSERT(pMaterial->type().m_id == cMaterial::SolidDiffuse && "Invalid material type"); - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, - frame, - pMaterial, - illuminationItem, - { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - }); - materialConst.objectId = instance; - std::array targets = { - eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - }; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - } + const uint32_t mainFrameIndex = updateFrameDescriptor( + frame, + frame.m_cmd, + apWorld, + { .m_size = float2(common->m_size.x, common->m_size.y), .m_viewMat = mainFrustumView, .m_projectionMat = mainFrustumProj }); + + { + + std::array reflectionBuffers; + for(size_t i = 0; i < common->m_reflectionBuffer.size(); i++) { + reflectionBuffers[i] = common->m_reflectionBuffer[i].m_buffer.m_outputBuffer.m_handle->pTexture; } + std::array params = {}; + params[0].pName = "refractionMap"; + params[0].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; + params[1].pName = "reflectionMap"; + params[1].ppTextures = reflectionBuffers.data(); + params[1].mCount = reflectionBuffers.size(); + updateDescriptorSet( + frame.m_renderer->Rend(), mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle, params.size(), params.data()); + } + + frame.m_resourcePool->Push(currentGBuffer.m_colorBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_normalBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_positionBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_specularBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_depthBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_outputBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_refractionImage); + // Setup far plane coordinates + m_farPlane = apFrustum->GetFarPlane(); + m_farTop = -tan(apFrustum->GetFOV() * 0.5f) * m_farPlane; + m_farBottom = -m_farTop; + m_farRight = m_farBottom * apFrustum->GetAspect(); + m_farLeft = -m_farRight; + + /////////////////////////// + // Occlusion testing + m_rendererList.BeginAndReset(afFrameTime, apFrustum); + cmdPreAndPostZ( + frame.m_cmd, + currentGBuffer.m_preZPassRenderables, + frame, + m_rendererList, + afFrameTime, + currentGBuffer.m_depthBuffer.m_handle, + currentGBuffer.m_hizDepthBuffer.m_handle, + apFrustum, + mainFrameIndex, + mainFrustumView, + mainFrustumProj, {}); + m_rendererList.End( + eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | + eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); + + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + cmdBuildPrimaryGBuffer(frame, frame.m_cmd, mainFrameIndex, + currentGBuffer.m_colorBuffer.m_handle, + currentGBuffer.m_normalBuffer.m_handle, + currentGBuffer.m_positionBuffer.m_handle, + currentGBuffer.m_specularBuffer.m_handle, + currentGBuffer.m_depthBuffer.m_handle, { + .m_invert = false + }); + + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } - // ------------------------------------------------------------------------ - // Render Fog Pass --> output target - // ------------------------------------------------------------------------ - auto fogRenderData = detail::createFogRenderData(mpCurrentRenderList->GetFogAreas(), apFrustum); + if (mpCurrentSettings->mbSSAOActive) { + ASSERT(m_hbaoPlusPipeline && "Invalid pipeline"); + ASSERT(currentGBuffer.m_depthBuffer.IsValid() && "Invalid depth buffer"); + ASSERT(currentGBuffer.m_normalBuffer.IsValid() && "Invalid depth buffer"); + ASSERT(currentGBuffer.m_colorBuffer.IsValid() && "Invalid depth buffer"); { - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Fog Box Pass "); - - auto createUniformFog = [&](bool isInsideNearPlane, cFogArea* fogArea) { - UniformFogData fogUniformData = {}; - if (isInsideNearPlane) { - fogUniformData.m_flags |= - (fogArea->GetShowBacksideWhenInside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty); - } else { - cMatrixf mtxInvModelView = - cMath::MatrixInverse(cMath::MatrixMul(apFrustum->GetViewMatrix(), *fogArea->GetModelMatrixPtr())); - cVector3f vRayCastStart = cMath::MatrixMul(mtxInvModelView, cVector3f(0)); - - cVector3f vNegPlaneDistNeg( - cMath::PlaneToPointDist(cPlanef(-1, 0, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, -1, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 0, -1, 0.5f), vRayCastStart)); - cVector3f vNegPlaneDistPos( - cMath::PlaneToPointDist(cPlanef(1, 0, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 1, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 0, 1, 0.5f), vRayCastStart)); - fogUniformData.m_invModelRotation = cMath::ToForgeMat4(mtxInvModelView.GetRotation().GetTranspose()); - fogUniformData.m_rayCastStart = float4(vRayCastStart.x, vRayCastStart.y, vRayCastStart.z, 0.0f); - fogUniformData.m_fogNegPlaneDistNeg = - float4(vNegPlaneDistNeg.x * -1.0f, vNegPlaneDistNeg.y * -1.0f, vNegPlaneDistNeg.z * -1.0f, 0.0f); - fogUniformData.m_fogNegPlaneDistPos = - float4(vNegPlaneDistPos.x * -1.0f, vNegPlaneDistPos.y * -1.0f, vNegPlaneDistPos.z * -1.0f, 0.0f); - fogUniformData.m_flags |= Fog::PipelineUseOutsideBox; - fogUniformData.m_flags |= - fogArea->GetShowBacksideWhenOutside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty; - } - const auto fogColor = fogArea->GetColor(); - fogUniformData.m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); - fogUniformData.m_start = fogArea->GetStart(); - fogUniformData.m_length = fogArea->GetEnd() - fogArea->GetStart(); - fogUniformData.m_falloffExp = fogArea->GetFalloffExp(); - - const cMatrixf modelMat = - fogArea->GetModelMatrixPtr() ? *fogArea->GetModelMatrixPtr() : cMatrixf::Identity; - fogUniformData.m_mv = cMath::ToForgeMat4(cMath::MatrixMul(mainFrustumView, modelMat).GetTranspose()); - fogUniformData.m_mvp = - cMath::ToForgeMat4(cMath::MatrixMul(cMath::MatrixMul(mainFrustumProj, mainFrustumView), modelMat).GetTranspose()); - return fogUniformData; + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, }; - std::vector nearPlanFog; - size_t fogIndex = 0; - for (const auto& fogArea : fogRenderData) { - cMatrixf mtxInvBoxSpace = cMath::MatrixInverse(*fogArea.m_fogArea->GetModelMatrixPtr()); - cVector3f boxSpaceFrustumOrigin = cMath::MatrixMul(mtxInvBoxSpace, apFrustum->GetOrigin()); - // test if inside near plane - if(fogArea.m_insideNearFrustum) { - nearPlanFog.emplace_back(fogArea.m_fogArea); - } else { - UniformFogData uniformData = createUniformFog(false, fogArea.m_fogArea); - BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, fogIndex * sizeof(UniformFogData)}; - beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = uniformData; - endUpdateResource(&updateDesc, NULL); - fogIndex++; - } + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + m_hbaoPlusPipeline->cmdDraw( + frame, + apFrustum, + &viewport, + currentGBuffer.m_depthBuffer.m_handle->pTexture, + currentGBuffer.m_normalBuffer.m_handle->pTexture, + currentGBuffer.m_colorBuffer.m_handle->pTexture); + { + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + } + + cmdLightPass( + frame.m_cmd, + frame, + apWorld, + apFrustum, + m_rendererList, + mainFrameIndex, + currentGBuffer.m_colorBuffer.m_handle, + currentGBuffer.m_normalBuffer.m_handle, + currentGBuffer.m_positionBuffer.m_handle, + currentGBuffer.m_specularBuffer.m_handle, + currentGBuffer.m_depthBuffer.m_handle, + currentGBuffer.m_outputBuffer.m_handle, + mainFrustumView, + mainFrustumViewInv, + mainFrustumProj, {}); + + cmdIlluminationPass( + frame.m_cmd, + frame, + m_rendererList, + mainFrameIndex, + currentGBuffer.m_depthBuffer.m_handle, + currentGBuffer.m_outputBuffer.m_handle, + {}); + // ------------------------------------------------------------------------ + // Render Illumination Pass --> renders to output target + // ------------------------------------------------------------------------ + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + std::array targets = { + currentGBuffer.m_outputBuffer.m_handle, + }; + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + cmdBindPipeline(frame.m_cmd, m_solidIlluminationPipelineCCW.m_handle); + + cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { + cMaterial* pMaterial = illuminationItem->GetMaterial(); + iVertexBuffer* vertexBuffer = illuminationItem->GetVertexBuffer(); + if (pMaterial == nullptr || vertexBuffer == nullptr) { + continue; } + ASSERT(pMaterial->type().m_id == cMaterial::SolidDiffuse && "Invalid material type"); + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(frame.m_cmd, frame, pMaterial, illuminationItem); + materialConst.objectId = instance; std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, + eVertexBufferElement_Position, + eVertexBufferElement_Texture0, }; - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - - cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipeline.m_handle); - - LegacyVertexBuffer::GeometryBinding binding{}; - std::array geometryStream = { eVertexBufferElement_Position }; - static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream, &binding); + LegacyVertexBuffer::GeometryBinding binding; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + } + } - { - std::array params = {}; - params[0].pName = "positionMap"; - params[0].ppTextures = ¤tGBuffer.m_positionBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), 0, m_fogPass.m_perFrameSet[frame.m_frameIndex], params.size(), params.data()); + // ------------------------------------------------------------------------ + // Render Fog Pass --> output target + // ------------------------------------------------------------------------ + auto fogRenderData = detail::createFogRenderData(m_rendererList.GetFogAreas(), apFrustum); + { + cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Fog Box Pass "); + + auto createUniformFog = [&](bool isInsideNearPlane, cFogArea* fogArea) { + UniformFogData fogUniformData = {}; + if (isInsideNearPlane) { + fogUniformData.m_flags |= (fogArea->GetShowBacksideWhenInside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty); + } else { + cMatrixf mtxInvModelView = + cMath::MatrixInverse(cMath::MatrixMul(apFrustum->GetViewMatrix(), *fogArea->GetModelMatrixPtr())); + cVector3f vRayCastStart = cMath::MatrixMul(mtxInvModelView, cVector3f(0)); + + cVector3f vNegPlaneDistNeg( + cMath::PlaneToPointDist(cPlanef(-1, 0, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, -1, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 0, -1, 0.5f), vRayCastStart)); + cVector3f vNegPlaneDistPos( + cMath::PlaneToPointDist(cPlanef(1, 0, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 1, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 0, 1, 0.5f), vRayCastStart)); + fogUniformData.m_invModelRotation = cMath::ToForgeMat4(mtxInvModelView.GetRotation().GetTranspose()); + fogUniformData.m_rayCastStart = float4(vRayCastStart.x, vRayCastStart.y, vRayCastStart.z, 0.0f); + fogUniformData.m_fogNegPlaneDistNeg = + float4(vNegPlaneDistNeg.x * -1.0f, vNegPlaneDistNeg.y * -1.0f, vNegPlaneDistNeg.z * -1.0f, 0.0f); + fogUniformData.m_fogNegPlaneDistPos = + float4(vNegPlaneDistPos.x * -1.0f, vNegPlaneDistPos.y * -1.0f, vNegPlaneDistPos.z * -1.0f, 0.0f); + fogUniformData.m_flags |= Fog::PipelineUseOutsideBox; + fogUniformData.m_flags |= fogArea->GetShowBacksideWhenOutside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty; } - uint32_t rootConstantIndex = getDescriptorIndexFromName(m_fogPass.m_fogRootSignature.m_handle, "rootConstant"); - struct { - float2 viewTexel; - uint32_t m_instanceIndex; - uint32_t pad0; - } fogConstant = {float2(1.0f / static_cast(common->m_size.x), 1.0f / static_cast(common->m_size.y))}; - - cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); - cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex, 0, 0); - - size_t offsetIndex = fogIndex; - for(auto& fogArea: nearPlanFog) { - UniformFogData uniformData = createUniformFog(true, fogArea); - BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, fogIndex * sizeof(UniformFogData)}; + const auto fogColor = fogArea->GetColor(); + fogUniformData.m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); + fogUniformData.m_start = fogArea->GetStart(); + fogUniformData.m_length = fogArea->GetEnd() - fogArea->GetStart(); + fogUniformData.m_falloffExp = fogArea->GetFalloffExp(); + + const cMatrixf modelMat = fogArea->GetModelMatrixPtr() ? *fogArea->GetModelMatrixPtr() : cMatrixf::Identity; + fogUniformData.m_mv = cMath::ToForgeMat4(cMath::MatrixMul(mainFrustumView, modelMat).GetTranspose()); + fogUniformData.m_mvp = + cMath::ToForgeMat4(cMath::MatrixMul(cMath::MatrixMul(mainFrustumProj, mainFrustumView), modelMat).GetTranspose()); + return fogUniformData; + }; + std::vector nearPlanFog; + size_t fogIndex = 0; + for (const auto& fogArea : fogRenderData) { + cMatrixf mtxInvBoxSpace = cMath::MatrixInverse(*fogArea.m_fogArea->GetModelMatrixPtr()); + cVector3f boxSpaceFrustumOrigin = cMath::MatrixMul(mtxInvBoxSpace, apFrustum->GetOrigin()); + // test if inside near plane + if (fogArea.m_insideNearFrustum) { + nearPlanFog.emplace_back(fogArea.m_fogArea); + } else { + UniformFogData uniformData = createUniformFog(false, fogArea.m_fogArea); + BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, + fogIndex * sizeof(UniformFogData) }; beginUpdateResource(&updateDesc); (*reinterpret_cast(updateDesc.pMappedData)) = uniformData; endUpdateResource(&updateDesc, NULL); fogIndex++; } + } + std::array targets = { + currentGBuffer.m_outputBuffer.m_handle, + }; + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipelineInsideNearFrustum.m_handle); - fogConstant.m_instanceIndex = offsetIndex; - cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex - offsetIndex, 0, 0); - - cmdEndDebugMarker(frame.m_cmd); - if (mpCurrentWorld->GetFogActive()) { - BufferUpdateDesc updateDesc = { m_fogPass.m_fogFullscreenUniformBuffer[frame.m_frameIndex].m_handle}; - beginUpdateResource(&updateDesc); - auto* fogData = reinterpret_cast(updateDesc.pMappedData); - auto fogColor = mpCurrentWorld->GetFogColor(); - fogData->m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); - fogData->m_fogStart = mpCurrentWorld->GetFogStart(); - fogData->m_fogLength = mpCurrentWorld->GetFogEnd() - mpCurrentWorld->GetFogStart(); - fogData->m_fogFalloffExp = mpCurrentWorld->GetFogFalloffExp(); - endUpdateResource(&updateDesc, NULL); - - cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); - cmdBindPipeline(frame.m_cmd, m_fogPass.m_fullScreenPipeline.m_handle); - cmdDraw(frame.m_cmd, 3, 0); + cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipeline.m_handle); - } - } - cmdEndDebugMarker(frame.m_cmd); + LegacyVertexBuffer::GeometryBinding binding{}; + std::array geometryStream = { eVertexBufferElement_Position }; + static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream, &binding); + detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array params = {}; + params[0].pName = "positionMap"; + params[0].ppTextures = ¤tGBuffer.m_positionBuffer.m_handle->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), 0, m_fogPass.m_perFrameSet[frame.m_frameIndex], params.size(), params.data()); + } + uint32_t rootConstantIndex = getDescriptorIndexFromName(m_fogPass.m_fogRootSignature.m_handle, "rootConstant"); + struct { + float2 viewTexel; + uint32_t m_instanceIndex; + uint32_t pad0; + } fogConstant = { float2(1.0f / static_cast(common->m_size.x), 1.0f / static_cast(common->m_size.y)) }; + + cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); + cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); + cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex, 0, 0); + + size_t offsetIndex = fogIndex; + for (auto& fogArea : nearPlanFog) { + UniformFogData uniformData = createUniformFog(true, fogArea); + BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, fogIndex * sizeof(UniformFogData) }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = uniformData; + endUpdateResource(&updateDesc, NULL); + fogIndex++; + } - { - std::array textureBarriers = { - TextureBarrier{ - currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, - }; - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - }; - cmdResourceBarrier( - frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); - } + cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipelineInsideNearFrustum.m_handle); + fogConstant.m_instanceIndex = offsetIndex; + cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); + cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex - offsetIndex, 0, 0); - cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_refractionCopyPipeline.m_handle); - DescriptorData params[2] = {}; - params[0].pName = "sourceInput"; - params[0].ppTextures = ¤tGBuffer.m_outputBuffer.m_handle->pTexture; - params[1].pName = "destOutput"; - params[1].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; - updateDescriptorSet( - frame.m_renderer->Rend(), 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle, 2, params); - cmdBindDescriptorSet(frame.m_cmd, 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle); - cmdDispatch( - frame.m_cmd, - static_cast(static_cast(common->m_size.x) / 16.0f) + 1, - static_cast(static_cast(common->m_size.y) / 16.0f) + 1, - 1); - { - std::array textureBarriers = { - TextureBarrier{ - currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, - }; + cmdEndDebugMarker(frame.m_cmd); + if (mpCurrentWorld->GetFogActive()) { + BufferUpdateDesc updateDesc = { m_fogPass.m_fogFullscreenUniformBuffer[frame.m_frameIndex].m_handle }; + beginUpdateResource(&updateDesc); + auto* fogData = reinterpret_cast(updateDesc.pMappedData); + auto fogColor = mpCurrentWorld->GetFogColor(); + fogData->m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); + fogData->m_fogStart = mpCurrentWorld->GetFogStart(); + fogData->m_fogLength = mpCurrentWorld->GetFogEnd() - mpCurrentWorld->GetFogStart(); + fogData->m_fogFalloffExp = mpCurrentWorld->GetFogFalloffExp(); + endUpdateResource(&updateDesc, NULL); - std::array rtBarriers = { - RenderTargetBarrier{ - currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - }; - cmdResourceBarrier( - frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); - } + cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); + cmdBindPipeline(frame.m_cmd, m_fogPass.m_fullScreenPipeline.m_handle); + cmdDraw(frame.m_cmd, 3, 0); } + } + cmdEndDebugMarker(frame.m_cmd); + + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - // notify post draw listeners - // ImmediateDrawBatch postSolidBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); - cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); - postSolidEvent.m_frustum = apFrustum; - postSolidEvent.m_frame = &frame; - postSolidEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; - postSolidEvent.m_viewport = &viewport; - postSolidEvent.m_renderSettings = mpCurrentSettings; - viewport.SignalDraw(postSolidEvent); - - // ------------------------------------------------------------------------ - // Translucency Pass --> output target - // ------------------------------------------------------------------------ { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, + std::array textureBarriers = { + TextureBarrier{ + currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - std::array translucencyBlendTable; - translucencyBlendTable[eMaterialBlendMode_None] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; - translucencyBlendTable[eMaterialBlendMode_Add] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; - translucencyBlendTable[eMaterialBlendMode_Mul] = TranslucencyPipeline::TranslucencyBlend::BlendMul; - translucencyBlendTable[eMaterialBlendMode_MulX2] = TranslucencyPipeline::TranslucencyBlend::BlendMulX2; - translucencyBlendTable[eMaterialBlendMode_Alpha] = TranslucencyPipeline::TranslucencyBlend::BlendAlpha; - translucencyBlendTable[eMaterialBlendMode_PremulAlpha] = TranslucencyPipeline::TranslucencyBlend::BlendPremulAlpha; - - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Translucency Pass"); - for (auto& translucencyItem : mpCurrentRenderList->GetRenderableItems(eRenderListType_Translucent)) { - cMaterial* pMaterial = translucencyItem->GetMaterial(); - iVertexBuffer* vertexBuffer = translucencyItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { - continue; - } + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); + } - const bool isRefraction = iRenderer::GetRefractionEnabled() && pMaterial->HasRefraction(); - const bool isFogActive = mpCurrentWorld->GetFogActive() && pMaterial->GetAffectedByFog(); - const bool isParticleEmitter = TypeInfo::IsSubtype(*translucencyItem); - const auto cubeMap = pMaterial->GetImage(eMaterialTexture_CubeMap); - cMatrixf* pMatrix = translucencyItem->GetModelMatrix(apFrustum); + cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_refractionCopyPipeline.m_handle); + DescriptorData params[2] = {}; + params[0].pName = "sourceInput"; + params[0].ppTextures = ¤tGBuffer.m_outputBuffer.m_handle->pTexture; + params[1].pName = "destOutput"; + params[1].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; + updateDescriptorSet( + frame.m_renderer->Rend(), 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle, 2, params); + cmdBindDescriptorSet(frame.m_cmd, 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle); + cmdDispatch( + frame.m_cmd, + static_cast(static_cast(common->m_size.x) / 16.0f) + 1, + static_cast(static_cast(common->m_size.y) / 16.0f) + 1, + 1); + { + std::array textureBarriers = { + TextureBarrier{ + currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + }; - if (translucencyItem->UpdateGraphicsForViewport(mpCurrentFrustum, mfCurrentFrameTime) == false) { - continue; - } + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); + } + } - if (pMaterial->HasWorldReflection() && translucencyItem->GetRenderType() == eRenderableType_SubMesh) { - // TODO implement world reflection - } + // notify post draw listeners + // ImmediateDrawBatch postSolidBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); + cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); + postSolidEvent.m_frustum = apFrustum; + postSolidEvent.m_frame = &frame; + postSolidEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; + postSolidEvent.m_viewport = &viewport; + postSolidEvent.m_renderSettings = mpCurrentSettings; + viewport.SignalDraw(postSolidEvent); + + // ------------------------------------------------------------------------ + // Translucency Pass --> output target + // ------------------------------------------------------------------------ + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + std::array targets = { + currentGBuffer.m_outputBuffer.m_handle, + }; + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + + + std::array translucencyBlendTable; + translucencyBlendTable[eMaterialBlendMode_None] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; + translucencyBlendTable[eMaterialBlendMode_Add] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; + translucencyBlendTable[eMaterialBlendMode_Mul] = TranslucencyPipeline::TranslucencyBlend::BlendMul; + translucencyBlendTable[eMaterialBlendMode_MulX2] = TranslucencyPipeline::TranslucencyBlend::BlendMulX2; + translucencyBlendTable[eMaterialBlendMode_Alpha] = TranslucencyPipeline::TranslucencyBlend::BlendAlpha; + translucencyBlendTable[eMaterialBlendMode_PremulAlpha] = TranslucencyPipeline::TranslucencyBlend::BlendPremulAlpha; + + cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Translucency Pass"); + cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + for (auto& translucencyItem : m_rendererList.GetRenderableItems(eRenderListType_Translucent)) { + cMaterial* pMaterial = translucencyItem->GetMaterial(); + iVertexBuffer* vertexBuffer = translucencyItem->GetVertexBuffer(); + if (pMaterial == nullptr || vertexBuffer == nullptr) { + continue; + } - if (isParticleEmitter) { - if (static_cast(vertexBuffer)->GetRequestNumberIndecies() == 0) { - continue; - } - } + const bool isRefraction = iRenderer::GetRefractionEnabled() && pMaterial->HasRefraction(); + const bool isReflection = pMaterial->HasWorldReflection() && translucencyItem->GetRenderType() == eRenderableType_SubMesh && + mpCurrentSettings->mbRenderWorldReflection; + const bool isFogActive = mpCurrentWorld->GetFogActive() && pMaterial->GetAffectedByFog(); + const bool isParticleEmitter = TypeInfo::IsSubtype(*translucencyItem); + const auto cubeMap = pMaterial->GetImage(eMaterialTexture_CubeMap); + uint32_t reflectionBufferIndex = 0; + cMatrixf* pMatrix = translucencyItem->GetModelMatrix(apFrustum); + + if (translucencyItem->UpdateGraphicsForViewport(apFrustum, mfCurrentFrameTime) == false) { + continue; + } - MaterialRootConstant materialConst = {0}; - float sceneAlpha = 1; - if (pMaterial->GetAffectedByFog()) { - for (auto& fogArea : fogRenderData) { - sceneAlpha *= detail::GetFogAreaVisibilityForObject(fogArea, *apFrustum, translucencyItem); - } - } - materialConst.m_sceneAlpha = sceneAlpha; - materialConst.m_lightLevel = 1.0f; + if (isReflection) { + cSubMeshEntity* pReflectionObject = static_cast(translucencyItem); - if (pMaterial->IsAffectedByLightLevel()) { - cVector3f vCenterPos = translucencyItem->GetBoundingVolume()->GetWorldCenter(); - // cRenderList *pRenderList = mpCurrentRenderList; - float fLightAmount = 0.0f; + bool bReflectionIsInRange = true; + if (pMaterial->GetMaxReflectionDistance() > 0) { + cVector3f vPoint = apFrustum->GetOrigin() + apFrustum->GetForward() * -1 * pMaterial->GetMaxReflectionDistance(); + cVector3f vNormal = apFrustum->GetForward(); - //////////////////////////////////////// - // Iterate lights and add light amount - for (auto& light : mpCurrentRenderList->GetLights()) { - // iLight* pLight = mpCurrentRenderList->GetLight(i); - auto maxColorValue = [](const cColor& aCol) { - return cMath::Max(cMath::Max(aCol.r, aCol.g), aCol.b); - }; - // Check if there is an intersection - if (light->CheckObjectIntersection(translucencyItem)) { - if (light->GetLightType() == eLightType_Box) { - fLightAmount += maxColorValue(light->GetDiffuseColor()); - } else { - float fDist = cMath::Vector3Dist(light->GetWorldPosition(), vCenterPos); + cPlanef maxRelfctionDistPlane; + maxRelfctionDistPlane.FromNormalPoint(vNormal, vPoint); - fLightAmount += - maxColorValue(light->GetDiffuseColor()) * cMath::Max(1.0f - (fDist / light->GetRadius()), 0.0f); + if (cMath::CheckPlaneBVCollision(maxRelfctionDistPlane, *translucencyItem->GetBoundingVolume()) == + eCollision_Outside) { + bReflectionIsInRange = false; + } + } + if (bReflectionIsInRange) { + /////////////////////////// + // Make a frustum, mirrored along the plane + cSubMesh* pSubMesh = pReflectionObject->GetSubMesh(); + cVector3f vSurfaceNormal = cMath::Vector3Normalize( + cMath::MatrixMul3x3(pReflectionObject->GetWorldMatrix(), pSubMesh->GetOneSidedNormal())); + cVector3f vSurfacePos = cMath::MatrixMul(pReflectionObject->GetWorldMatrix(), pSubMesh->GetOneSidedPoint()); + + cPlanef reflectPlane; + reflectPlane.FromNormalPoint(vSurfaceNormal, vSurfacePos); + + cMatrixf mtxReflection = cMath::MatrixPlaneMirror(reflectPlane); + cMatrixf mtxReflView = cMath::MatrixMul(apFrustum->GetViewMatrix(), mtxReflection); + cVector3f vReflOrigin = cMath::MatrixMul(mtxReflection, apFrustum->GetOrigin()); + + cMatrixf mtxProj = apFrustum->GetProjectionMatrix(); + + cPlanef cameraSpaceReflPlane = cMath::TransformPlane(mtxReflView, reflectPlane); + cMatrixf mtxReflProj = cMath::ProjectionMatrixObliqueNearClipPlane(mtxProj, cameraSpaceReflPlane); + + cFrustum reflectFrustum; + reflectFrustum.SetupPerspectiveProj( + mtxReflProj, + mtxReflView, + apFrustum->GetFarPlane(), + apFrustum->GetNearPlane(), + apFrustum->GetFOV(), + apFrustum->GetAspect(), + vReflOrigin, + false, + &mtxProj, + true); + reflectFrustum.SetInvertsCullMode(true); + + uint32_t maxFrameDistance = 0; + for (uint32_t i = 0; i < common->m_reflectionBuffer.size(); i++) { + if (common->m_reflectionBuffer[i].m_target == translucencyItem) { + reflectionBufferIndex = i; + break; } - if (fLightAmount >= 1.0f) { - fLightAmount = 1.0f; - break; + const uint32_t frameDist = frame.m_currentFrame - common->m_reflectionBuffer[i].m_frameCount; + if (frameDist > maxFrameDistance) { + maxFrameDistance = frameDist; + reflectionBufferIndex = i; } } - } - materialConst.m_lightLevel = fLightAmount; - } - materialConst.m_afT = GetTimeCount(); - - switch (pMaterial->type().m_id) { - case cMaterial::Translucent: - { - - - uint32_t instance = cmdBindMaterialAndObject( + cRendererDeferred::ReflectionGBuffer& resolveReflectionBuffer = common->m_reflectionBuffer[reflectionBufferIndex]; + const cMatrixf reflectionFrustumViewInv = cMath::MatrixInverse(reflectFrustum.GetViewMatrix()); + const cMatrixf reflectionFrustumView = reflectFrustum.GetViewMatrix(); + const cMatrixf reflectionFrustumProj = reflectFrustum.GetProjectionMatrix(); + const uint32_t reflectionFrameDescIndex = updateFrameDescriptor( + frame, frame.m_cmd, + apWorld, + { .m_size = float2( + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle->mWidth, + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle->mHeight), + .m_viewMat = reflectionFrustumView, + .m_projectionMat = reflectionFrustumProj }); + + FenceStatus fenceStatus; + getFenceStatus(frame.m_renderer->Rend(), resolveReflectionBuffer.m_fence.m_handle, &fenceStatus); + if (fenceStatus == FENCE_STATUS_INCOMPLETE) { + waitForFences(frame.m_renderer->Rend(), 1, &resolveReflectionBuffer.m_fence.m_handle); + } + resetCmdPool(frame.m_renderer->Rend(), resolveReflectionBuffer.m_pool.m_handle); + + beginCmd(resolveReflectionBuffer.m_cmd.m_handle); + m_reflectionRendererList.BeginAndReset(afFrameTime, &reflectFrustum); + cmdPreAndPostZ( + resolveReflectionBuffer.m_cmd.m_handle, + resolveReflectionBuffer.m_buffer.m_preZPassRenderables, frame, - pMaterial, - translucencyItem, + m_reflectionRendererList, + afFrameTime, + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_hizDepthBuffer.m_handle, + &reflectFrustum, + reflectionFrameDescIndex, + reflectionFrustumView, + reflectionFrustumProj, { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - .m_modelMatrix = std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }, + .objectVisibilityFlags = eRenderableFlag_VisibleInReflection, + .clipPlanes = {}, + .m_invert = true, + .m_disableOcclusionQueries = true, }); - materialConst.objectId = instance; - LegacyVertexBuffer::GeometryBinding binding; - - if (isParticleEmitter) { - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Color0 }; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - } else { - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent, - eVertexBufferElement_Color0 }; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - } - - cRendererDeferred::TranslucencyPipeline::TranslucencyKey key = {}; - key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + m_reflectionRendererList.End( + eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | + eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); + { + cmdBindRenderTargets(resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_colorBuffer.m_handle, + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_normalBuffer.m_handle, + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_positionBuffer.m_handle, + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_specularBuffer.m_handle, + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier( + resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + // options.m_invert = true; + cmdBuildPrimaryGBuffer( + frame, + resolveReflectionBuffer.m_cmd.m_handle, + reflectionFrameDescIndex, + resolveReflectionBuffer.m_buffer.m_colorBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_normalBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_positionBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_specularBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle, + { .m_invert = true }); - ASSERT( - pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && - pMaterial->GetBlendMode() != eMaterialBlendMode_None && "Invalid blend mode"); - if (isParticleEmitter) { - cmdBindPipeline( - frame.m_cmd, - m_materialTranslucencyPass - .m_particlePipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id].m_handle); - } else { - cmdBindPipeline( - frame.m_cmd, - (isRefraction ? m_materialTranslucencyPass.m_refractionPipeline[key.m_id].m_handle - : m_materialTranslucencyPass - .m_pipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id].m_handle)); + { + cmdBindRenderTargets(resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_colorBuffer.m_handle, + RESOURCE_STATE_RENDER_TARGET, + RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_normalBuffer.m_handle, + RESOURCE_STATE_RENDER_TARGET, + RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_positionBuffer.m_handle, + RESOURCE_STATE_RENDER_TARGET, + RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_specularBuffer.m_handle, + RESOURCE_STATE_RENDER_TARGET, + RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_outputBuffer.m_handle, + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier( + resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + cmdLightPass( + resolveReflectionBuffer.m_cmd.m_handle, + frame, + apWorld, + apFrustum, + m_reflectionRendererList, + reflectionFrameDescIndex, + resolveReflectionBuffer.m_buffer.m_colorBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_normalBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_positionBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_specularBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_outputBuffer.m_handle, + reflectionFrustumView, + reflectionFrustumViewInv, + reflectionFrustumProj, + { .m_invert = true }); + + cmdIlluminationPass( + resolveReflectionBuffer.m_cmd.m_handle, + frame, + m_reflectionRendererList, + reflectionFrameDescIndex, + resolveReflectionBuffer.m_buffer.m_depthBuffer.m_handle, + resolveReflectionBuffer.m_buffer.m_outputBuffer.m_handle, + { .m_invert = true }); + { + cmdBindRenderTargets(resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ resolveReflectionBuffer.m_buffer.m_outputBuffer.m_handle, + RESOURCE_STATE_RENDER_TARGET, + RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier( + resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); - materialConst.m_options = - (isFogActive ? TranslucencyFlags::UseFog : 0) | - (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | - translucencyBlendTable[pMaterial->GetBlendMode()] - ; + endCmd(resolveReflectionBuffer.m_cmd.m_handle); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + QueueSubmitDesc submitDesc = {}; + submitDesc.mCmdCount = 1; + submitDesc.ppCmds = &resolveReflectionBuffer.m_cmd.m_handle; + submitDesc.pSignalFence = resolveReflectionBuffer.m_fence.m_handle; + submitDesc.mSubmitDone = true; + queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); + } + } + + if (isParticleEmitter) { + if (static_cast(vertexBuffer)->GetRequestNumberIndecies() == 0) { + continue; + } + } - if (cubeMap && !isRefraction){ - materialConst.m_options = - TranslucencyFlags::UseIlluminationTrans | - (isFogActive ? TranslucencyFlags::UseFog : 0) | - TranslucencyPipeline::TranslucencyBlend::BlendAdd; + MaterialRootConstant materialConst = { 0 }; + float sceneAlpha = 1; + if (pMaterial->GetAffectedByFog()) { + for (auto& fogArea : fogRenderData) { + sceneAlpha *= detail::GetFogAreaVisibilityForObject(fogArea, *apFrustum, translucencyItem); + } + } + materialConst.m_sceneAlpha = sceneAlpha; + materialConst.m_lightLevel = 1.0f; + + if (pMaterial->IsAffectedByLightLevel()) { + cVector3f vCenterPos = translucencyItem->GetBoundingVolume()->GetWorldCenter(); + float fLightAmount = 0.0f; + + //////////////////////////////////////// + // Iterate lights and add light amount + for (auto& light : m_rendererList.GetLights()) { + auto maxColorValue = [](const cColor& aCol) { + return cMath::Max(cMath::Max(aCol.r, aCol.g), aCol.b); + }; + // Check if there is an intersection + if (light->CheckObjectIntersection(translucencyItem)) { + if (light->GetLightType() == eLightType_Box) { + fLightAmount += maxColorValue(light->GetDiffuseColor()); + } else { + float fDist = cMath::Vector3Dist(light->GetWorldPosition(), vCenterPos); - cmdBindPipeline( - frame.m_cmd, m_materialTranslucencyPass - .m_pipelines[TranslucencyPipeline::TranslucencyBlend::BlendAdd][key.m_id].m_handle); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + fLightAmount += maxColorValue(light->GetDiffuseColor()) * cMath::Max(1.0f - (fDist / light->GetRadius()), 0.0f); + } + if (fLightAmount >= 1.0f) { + fLightAmount = 1.0f; + break; } - break; } - case cMaterial::Water: - { - LegacyVertexBuffer::GeometryBinding binding; + } + materialConst.m_lightLevel = fLightAmount; + } + materialConst.m_afT = GetTimeCount(); + + switch (pMaterial->type().m_id) { + case cMaterial::Translucent: + { + uint32_t instance = cmdBindMaterialAndObject( + frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); + materialConst.objectId = instance; + LegacyVertexBuffer::GeometryBinding binding; + + if (isParticleEmitter) { + std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + } else { std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent, eVertexBufferElement_Color0 }; static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + } + + cRendererDeferred::TranslucencyPipeline::TranslucencyKey key = {}; + key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + + ASSERT( + pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && pMaterial->GetBlendMode() != eMaterialBlendMode_None && + "Invalid blend mode"); + if (isParticleEmitter) { + cmdBindPipeline( + frame.m_cmd, + m_materialTranslucencyPass.m_particlePipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] + .m_handle); + } else { + cmdBindPipeline( + frame.m_cmd, + (isRefraction + ? m_materialTranslucencyPass.m_refractionPipeline[key.m_id].m_handle + : m_materialTranslucencyPass.m_pipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] + .m_handle)); + } - materialConst.m_options = - (isFogActive ? TranslucencyFlags::UseFog : 0) | - (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | - translucencyBlendTable[pMaterial->GetBlendMode()] - ; + detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); + materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | + (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | translucencyBlendTable[pMaterial->GetBlendMode()]; - cRendererDeferred::TranslucencyPipeline::TranslucencyWaterKey key = {}; - key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); + if (cubeMap && !isRefraction) { + materialConst.m_options = TranslucencyFlags::UseIlluminationTrans | (isFogActive ? TranslucencyFlags::UseFog : 0) | + TranslucencyPipeline::TranslucencyBlend::BlendAdd; - cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_waterPipeline[key.m_id].m_handle); - uint32_t instance = cmdBindMaterialAndObject( + cmdBindPipeline( frame.m_cmd, - frame, - pMaterial, - translucencyItem, - { - .m_viewMat = mainFrustumView, - .m_projectionMat = mainFrustumProj, - .m_modelMatrix = std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }, - }); - materialConst.objectId = instance; + m_materialTranslucencyPass.m_pipelines[TranslucencyPipeline::TranslucencyBlend::BlendAdd][key.m_id].m_handle); cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); - break; } - default: - ASSERT(false && "Invalid material type"); - continue; } - } - cmdEndDebugMarker(frame.m_cmd); - } + break; + case cMaterial::Water: + { + LegacyVertexBuffer::GeometryBinding binding; + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent, + eVertexBufferElement_Color0 }; + static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - // ImmediateDrawBatch postTransBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); - cViewport::PostTranslucenceDrawPacket translucenceEvent = cViewport::PostTranslucenceDrawPacket(); - translucenceEvent.m_frustum = apFrustum; - translucenceEvent.m_frame = &frame; - translucenceEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; - translucenceEvent.m_viewport = &viewport; - translucenceEvent.m_renderSettings = mpCurrentSettings; - viewport.SignalDraw(translucenceEvent); + materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | + (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | + (isReflection ? TranslucencyFlags::UseReflectionTrans : 0) | + translucencyBlendTable[pMaterial->GetBlendMode()] | + (((reflectionBufferIndex & TranslucencyReflectionBufferMask) << TranslucencyReflectionBufferOffset)); - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + + cRendererDeferred::TranslucencyPipeline::TranslucencyWaterKey key = {}; + key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + + detail::cmdDefaultLegacyGeomBinding(frame.m_cmd, frame, binding); + + cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_waterPipeline[key.m_id].m_handle); + uint32_t instance = cmdBindMaterialAndObject( + frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); + materialConst.objectId = instance; + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + + } + break; + default: + ASSERT(false && "Invalid material type"); + continue; + } } + cmdEndDebugMarker(frame.m_cmd); } - iVertexBuffer* cRendererDeferred::GetLightShape(iLight* apLight, eDeferredShapeQuality aQuality) const { - switch (apLight->GetLightType()) { - case eLightType_Point: - return m_shapeSphere[aQuality].get(); - case eLightType_Spot: - return m_shapePyramid.get(); - case eLightType_Box: - return m_box.get(); - default: - break; - } - return nullptr; + // ImmediateDrawBatch postTransBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); + cViewport::PostTranslucenceDrawPacket translucenceEvent = cViewport::PostTranslucenceDrawPacket(); + translucenceEvent.m_frustum = apFrustum; + translucenceEvent.m_frame = &frame; + translucenceEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; + translucenceEvent.m_viewport = &viewport; + translucenceEvent.m_renderSettings = mpCurrentSettings; + viewport.SignalDraw(translucenceEvent); + + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } +} + +iVertexBuffer* cRendererDeferred::GetLightShape(iLight* apLight, eDeferredShapeQuality aQuality) const { + switch (apLight->GetLightType()) { + case eLightType_Point: + return m_shapeSphere[aQuality].get(); + case eLightType_Spot: + return m_shapePyramid.get(); + case eLightType_Box: + return m_box.get(); + default: + break; } + return nullptr; +} } // namespace hpl diff --git a/HPL2/sources/graphics/RendererSimple.cpp b/HPL2/sources/graphics/RendererSimple.cpp index 8a0d859f6..2aae245cf 100644 --- a/HPL2/sources/graphics/RendererSimple.cpp +++ b/HPL2/sources/graphics/RendererSimple.cpp @@ -50,7 +50,7 @@ namespace hpl { cRendererSimple::cRendererSimple(cGraphics* apGraphics, cResources* apResources) - : iRenderer("Simple", apGraphics, apResources, 0) + : iRenderer("Simple", apGraphics, apResources) { } diff --git a/HPL2/sources/graphics/RendererWireFrame.cpp b/HPL2/sources/graphics/RendererWireFrame.cpp index 5f4ef83df..9e8c201dd 100644 --- a/HPL2/sources/graphics/RendererWireFrame.cpp +++ b/HPL2/sources/graphics/RendererWireFrame.cpp @@ -54,7 +54,7 @@ namespace hpl { //----------------------------------------------------------------------- cRendererWireFrame::cRendererWireFrame(cGraphics *apGraphics,cResources* apResources) - : iRenderer("WireFrame",apGraphics, apResources,0) + : iRenderer("WireFrame",apGraphics, apResources) { //////////////////////////////////// // Set up render specific things diff --git a/HPL2/sources/math/Math.cpp b/HPL2/sources/math/Math.cpp index 94d21738a..f4f89776b 100644 --- a/HPL2/sources/math/Math.cpp +++ b/HPL2/sources/math/Math.cpp @@ -2473,9 +2473,9 @@ namespace hpl { cMatrixf cMath::MatrixPlaneMirror(const cPlanef &aPlane) { - return cMatrixf( 1-2*aPlane.a*aPlane.a, -2*aPlane.b*aPlane.a, -2*aPlane.c*aPlane.a, -2*aPlane.a*aPlane.d, - -2*aPlane.a*aPlane.b, 1-2*aPlane.b*aPlane.b, -2*aPlane.c*aPlane.b, -2*aPlane.b*aPlane.d, - -2*aPlane.a*aPlane.c, -2*aPlane.b*aPlane.c, 1-2*aPlane.c*aPlane.c, -2*aPlane.c*aPlane.d, + return cMatrixf( 1.0f-2.0f*aPlane.a*aPlane.a, -2.0f*aPlane.b*aPlane.a, -2.0f*aPlane.c*aPlane.a, -2*aPlane.a*aPlane.d, + -2.0f*aPlane.a*aPlane.b, 1.0f-2.0f*aPlane.b*aPlane.b, -2.0f*aPlane.c*aPlane.b, -2*aPlane.b*aPlane.d, + -2.0f*aPlane.a*aPlane.c, -2.0f*aPlane.b*aPlane.c, 1.0f-2.0f*aPlane.c*aPlane.c, -2*aPlane.c*aPlane.d, 0, 0, 0, 1); } @@ -2617,13 +2617,13 @@ namespace hpl { pQ.a = (Sign(aClipPlane.a) + a_mtxProjMatrix.m[0][2]) / a_mtxProjMatrix.m[0][0]; pQ.b = (Sign(aClipPlane.b) + a_mtxProjMatrix.m[1][2]) / a_mtxProjMatrix.m[1][1]; pQ.c = -1.0f; - pQ.d = (1.0f + a_mtxProjMatrix.m[2][2]) / a_mtxProjMatrix.m[2][3]; + pQ.d = (1.0f - a_mtxProjMatrix.m[2][2]) / a_mtxProjMatrix.m[2][3]; cPlanef pC = aClipPlane * (2.0f / PlaneDot(aClipPlane, pQ)); mtxOutput.m[2][0] = pC.a; mtxOutput.m[2][1] = pC.b; - mtxOutput.m[2][2] = pC.c + 1.0f; + mtxOutput.m[2][2] = pC.c;// + 1.0f; mtxOutput.m[2][3] = pC.d; return mtxOutput; diff --git a/HPL2/sources/scene/Viewport.cpp b/HPL2/sources/scene/Viewport.cpp index 11e5bd955..443bd90e5 100644 --- a/HPL2/sources/scene/Viewport.cpp +++ b/HPL2/sources/scene/Viewport.cpp @@ -47,8 +47,6 @@ namespace hpl { , mpRenderer(nullptr) , mpPostEffectComposite(nullptr) , mbIsListener(false) { - // m_imageDescriptor = ImageDescriptor::CreateTexture2D(0, 0, false, bgfx::TextureFormat::Enum::RGBA8); - // m_imageDescriptor.m_configuration.m_rt = RTType::RT_Write; std::lock_guard lock(internal::m_mutex); if (internal::m_freelist.empty()) { @@ -63,9 +61,6 @@ namespace hpl { if (m_dirtyViewport) { if (m_size.x > 0 && m_size.y > 0 && m_renderTarget) { m_dirtyViewport = false; - // m_imageDescriptor.m_width = m_size.x; - // m_imageDescriptor.m_height = m_size.y; - // auto image = std::make_shared(); } m_viewportChanged.Signal(); } @@ -160,15 +155,7 @@ namespace hpl { m_updateEventHandler = IUpdateEventLoop::UpdateEvent::Handler([&](float dt) { if (m_dirtyViewport) { if (m_size.x > 0 && m_size.y > 0) { - // auto desc = ImageDescriptor::CreateTexture2D(m_size.x, m_size.y, false, bgfx::TextureFormat::Enum::RGBA8); - // desc.m_configuration.m_rt = RTType::RT_Write; - // auto image = std::make_shared(); - // image->Initialize(desc); - m_dirtyViewport = false; - // std::array, 1> images = { image }; - // m_renderTarget.Invalidate(); - // m_renderTarget.Initialize(images); } m_viewportChanged.Signal(); } diff --git a/vcpkg b/vcpkg index c7fc29984..4a600e9fe 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit c7fc2998445046e8ba3a470eeb49ee1520fbd370 +Subproject commit 4a600e9fea71bd7872080cbb716797e04d30e6d3