diff --git a/build/engine/textures/dev/dev_floor_normal.dds b/build/engine/textures/dev/dev_floor_normal.dds index 939ee60d6e58a9e0167f0c3754b1cecef0d878f5..6090c53fb7822e29f22685425b70a2bd465c72a3 100644 Binary files a/build/engine/textures/dev/dev_floor_normal.dds and b/build/engine/textures/dev/dev_floor_normal.dds differ diff --git a/build/engine/textures/dev/dev_floor_normal.psd b/build/engine/textures/dev/dev_floor_normal.psd new file mode 100644 index 0000000000000000000000000000000000000000..a32f6e496a8f49da035c3bb7618716c24bb483e4 Binary files /dev/null and b/build/engine/textures/dev/dev_floor_normal.psd differ diff --git a/build/gamesource/gui/menu/settings_video.html b/build/gamesource/gui/menu/settings_video.html index aaff1a2b9bda3d6cc65f75e299f41be2fa1ca186..1873829d281d67034ac4c29725f4f7fc22225da7 100644 --- a/build/gamesource/gui/menu/settings_video.html +++ b/build/gamesource/gui/menu/settings_video.html @@ -9,12 +9,13 @@ <div id="title">Видео</div> <div id="left_menu"> <div class="menu-item">Разрешение</div> - <div class="menu-item">Во весь экран</div> - <div class="menu-item">Сглаживание</div> + <!-- <div class="menu-item">Во весь экран</div> --> + <!-- <div class="menu-item">Сглаживание</div> --> <div class="menu-item">Разрешение текстур</div> - <div class="menu-item">Контраст</div> - <div class="menu-item">Гамма</div> - <div class="menu-item">Яркость</div> + <div class="menu-item">Глобальное освещение</div> + <!-- <div class="menu-item">Контраст</div> --> + <!-- <div class="menu-item">Гамма</div> --> + <!-- <div class="menu-item">Яркость</div> --> <div class="menu-item" onclick="engine_command" args=" gui_load menu_settings_video_ex menu/settings_video_ex.html @@ -29,24 +30,30 @@ <option value="1">1920x1080</option> <option value="0">1366x768</option> </select> - <select class="set_item" cvar="r_win_windowed"> - <option value="0">Да</option> - <option value="1">Нет</option> - </select> - <select class="set_item" cvar="pp_dlaa|pp_nfaa"> - <option value="0|0">Нет</option> - <option value="1|0">DLAA</option> - <option value="0|1">NFAA</option> + <!-- <select class="set_item" cvar="r_win_windowed"> --> + <!-- <option value="0">Да</option> --> + <!-- <option value="1">Нет</option> --> + <!-- </select> --> + <!-- <select class="set_item" cvar="pp_dlaa|pp_nfaa"> --> + <!-- <option value="0|0">Нет</option> --> + <!-- <option value="1|0">DLAA</option> --> + <!-- <option value="0|1">NFAA</option> --> <!-- <option value="1|1">NFAA+DLAA</option> --> - </select> + <!-- </select> --> <select class="set_item" cvar="r_texfilter_max_miplevel"> <option value="0">Высокое</option> <option value="1">Среднее</option> <option value="2">Низкое</option> </select> - <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_contrast" /></div> - <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_gamma" /></div> - <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_bright" /></div> + <select class="set_item" cvar="lpv_cascades_count"> + <option value="0">Нет</option> + <option value="1">Низкое</option> + <option value="2">Среднее</option> + <option value="3">Высокое</option> + </select> + <!-- <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_contrast" /></div> --> + <!-- <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_gamma" /></div> --> + <!-- <div style="height: 40px; position: relative; top: 10px;"><range class="set_item" min="0" max="1" step="0.01" format="%.2f" cvar="pp_bright" /></div> --> <div class="menu-item bottom" onclick="settings_commit" style="text-align: right;">Применить</div> </div> diff --git a/build/gamesource/gui/menu/settings_video_ex.html b/build/gamesource/gui/menu/settings_video_ex.html index ded330006ed46c24ceed22ca9fc9d34fa1778b77..e1e667924e9acc83992e4657e18be641b102192c 100644 --- a/build/gamesource/gui/menu/settings_video_ex.html +++ b/build/gamesource/gui/menu/settings_video_ex.html @@ -9,13 +9,14 @@ <div id="title">Расширенные</div> <div id="left_menu"> <div class="menu-item">Фильтрация текстур</div> - <div class="menu-item">Эффект bloom</div> - <div class="menu-item">Эффект lensflare</div> - <div class="menu-item">Эффект SSAO</div> + <!-- <div class="menu-item">Эффект bloom</div> --> + <!-- <div class="menu-item">Эффект lensflare</div> --> + <!-- <div class="menu-item">Эффект SSAO</div> --> <div class="menu-item">Глобальные тени</div> - <div class="menu-item">Локальные тени</div> - <div class="menu-item">Размытие теней</div> - <div class="menu-item">Размытие в движении</div> + <div class="menu-item">Точечные тени</div> + <div class="menu-item">Направленные тени</div> + <!-- <div class="menu-item">Размытие теней</div> --> + <!-- <div class="menu-item">Размытие в движении</div> --> <div class="menu-item bottom" onclick="on_cancel">Назад</div> </div> @@ -29,7 +30,7 @@ <option value="2|8">Анизотропная 8X</option> <option value="2|16">Анизотропная 16X</option> </select> - <select class="set_item" cvar="pp_bloom"> + <!-- <select class="set_item" cvar="pp_bloom"> <option value="1">Включить</option> <option value="0">Выключить</option> </select> @@ -40,13 +41,19 @@ <select class="set_item" cvar="pp_ssao"> <option value="1">Включить</option> <option value="0">Выключить</option> + </select> --> + <select class="set_item" cvar="r_pssm_quality"> + <!-- <option value="0|0.500000">Нет</option> --> + <option value="0.500000">Низкое</option> + <option value="1.000000">Среднее</option> + <option value="2.000000">Высокое</option> + <option value="4.000000">Очень высокое</option> </select> - <select class="set_item" cvar="r_pssm_shadowed|r_pssm_quality"> - <option value="0|0.500000">Нет</option> - <option value="1|0.500000">Низкое</option> - <option value="1|1.000000">Среднее</option> - <option value="1|2.000000">Высокое</option> - <option value="1|4.000000">Очень высокое</option> + <select class="set_item" cvar="r_psm_quality"> + <option value="0.500000">Низкое</option> + <option value="1.000000">Среднее</option> + <option value="2.000000">Высокое</option> + <option value="4.000000">Очень высокое</option> </select> <select class="set_item" cvar="r_lsm_quality"> <option value="0.500000">Низкое</option> @@ -54,7 +61,7 @@ <option value="2.000000">Высокое</option> <option value="4.000000">Очень высокое</option> </select> - <select class="set_item" cvar="r_shadow_soft"> + <!-- <select class="set_item" cvar="r_shadow_soft"> <option value="0">Нет</option> <option value="1">1 проход</option> <option value="2">2 прохода</option> @@ -62,7 +69,7 @@ <select class="set_item" cvar="pp_motionblur"> <option value="1">Включить</option> <option value="0">Выключить</option> - </select> + </select> --> <div class="menu-item bottom" onclick="settings_commit" style="text-align: right;">Применить</div> </div> diff --git a/source/anim/RenderableVisibility.cpp b/source/anim/RenderableVisibility.cpp index ca01c54d0d0406a0dbbfe98ce6e1bc5fa4ba6ec3..7f15e413e1b6f31774919e6434c76beb75b5d86f 100644 --- a/source/anim/RenderableVisibility.cpp +++ b/source/anim/RenderableVisibility.cpp @@ -10,7 +10,7 @@ CRenderableVisibility::CRenderableVisibility(ID idPlugin, CAnimatedModelProvider { } -ID CRenderableVisibility::getPluginId() +ID CRenderableVisibility::getPluginId() const { return(m_idPlugin); } @@ -30,7 +30,7 @@ void CRenderableVisibility::updateForFrustum(const IFrustum *pFrustum, const IXR CRenderableVisibility *pRef = NULL; if(pReference) { - assert(((IXRenderableVisibility*)pReference)->getPluginId() == -1); + assert(((IXRenderableVisibility*)pReference)->getPluginId() == getPluginId()); pRef = (CRenderableVisibility*)pReference; } @@ -38,6 +38,90 @@ void CRenderableVisibility::updateForFrustum(const IFrustum *pFrustum, const IXR m_pProviderDynamic->computeVisibility(pFrustum, this, pRef); } +void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) +{ + assert(((IXRenderableVisibility*)pOther_)->getPluginId() == getPluginId()); + const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; + + item_s *pItem; + const item_s *pOtherItem; + for(UINT i = 0, l = pOther->m_aItems.size(); i < l; ++i) + { + pOtherItem = &pOther->m_aItems[i]; + if(pOtherItem->isVisible) + { + pItem = &m_aItems[i]; + if(pItem->isVisible) + { + if(pOtherItem->uLod < pItem->uLod) + { + pItem->uLod = pOtherItem->uLod; + } + } + else + { + pItem->isTransparent = pOtherItem->isTransparent; + pItem->isVisible = true; + pItem->uLod = pOtherItem->uLod; + } + } + } + + for(UINT i = 0, l = pOther->m_aItemsDynamic.size(); i < l; ++i) + { + pOtherItem = &pOther->m_aItemsDynamic[i]; + if(pOtherItem->isVisible) + { + pItem = &m_aItemsDynamic[i]; + if(pItem->isVisible) + { + if(pOtherItem->uLod < pItem->uLod) + { + pItem->uLod = pOtherItem->uLod; + } + } + else + { + pItem->isTransparent = pOtherItem->isTransparent; + pItem->isVisible = true; + pItem->uLod = pOtherItem->uLod; + } + } + } + + //! @todo implement for transparency too! +} + +void CRenderableVisibility::substract(const IXRenderableVisibility *pOther_) +{ + assert(((IXRenderableVisibility*)pOther_)->getPluginId() == getPluginId()); + const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; + + item_s *pItem; + const item_s *pOtherItem; + for(UINT i = 0, l = pOther->m_aItems.size(); i < l; ++i) + { + pOtherItem = &pOther->m_aItems[i]; + pItem = &m_aItems[i]; + if(pItem->isVisible && pOtherItem->isVisible) + { + pItem->isVisible = false; + } + } + + for(UINT i = 0, l = pOther->m_aItemsDynamic.size(); i < l; ++i) + { + pOtherItem = &pOther->m_aItemsDynamic[i]; + pItem = &m_aItemsDynamic[i]; + if(pItem->isVisible && pOtherItem->isVisible) + { + pItem->isVisible = false; + } + } + + //! @todo implement for transparency too! +} + void CRenderableVisibility::setItemCount(UINT uCount) { if(m_aItems.GetAllocSize() > uCount * 2) diff --git a/source/anim/RenderableVisibility.h b/source/anim/RenderableVisibility.h index f890ae17867d53d21bc52f485455c4afbc9d1004..d0d4112e11641c3789bc92a8ca24e0a12d7b47ce 100644 --- a/source/anim/RenderableVisibility.h +++ b/source/anim/RenderableVisibility.h @@ -11,14 +11,18 @@ class CRenderableVisibility: public IXRenderableVisibility public: CRenderableVisibility(ID idPlugin, CAnimatedModelProvider *m_pProviderAnimated, CDynamicModelProvider *m_pProviderDynamic); - ID getPluginId(); + ID getPluginId() const override; - void setOcclusionCuller(IXOcclusionCuller *pOcclusionCuller); + void setOcclusionCuller(IXOcclusionCuller *pOcclusionCuller) override; - void updateForCamera(ICamera *pCamera, const IXRenderableVisibility *pReference = NULL); + void updateForCamera(ICamera *pCamera, const IXRenderableVisibility *pReference = NULL) override; - void updateForFrustum(const IFrustum *pFrustum, const IXRenderableVisibility *pReference = NULL); + void updateForFrustum(const IFrustum *pFrustum, const IXRenderableVisibility *pReference = NULL) override; + void append(const IXRenderableVisibility *pOther) override; + + void substract(const IXRenderableVisibility *pOther) override; + struct item_s { bool isVisible = false; diff --git a/source/common b/source/common index cc34760a0f9dc08eaa9db29930f96c9697a7e975..a887a31b4b9541a0997e9fa8ac34ad62977813fc 160000 --- a/source/common +++ b/source/common @@ -1 +1 @@ -Subproject commit cc34760a0f9dc08eaa9db29930f96c9697a7e975 +Subproject commit a887a31b4b9541a0997e9fa8ac34ad62977813fc diff --git a/source/light/LightSystem.cpp b/source/light/LightSystem.cpp index 519ca34ff02d19491bbdc66dba744ba5211cb3f1..24615237e24dac39749deb63581a875bc0672473 100644 --- a/source/light/LightSystem.cpp +++ b/source/light/LightSystem.cpp @@ -32,6 +32,11 @@ private: CLightSystem::CLightSystem(IXCore *pCore): m_pCore(pCore) { + Core_0RegisterCVarFloat("lpv_size_0", 1.0f, "Коэфициент размера первого каскада LPV"); + Core_0RegisterCVarFloat("lpv_size_1", 2.0f, "Коэфициент размера второго каскада LPV"); + Core_0RegisterCVarFloat("lpv_size_2", 4.0f, "Коэфициент размера третьего каскада LPV"); + Core_0RegisterCVarInt("lpv_cascades_count", 3, "Количество активных каскадов LPV [0;3]"); + m_pLevelListener = new CLevelLoadListener(this, pCore); m_pLevelChannel = pCore->getEventChannel<XEventLevel>(EVENT_LEVEL_GUID); @@ -198,7 +203,13 @@ CLightSystem::CLightSystem(IXCore *pCore): m_idComLightingSpotShadow = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_com.ps", "lighting_com_spot_shadow.ps", Defines_IS_SPOT_SHADOWED)); m_idComLightingPSSMShadow = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_com.ps", "lighting_com_pssm_shadow.ps", Defines_IS_PSSM_SHADOWED)); - m_idComLightingGI = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_gi.ps")); + // LPV_CASCADES_COUNT - iCascades + GXMacro Defines_LPV_CASCADE_3[] = {{"LPV_START_CASCADE", "0"}, {0, 0}}; + m_idComLightingGI[2] = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_gi.ps", 0, Defines_LPV_CASCADE_3)); + GXMacro Defines_LPV_CASCADE_2[] = {{"LPV_START_CASCADE", "1"}, {0, 0}}; + m_idComLightingGI[1] = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_gi.ps", 0, Defines_LPV_CASCADE_2)); + GXMacro Defines_LPV_CASCADE_1[] = {{"LPV_START_CASCADE", "2"}, {0, 0}}; + m_idComLightingGI[0] = SGCore_ShaderCreateKit(idResPos, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "lighting_gi.ps", 0, Defines_LPV_CASCADE_1)); m_idHDRinitLuminance = SGCore_ShaderCreateKit(idScreenOut, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "hdr_luminance.ps")); m_idHDRAdaptLuminance = SGCore_ShaderCreateKit(idScreenOut, SGCore_ShaderLoad(SHADER_TYPE_PIXEL, "hdr_adapt.ps")); @@ -351,7 +362,6 @@ void CLightSystem::destroySun(IXLightSun *pLight) { assert(m_pSun == pLight); _deleteLight(m_pSun); - mem_delete(m_pSun); } void CLightSystem::destroyPoint(IXLightPoint *_pLight) { @@ -404,16 +414,37 @@ void XMETHODCALLTYPE CLightSystem::updateVisibility() float3 vCamPos; m_pMainCamera->getPosition(&vCamPos); + float3 vCamDir; + m_pMainCamera->getLook(&vCamDir); - //! @todo fix this values! - float3 vLPVmin = float3(-16.0f, -16.0f, -16.0f) + vCamPos; - float3 vLPVmax = float3(16.0f, 16.0f, 16.0f) + vCamPos; + static const float *lpv_size_2 = GET_PCVAR_FLOAT("lpv_size_2"); + static const int *lpv_cascades_count = GET_PCVAR_INT("lpv_cascades_count"); + + int iCascades = *lpv_cascades_count; + if(iCascades < 0) + { + iCascades = 0; + } + if(iCascades > LPV_CASCADES_COUNT) + { + iCascades = LPV_CASCADES_COUNT; + } + + float3 vLPVmin; + float3 vLPVmax; + if(iCascades) + { + vLPVmin = vLPVmax = vCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * *lpv_size_2; + + vLPVmin += float3(-16.0f, -16.0f, -16.0f) * *lpv_size_2; + vLPVmax += float3(16.0f, 16.0f, 16.0f) * *lpv_size_2; + } for(UINT i = 0, l = m_aLights.size(); i < l; ++i) { if(m_aLights[i]->isEnabled()) { - m_aLights[i]->updateVisibility(m_pMainCamera, vLPVmin, vLPVmax); + m_aLights[i]->updateVisibility(m_pMainCamera, vLPVmin, vLPVmax, iCascades > 0); } } } @@ -423,14 +454,24 @@ void XMETHODCALLTYPE CLightSystem::setFrameObserverCamera(ICamera *pMainCamera) //! @todo uncomment me! // pMainCamera->AddRef(); m_pMainCamera = pMainCamera; + if(m_pSun) + { + m_pSun->setCamera(pMainCamera); + } } void XMETHODCALLTYPE CLightSystem::setGBuffer(IGXTexture2D *pColor, IGXTexture2D *pNormals, IGXTexture2D *pParams, IGXTexture2D *pDepth) { + mem_release(m_pGBufferColor); + mem_release(m_pGBufferNormals); + mem_release(m_pGBufferParams); + mem_release(m_pGBufferDepth); + pColor->AddRef(); pNormals->AddRef(); pParams->AddRef(); pDepth->AddRef(); + m_pGBufferColor = pColor; m_pGBufferNormals = pNormals; m_pGBufferParams = pParams; @@ -476,7 +517,7 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur //очищаем рт и стенсил pCtx->clear(GX_CLEAR_COLOR); // pCtx->clear(GX_CLEAR_COLOR | GX_CLEAR_STENCIL); - + m_pRenderPipeline->renderGI(); float3 vCamDir; @@ -484,15 +525,25 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur float3 vCamPos; m_pMainCamera->getPosition(&vCamPos); + static const float *lpv_size_0 = GET_PCVAR_FLOAT("lpv_size_0"); + static const float *lpv_size_1 = GET_PCVAR_FLOAT("lpv_size_1"); + static const float *lpv_size_2 = GET_PCVAR_FLOAT("lpv_size_2"); + static const int *lpv_cascades_count = GET_PCVAR_INT("lpv_cascades_count"); - const float c_aLPVsizes[] = { - //0.5f, - //1.0f, - //2.0f + int iCascades = *lpv_cascades_count; + if(iCascades < 0) + { + iCascades = 0; + } + if(iCascades > LPV_CASCADES_COUNT) + { + iCascades = LPV_CASCADES_COUNT; + } - 1.0f, - 2.0f, - 4.0f + const float c_aLPVsizes[] = { + *lpv_size_0, + *lpv_size_1, + *lpv_size_2 }; m_lpvCentersShaderData.vs.vCenterSize[0] = float4(vCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[0], c_aLPVsizes[0]); @@ -500,31 +551,6 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur m_lpvCentersShaderData.vs.vCenterSize[2] = float4(vCamPos + vCamDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * c_aLPVsizes[2], c_aLPVsizes[2]); m_pLPVcentersShaderData->update(&m_lpvCentersShaderData.vs); - /* - vs: - cbuffer0: (per light) - - g_mW - cbuffer1: (per frame) - - g_mVP - - g_mViewInv - - g_vNearFar - - g_vParamProj - - ps: - cbuffer0: (per light) - - g_vLightPos - - g_vLightColor - - g_vLightPowerDistShadow - cbuffer1: (per frame) - - g_vViewPos - - - { - render shadowmaps - render direct light with shadows - inject VPLs into LPV grid - } - */ // Определим список лампочек, которые будут участвовать в текущем кадре CXLight *pLight; @@ -550,25 +576,9 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur static const float *r_near = GET_PCVAR_FLOAT("r_near"); static const float *r_far = GET_PCVAR_FLOAT("r_far"); - // float4x4 &mCamView = gdata::mCamView; - // // Core_RMatrixGet(G_RI_MATRIX_OBSERVER_VIEW, &mCamView); - // m_shadowShaderData.vs.mViewInv = SMMatrixTranspose(SMMatrixInverse(NULL, mCamView)); - // m_shadowShaderData.vs.vNearFar = gdata::vNearFar; // float2(*r_near, *r_far); - // m_shadowShaderData.vs.vParamProj = float3((float)m_uOutWidth, (float)m_uOutHeight, gdata::fProjFov); // *r_default_fov); - // m_pShadowShaderDataVS->update(&m_shadowShaderData.vs); - - //@TODO: убрать это - //Core_RFloat3Get(G_RI_FLOAT3_OBSERVER_POSITION, &m_shadowShaderData.ps.vPosCam); - //m_pShadowShaderDataPS->update(&m_shadowShaderData.ps); - - - //m_pDevice->setPixelShaderConstant(m_pShadowShaderDataPS, 7); pCtx->setRasterizerState(m_pRasterizerConservative); - //pCtx->setVSConstant(m_pCameraShaderDataVS, 8); - //pCtx->setPSConstant(m_pCameraShaderDataVS, 8); - UINT uShadowCount = 0; while((uShadowCount = m_pShadowCache->processNextBunch())) { @@ -576,9 +586,6 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur pCtx->setDepthStencilSurface(pOldDSSurface); pCtx->setBlendState(m_pBlendAlphaOneOne); - // pCtx->setVSConstant(m_pLightingShaderDataVS, 1); - // pCtx->setPSConstant(m_pLightingShaderDataPS, 1); - IBaseShadowMap *pShadow = NULL; //render direct light with shadows @@ -611,10 +618,6 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur pCtx->setRasterizerState(NULL); - - //pCtx->setVSConstant(m_pShadowShaderDataVS, 1); - // pCtx->setVSConstant(m_pLightingShaderDataVS, 1); - pCtx->setBlendState(m_pBlendRed); pShadow->genShadow(m_pGBufferDepth, m_pGBufferNormals); pCtx->setBlendState(m_pBlendAlphaOneOne); @@ -638,8 +641,6 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur assert(!"Unknown light type!"); } - // pCtx->setVSConstant(m_pLightingShaderDataVS, 1); - //теперь когда будем считать освещение надо сбросить значения в стенсил буфере, чтобы каждый кадр не чистить //если стенсил тест прошел успешно, устанавливаем значнеие в нуль if(pLight->getType() != LIGHT_TYPE_SUN) @@ -663,17 +664,13 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur SGCore_ScreenQuadDraw(); } - - - //pCtx->setSamplerState(gdata::rstates::pSamplerLinearWrap, 0); - //pCtx->setSamplerState(gdata::rstates::pSamplerLinearWrap, 1); } pCtx->setVSConstant(m_pLPVcentersShaderData, 9); pCtx->setPSConstant(m_pLPVcentersShaderData, 9); bool isFirstRun[3] = {true, true, true}; - while((uShadowCount = m_pShadowCache->processNextRSMBunch())) + while(iCascades && (uShadowCount = m_pShadowCache->processNextRSMBunch())) { pCtx->setVSConstant(m_pLPVcurrentCascadeShaderData, 10); pCtx->setPSConstant(m_pLPVcurrentCascadeShaderData, 10); @@ -681,15 +678,15 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur pCtx->setDepthStencilSurface(pOldDSSurface); pCtx->setBlendState(m_pBlendAlphaOneOne); - // pCtx->setVSConstant(m_pLightingShaderDataVS, 1); - // pCtx->setPSConstant(m_pLightingShaderDataPS, 1); + // pCtx->setVSConstant(m_pLightingShaderDataVS, 1); + // pCtx->setPSConstant(m_pLightingShaderDataPS, 1); IGXDepthStencilSurface *pOldSurface = pCtx->getDepthStencilSurface(); pCtx->unsetDepthStencilSurface(); IBaseReflectiveShadowMap *pShadow = NULL; - for(UINT i = 0; i < 3; ++i) + for(UINT i = LPV_CASCADES_COUNT - iCascades; i < LPV_CASCADES_COUNT; ++i) { float4_t vTmp((float)i + 0.5f); // just to be sure m_pLPVcurrentCascadeShaderData->update(&vTmp); @@ -744,38 +741,42 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur //break; } - for(UINT i = 0; i < 3; ++i) + + bool isClean[3] = {0}; + if(iCascades) { - if(isFirstRun[i]) + for(UINT i = 0; i < 3; ++i) { - IGXSurface *pLPVRed = m_aLPVs[i].pGIAccumRed->asRenderTarget(); - IGXSurface *pLPVGreen = m_aLPVs[i].pGIAccumGreen->asRenderTarget(); - IGXSurface *pLPVBlue = m_aLPVs[i].pGIAccumBlue->asRenderTarget(); + if(isFirstRun[i]) + { + IGXSurface *pLPVRed = m_aLPVs[i].pGIAccumRed->asRenderTarget(); + IGXSurface *pLPVGreen = m_aLPVs[i].pGIAccumGreen->asRenderTarget(); + IGXSurface *pLPVBlue = m_aLPVs[i].pGIAccumBlue->asRenderTarget(); - pCtx->setColorTarget(pLPVRed); - pCtx->setColorTarget(pLPVGreen, 1); - pCtx->setColorTarget(pLPVBlue, 2); + pCtx->setColorTarget(pLPVRed); + pCtx->setColorTarget(pLPVGreen, 1); + pCtx->setColorTarget(pLPVBlue, 2); - mem_release(pLPVRed); - mem_release(pLPVGreen); - mem_release(pLPVBlue); + mem_release(pLPVRed); + mem_release(pLPVGreen); + mem_release(pLPVBlue); - pCtx->clear(GX_CLEAR_COLOR); - isFirstRun[i] = false; + pCtx->clear(GX_CLEAR_COLOR); + isFirstRun[i] = false; - pCtx->setColorTarget(NULL); - pCtx->setColorTarget(NULL, 1); - pCtx->setColorTarget(NULL, 2); + pCtx->setColorTarget(NULL); + pCtx->setColorTarget(NULL, 1); + pCtx->setColorTarget(NULL, 2); + + isClean[i] = true; + } } } - SGCore_ShaderUnBind(); mem_release(pOldDSSurface); - //pCtx->setVSConstant(m_pLightingShaderDataVS, 1); - //pCtx->setPSConstant(m_pLightingShaderDataPS, 1); - + if(iCascades) { SGCore_ShaderBind(m_idLPVPropagateShader); UINT uStepCount[] = {4, 6, 8}; @@ -784,6 +785,10 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur //{ for(UINT j = 0; j < 3; ++j) { + if(isClean[j]) + { + continue; + } for(UINT i = 0; i < uStepCount[j]; ++i) { pCtx->setCSTexture(m_aLPVs[j].pGIAccumRed, 0); @@ -830,6 +835,7 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur } + if(iCascades) { pCtx->setColorTarget(pAmbientSurf); //gdata::pDXDevice->setRasterizerState(NULL); @@ -837,13 +843,7 @@ void XMETHODCALLTYPE CLightSystem::renderGI(IGXTexture2D *pLightTotal, IGXTextur pCtx->setBlendState(m_pBlendAlphaOneOne); pCtx->setDepthStencilState(m_pDepthStencilStateLightShadowGlobal); - //pCtx->setPSConstant(m_pLightingShaderDataPS, 1); - - ID idshaderkit = m_idComLightingGI; - - //SGCore_ShaderSetVRF(SHADER_TYPE_PIXEL, idshader, "g_vViewPos", &gdata::vConstCurrCamPos); - - // pCtx->setPSConstant(m_pCameraShaderDataVS, 8); + ID idshaderkit = m_idComLightingGI[iCascades - 1]; SGCore_ShaderBind(idshaderkit); diff --git a/source/light/LightSystem.h b/source/light/LightSystem.h index bc33f45a63f4dc62f22ccbd5c52fbbd332e92924..ce108a9c8084ef90408f83cca7fdfbc9f7ef039b 100644 --- a/source/light/LightSystem.h +++ b/source/light/LightSystem.h @@ -114,7 +114,7 @@ protected: ID m_idComLightingShadow = -1; ID m_idComLightingSpotShadow = -1; ID m_idComLightingPSSMShadow = -1; - ID m_idComLightingGI = -1; + ID m_idComLightingGI[LPV_CASCADES_COUNT]; ID m_idHDRinitLuminance = -1; ID m_idHDRAdaptLuminance = -1; diff --git a/source/light/light.cpp b/source/light/light.cpp index bdf07c8c2a35123cf06f8681a73d64f3a9bb5585..ea4275b635070c1b9a772b486f668254041608f6 100644 --- a/source/light/light.cpp +++ b/source/light/light.cpp @@ -181,11 +181,11 @@ float CXLight::getMaxDistance() return(SMVector3Length2(m_vColor)); } -void CXLight::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) +void CXLight::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) { updateFrustum(); - if(m_pFrustum->boxInFrustum(&vLPVmin, &vLPVmax)) + if(useLPV && m_pFrustum->boxInFrustum(&vLPVmin, &vLPVmax)) { m_renderType |= LRT_LPV; } @@ -250,7 +250,7 @@ void CXLightPoint::updateFrustum() m_pFrustum->update(planes, true); } -void CXLightPoint::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) +void CXLightPoint::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) { m_renderType = LRT_NONE; @@ -260,7 +260,7 @@ void CXLightPoint::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, m_renderType |= LRT_LIGHT; } - CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax); + CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax, useLPV); } //########################################################################## @@ -269,15 +269,33 @@ CXLightSun::CXLightSun(CLightSystem *pLightSystem): CXLight(pLightSystem) { m_type = LIGHT_TYPE_SUN; + + IXRenderPipeline *pPipeline; + Core_GetIXCore()->getRenderPipeline(&pPipeline); + pPipeline->newVisData(&m_pReflectiveVisibility); + pPipeline->newVisData(&m_pTempVisibility); + mem_release(pPipeline); + + m_pReflectiveFrustum = SGCore_CrFrustum(); + + for(UINT i = 0; i < PSSM_MAX_SPLITS; ++i) + { + m_pPSSMFrustum[i] = SGCore_CrFrustum(); + } } -void CXLightSun::Release() +CXLightSun::~CXLightSun() { - --m_uRefCount; - if(!m_uRefCount) + mem_release(m_pReflectiveFrustum); + mem_release(m_pReflectiveVisibility); + mem_release(m_pTempVisibility); + + for(UINT i = 0; i < PSSM_MAX_SPLITS; ++i) { - m_pLightSystem->destroySun(this); + mem_release(m_pPSSMFrustum[i]); } + + m_pLightSystem->destroySun(this); } SMQuaternion CXLightSun::getDirection() @@ -301,6 +319,7 @@ void CXLightSun::updatePSConstants(IGXDevice *pDevice) { m_pPSData = pDevice->createConstantBuffer(sizeof(m_dataPS)); } + m_dataPS.vLightColor = float4(m_vColor, SMVector3Length2(m_vColor)); m_dataPS.vLightPos = float4(m_qDirection * -LIGHTS_DIR_BASE, m_fShadowIntensity); m_pPSData->update(&m_dataPS); @@ -316,19 +335,225 @@ void CXLightSun::setMaxDistance(float fMax) m_fMaxDistance = fMax; } -void CXLightSun::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) +void CXLightSun::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) { m_renderType = LRT_LIGHT | LRT_LPV; -#if 0 - m_renderType = LRT_NONE; - float3 vOrigin = getPosition(); - if(pMainCamera->getFrustum()->sphereInFrustum(&vOrigin, getMaxDistance())) + CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax, useLPV); + + static const int *lpv_cascades_count = GET_PCVAR_INT("lpv_cascades_count"); + + if(lpv_cascades_count > 0) { - m_renderType |= LRT_LIGHT; + m_pReflectiveVisibility->updateForFrustum(m_pReflectiveFrustum); } -#endif - CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax); + + static const int *r_pssm_splits = GET_PCVAR_INT("r_pssm_splits"); + + for(UINT i = 1; i < *r_pssm_splits; ++i) + { + m_pTempVisibility->updateForFrustum(m_pPSSMFrustum[i - 1]); + m_pVisibility->append(m_pTempVisibility); + } +} + +void CXLightSun::updateFrustum() +{ + assert(m_pCamera); + + float3 vLightDir = getDirection() * LIGHTS_DIR_BASE; + float3 vUpDir = getDirection() * float3(1.0f, 0.0f, 0.0f); + + float3 vStart; + m_pCamera->getPosition(&vStart); + float3 vDir; + m_pCamera->getLook(&vDir); + vDir = SMVector3Normalize(vDir); + float3 vRight; + m_pCamera->getRight(&vRight); + float3 vUp; + m_pCamera->getUp(&vUp); + + static const int *r_win_width = GET_PCVAR_INT("r_win_width"); + static const int *r_win_height = GET_PCVAR_INT("r_win_height"); + static const float *r_effective_fov = GET_PCVAR_FLOAT("r_default_fov"); + + float fAspectRatio = (float)*r_win_width / (float)*r_win_height; + float fFovTan = tanf(*r_effective_fov * 0.5f); + + { + static const float *s_pfRPSSMQuality = GET_PCVAR_FLOAT("r_pssm_quality"); + const float fSize = 512.0f * *s_pfRPSSMQuality; + + + + static const float *r_near = GET_PCVAR_FLOAT("r_near"); + static const float *r_far = GET_PCVAR_FLOAT("r_far"); + static const float *r_pssm_max_distance = GET_PCVAR_FLOAT("r_pssm_max_distance"); + + static const int *r_pssm_splits = GET_PCVAR_INT("r_pssm_splits"); + if(*r_pssm_splits < 1) + { + Core_0SetCVarInt("r_pssm_splits", 1); + } + else if(*r_pssm_splits > PSSM_MAX_SPLITS) + { + Core_0SetCVarInt("r_pssm_splits", PSSM_MAX_SPLITS); + } + + float fSplitWeight = 0.8f; + float fShadowDistance = min(*r_pssm_max_distance, *r_far); + + float fMaxDistanceSun = getMaxDistance(); + if(fShadowDistance > fMaxDistanceSun) + { + fShadowDistance = fMaxDistanceSun; + } + + float aSplitDistances[PSSM_MAX_SPLITS]; + for(int i = 0; i < *r_pssm_splits; ++i) + { + float f = (i + 1.0f) / *r_pssm_splits; + float fLogDistance = *r_near * pow(fShadowDistance / *r_near, f); + float fUniformDistance = *r_near + (fShadowDistance - *r_near) * f; + aSplitDistances[i] = lerpf(fUniformDistance, fLogDistance, fSplitWeight); + + if(i == 0) + { + m_splits[i].vNearFar = float2(*r_near, aSplitDistances[i]); + } + else + { + m_splits[i].vNearFar = float2(aSplitDistances[i - 1], aSplitDistances[i]); + } + } + + + + for(int i = 0; i < *r_pssm_splits; ++i) + { + Split &split = m_splits[i]; + + float3 vNearCenter = vStart + vDir * split.vNearFar.x; + float3 vFarCenter = vStart + vDir * split.vNearFar.y; + + float fNearHalfHeight = fFovTan * split.vNearFar.x; + float fFarHalfHeight = fFovTan * split.vNearFar.y; + + float fNearHalfWidth = fNearHalfHeight * fAspectRatio; + float fFarHalfWidth = fFarHalfHeight * fAspectRatio; + + float3 vA = vNearCenter - vUp * fNearHalfHeight + vRight * fNearHalfWidth; + float3 vB = vFarCenter + vUp * fFarHalfHeight - vRight * fFarHalfWidth; + float3 vC = vFarCenter - vUp * fFarHalfHeight + vRight * fFarHalfWidth; + + float3 vCenter = SMTriangleCircumcenter3(vA, vB, vC); + + + float fRadius = SMVector3Length(vCenter - vA); + + SMMATRIX mLight(SMMatrixTranspose(SMMATRIX( + float4(SMVector3Cross(vUpDir, vLightDir)), + float4(vUpDir), + float4(vLightDir), + float4(0.0f, 0.0f, 0.0f, 1.0f) + ))); + SMMATRIX mLightInv = SMMatrixInverse(NULL, mLight); + + vCenter = SMVector3Transform(vCenter, mLight); + float fStep = (fRadius * 2.0f / fSize); + vCenter.x -= fmodf(vCenter.x, fStep); + vCenter.y -= fmodf(vCenter.y, fStep); + + vCenter = SMVector3Transform(vCenter, mLightInv); + + float fMaxDistance = PSSM_LIGHT_FAR; + + split.mProj = SMMatrixOrthographicLH(fRadius * 2.0f, fRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance); + split.mView = SMMatrixLookToLH(vCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir); + + m_mVPs[i] = SMMatrixTranspose(split.mView * split.mProj); + + if(i == 0) + { + m_pFrustum->update(&split.mView, &split.mProj); + } + else + { + m_pPSSMFrustum[i - 1]->update(&split.mView, &split.mProj); + } + } + } + + static const int *lpv_cascades_count = GET_PCVAR_INT("lpv_cascades_count"); + int iCascades = *lpv_cascades_count; + if(iCascades < 0) + { + iCascades = 0; + } + if(iCascades > LPV_CASCADES_COUNT) + { + iCascades = LPV_CASCADES_COUNT; + } + + if(iCascades) + { + static const float *lpv_size_2 = GET_PCVAR_FLOAT("lpv_size_2"); + + float3 vGridCenter = vStart + vDir * (LPV_GRID_SIZE / 2 - LPV_STEP_COUNT) * *lpv_size_2; + //float fGridRadius = sqrtf(16.0f * 16.0f * 3.0f); + float fDim = 16.0f * *lpv_size_2; + float fGridRadius = sqrtf(fDim * fDim * 3.0f); + + + SMMATRIX mLight(SMMatrixTranspose(SMMATRIX( + float4(SMVector3Cross(vUpDir, vLightDir)), + float4(vUpDir), + float4(vLightDir), + float4(0.0f, 0.0f, 0.0f, 1.0f) + ))); + SMMATRIX mLightInv = SMMatrixInverse(NULL, mLight); + + vGridCenter = SMVector3Transform(vGridCenter, mLight); + float fStep = (fGridRadius * 2.0f / (float)RSM_SUN_SIZE); + vGridCenter.x -= fmodf(vGridCenter.x, fStep); + vGridCenter.y -= fmodf(vGridCenter.y, fStep); + + vGridCenter = SMVector3Transform(vGridCenter, mLightInv); + + float fMaxDistance = PSSM_LIGHT_FAR; + + m_mReflectiveProj = SMMatrixOrthographicLH(fGridRadius * 2.0f, fGridRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance); + m_mReflectiveView = SMMatrixLookToLH(vGridCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir); + + m_pReflectiveFrustum->update(&m_mReflectiveView, &m_mReflectiveProj); + } +} + +void CXLightSun::setCamera(ICamera *pCamera) +{ + m_pCamera = pCamera; +} + +const SMMATRIX* CXLightSun::getPSSMVPs() const +{ + return(m_mVPs); +} + +const CXLightSun::Split* CXLightSun::getPSSMsplits() const +{ + return(m_splits); +} + +IXRenderableVisibility* CXLightSun::getReflectiveVisibility() +{ + return(m_pReflectiveVisibility); +} + +void CXLightSun::getReflectiveVP(SMMATRIX *pView, SMMATRIX *pProj) const +{ + *pView = m_mReflectiveView; + *pProj = m_mReflectiveProj; } //########################################################################## @@ -425,7 +650,7 @@ void CXLightSpot::updateFrustum() m_pFrustum->update(&mView, &mProj); } -void CXLightSpot::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) +void CXLightSpot::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) { m_renderType = LRT_NONE; @@ -436,5 +661,5 @@ void CXLightSpot::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, m_renderType |= LRT_LIGHT; } - CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax); + CXLight::updateVisibility(pMainCamera, vLPVmin, vLPVmax, useLPV); } diff --git a/source/light/light.h b/source/light/light.h index c5952cd50daac142300b905c56bf552722b27206..b67b0c18b011b1268bfc6f4f9df94425e67e64dd 100644 --- a/source/light/light.h +++ b/source/light/light.h @@ -19,6 +19,10 @@ See the license in LICENSE #include "IXLight.h" +#define PSSM_MAX_SPLITS 6 +#define PSSM_LIGHT_NEAR 0.1f +#define PSSM_LIGHT_FAR 5000.0f + class CLightSystem; class CXLight: public virtual IXLight { @@ -52,7 +56,7 @@ public: float getMaxDistance(); - virtual void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax); + virtual void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV); IXRenderableVisibility *getVisibility() override; LIGHT_RENDER_TYPE getRenderType() { @@ -126,7 +130,7 @@ public: void updateFrustum() override; - void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) override; + void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) override; protected: void updatePSConstants(IGXDevice *pDevice); @@ -140,7 +144,7 @@ public: SX_ALIGNED_OP_MEM2(); CXLightSun(CLightSystem *pLightSystem); - void XMETHODCALLTYPE Release(); + ~CXLightSun(); SMQuaternion getDirection(); void setDirection(const SMQuaternion &qDirection); @@ -148,7 +152,27 @@ public: float getMaxDistance(); void setMaxDistance(float fMax); - void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) override; + void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) override; + + void updateFrustum() override; + + void setCamera(ICamera *pCamera); + + const SMMATRIX* getPSSMVPs() const; + void getReflectiveVP(SMMATRIX *pView, SMMATRIX *pProj) const; + + IXRenderableVisibility* getReflectiveVisibility(); + + struct Split + { + SX_ALIGNED_OP_MEM2(); + + float2 vNearFar; + float4x4 mView; + float4x4 mProj; + }; + + const Split* getPSSMsplits() const; protected: void updatePSConstants(IGXDevice *pDevice); @@ -157,6 +181,19 @@ protected: SMQuaternion m_qDirection; float m_fMaxDistance = 1000.0f; + + ICamera *m_pCamera = NULL; + + Split m_splits[PSSM_MAX_SPLITS]; + + SMMATRIX m_mVPs[PSSM_MAX_SPLITS]; + SMMATRIX m_mReflectiveView; + SMMATRIX m_mReflectiveProj; + + IFrustum *m_pPSSMFrustum[PSSM_MAX_SPLITS - 1]; + IFrustum *m_pReflectiveFrustum = NULL; + IXRenderableVisibility *m_pReflectiveVisibility = NULL; + IXRenderableVisibility *m_pTempVisibility = NULL; }; class CXLightSpot: public CXLight, public virtual IXLightSpot @@ -174,7 +211,7 @@ public: SMMATRIX getWorldTM(); - void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax) override; + void updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) override; protected: void updatePSConstants(IGXDevice *pDevice); void updateFrustum() override; diff --git a/source/light/shadow.cpp b/source/light/shadow.cpp index e15b175b7c05f0fee1de189cd3a02630870e89cb..20bdaa8384f038e453bc3c049c4e0d9c7598c432 100644 --- a/source/light/shadow.cpp +++ b/source/light/shadow.cpp @@ -547,7 +547,7 @@ void CShadowPSSM::init(IGXDevice *pContext, UINT uSize) m_pShaderDataPS = m_pDevice->createConstantBuffer(sizeof(m_shaderData.ps)); - m_pShaderDataGS = m_pDevice->createConstantBuffer(sizeof(m_shaderData.gs)); + m_pShaderDataGS = m_pDevice->createConstantBuffer(sizeof(SMMATRIX) * PSSM_MAX_SPLITS); m_pCameraShaderDataVS = m_pDevice->createConstantBuffer(sizeof(m_cameraShaderData.vs)); } @@ -602,7 +602,7 @@ void CShadowPSSM::process(IXRenderPipeline *pRenderPipeline) mem_release(pLightConstants); pRenderPipeline->renderShadows(); - pRenderPipeline->renderStage(XRS_SHADOWS, NULL); // m_pLight->getVisibility()); + pRenderPipeline->renderStage(XRS_SHADOWS, m_pLight->getVisibility()); pCtx->setColorTarget(NULL); @@ -612,122 +612,11 @@ void CShadowPSSM::process(IXRenderPipeline *pRenderPipeline) }*/ } -#define PSSM_LIGHT_NEAR 0.1f -#define PSSM_LIGHT_FAR 5000.0f - void CShadowPSSM::updateFrustums() { - assert(m_pCamera); - CXLightSun *pSunLight = (CXLightSun*)m_pLight; - float3 vLightDir = pSunLight->getDirection() * LIGHTS_DIR_BASE; - float3 vUpDir = pSunLight->getDirection() * float3(1.0f, 0.0f, 0.0f); - - static const float *r_near = GET_PCVAR_FLOAT("r_near"); - static const float *r_far = GET_PCVAR_FLOAT("r_far"); - static const float *r_pssm_max_distance = GET_PCVAR_FLOAT("r_pssm_max_distance"); - static const int *r_win_width = GET_PCVAR_INT("r_win_width"); - static const int *r_win_height = GET_PCVAR_INT("r_win_height"); - static const float *r_effective_fov = GET_PCVAR_FLOAT("r_default_fov"); - static const int *r_pssm_splits = GET_PCVAR_INT("r_pssm_splits"); - if(*r_pssm_splits < 1) - { - Core_0SetCVarInt("r_pssm_splits", 1); - } - else if(*r_pssm_splits > PSSM_MAX_SPLITS) - { - Core_0SetCVarInt("r_pssm_splits", PSSM_MAX_SPLITS); - } - - float fSplitWeight = 0.8f; - float fShadowDistance = min(*r_pssm_max_distance, *r_far); - - float fMaxDistanceSun = pSunLight->getMaxDistance(); - if(fShadowDistance > fMaxDistanceSun) - { - fShadowDistance = fMaxDistanceSun; - } - - float aSplitDistances[PSSM_MAX_SPLITS]; - for(int i = 0; i < *r_pssm_splits; ++i) - { - float f = (i + 1.0f) / *r_pssm_splits; - float fLogDistance = *r_near * pow(fShadowDistance / *r_near, f); - float fUniformDistance = *r_near + (fShadowDistance - *r_near) * f; - aSplitDistances[i] = lerpf(fUniformDistance, fLogDistance, fSplitWeight); - - if(i == 0) - { - m_splits[i].vNearFar = float2(*r_near, aSplitDistances[i]); - } - else - { - m_splits[i].vNearFar = float2(aSplitDistances[i - 1], aSplitDistances[i]); - } - } - - - float3 vStart; - m_pCamera->getPosition(&vStart); - float3 vDir; - m_pCamera->getLook(&vDir); - vDir = SMVector3Normalize(vDir); - float3 vRight; - m_pCamera->getRight(&vRight); - float3 vUp; - m_pCamera->getUp(&vUp); - float fAspectRatio = (float)*r_win_width / (float)*r_win_height; - float fFovTan = tanf(*r_effective_fov * 0.5f); - for(int i = 0; i < *r_pssm_splits; ++i) - { - Split &split = m_splits[i]; - - float3 vNearCenter = vStart + vDir * split.vNearFar.x; - float3 vFarCenter = vStart + vDir * split.vNearFar.y; - - float fNearHalfHeight = fFovTan * split.vNearFar.x; - float fFarHalfHeight = fFovTan * split.vNearFar.y; - - float fNearHalfWidth = fNearHalfHeight * fAspectRatio; - float fFarHalfWidth = fFarHalfHeight * fAspectRatio; - - float3 vA = vNearCenter - vUp * fNearHalfHeight + vRight * fNearHalfWidth; - float3 vB = vFarCenter + vUp * fFarHalfHeight - vRight * fFarHalfWidth; - float3 vC = vFarCenter - vUp * fFarHalfHeight + vRight * fFarHalfWidth; - - float3 vCenter = SMTriangleCircumcenter3(vA, vB, vC); - - - float fRadius = SMVector3Length(vCenter - vA); - //float fRadius1 = SMVector3Length(vCenter - vB); - //float fRadius2 = SMVector3Length(vCenter - vC); - - // vCenter.mmv = _mm_round_ps(vCenter, _MM_ROUND_NEAREST); - - SMMATRIX mLight(SMMatrixTranspose(SMMATRIX( - float4(SMVector3Cross(vUpDir, vLightDir)), - float4(vUpDir), - float4(vLightDir), - float4(0.0f, 0.0f, 0.0f, 1.0f) - ))); - SMMATRIX mLightInv = SMMatrixInverse(NULL, mLight); - - vCenter = SMVector3Transform(vCenter, mLight); - float fStep = (fRadius * 2.0f / m_fSize); - vCenter.x -= fmodf(vCenter.x, fStep); - vCenter.y -= fmodf(vCenter.y, fStep); - - vCenter = SMVector3Transform(vCenter, mLightInv); - - float fMaxDistance = PSSM_LIGHT_FAR; - - split.mProj = SMMatrixOrthographicLH(fRadius * 2.0f, fRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance); - split.mView = SMMatrixLookToLH(vCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir); - - m_shaderData.gs.mVP[i] = SMMatrixTranspose(split.mView * split.mProj); - } - m_pShaderDataGS->update(&m_shaderData.gs); + m_pShaderDataGS->update(pSunLight->getPSSMVPs()); } void CShadowPSSM::genShadow(IGXTexture2D *pGBufferDepth, IGXTexture2D *pGBufferNormals) @@ -741,6 +630,8 @@ void CShadowPSSM::genShadow(IGXTexture2D *pGBufferDepth, IGXTexture2D *pGBufferN // static const float *r_near = GET_PCVAR_FLOAT("r_near"); // static const float *r_far = GET_PCVAR_FLOAT("r_far"); + CXLightSun *pSunLight = (CXLightSun*)m_pLight; + IGXContext *pCtx = m_pDevice->getThreadContext(); // const float c_fTexWidth = (float)pShadowMap->getWidth(); @@ -764,12 +655,14 @@ void CShadowPSSM::genShadow(IGXTexture2D *pGBufferDepth, IGXTexture2D *pGBufferN //pCtx->setPSTexture(ms_pRandomTexture, 2); pCtx->setPSTexture(pGBufferNormals, 3); + const CXLightSun::Split *pSplits = pSunLight->getPSSMsplits(); + SMMATRIX tmp = SMMatrixTranspose(m_mScaleBiasMat); for(int i = 0; i < PSSM_MAX_SPLITS; ++i) { //m_shaderData.ps.mMatrixTextureV[i] = tmp * m_shaderData.gs.mVP[i]; - m_shaderData.ps.mMatrixTextureV[i] = SMMatrixTranspose(m_splits[i].mView); - m_shaderData.ps.mMatrixTextureP[i] = SMMatrixTranspose(m_splits[i].mProj * m_mScaleBiasMat); + m_shaderData.ps.mMatrixTextureV[i] = SMMatrixTranspose(pSplits[i].mView); + m_shaderData.ps.mMatrixTextureP[i] = SMMatrixTranspose(pSplits[i].mProj * m_mScaleBiasMat); } //m_shaderData.ps.vPixelMapSizeBias = float3(m_fBlurPixel / m_fSize, m_fSize, m_fBias); m_shaderData.ps.vSizeBoundNearFar = float4(m_fSize, PSSM_LIGHT_NEAR * tanf(0.001f), PSSM_LIGHT_NEAR, PSSM_LIGHT_FAR); @@ -937,61 +830,27 @@ void CReflectiveShadowSun::process(IXRenderPipeline *pRenderPipeline) //m_pLight->setPSConstants(m_pDevice, 5); pRenderPipeline->renderShadows(); - pRenderPipeline->renderStage(XRS_SHADOWS, NULL); // m_pLight->getVisibility()); + pRenderPipeline->renderStage(XRS_SHADOWS, ((CXLightSun*)m_pLight)->getReflectiveVisibility()); pCtx->setColorTarget(NULL); pCtx->setColorTarget(NULL, 1); pCtx->setColorTarget(NULL, 2); + /* if(GetAsyncKeyState('U') < 0) { m_pDevice->saveTextureToFile("sm_depth.dds", m_pDepthMap); m_pDevice->saveTextureToFile("sm_normal.dds", m_pNormalMap); m_pDevice->saveTextureToFile("sm_flux.dds", m_pFluxMap); } + */ } void CReflectiveShadowSun::updateFrustum() { - assert(m_pCamera); - - CXLightSun *pSunLight = (CXLightSun*)m_pLight; - float3 vLightDir = pSunLight->getDirection() * LIGHTS_DIR_BASE; - float3 vUpDir = pSunLight->getDirection() * float3(1.0f, 0.0f, 0.0f); - - float3 vStart; - m_pCamera->getPosition(&vStart); - float3 vDir; - m_pCamera->getLook(&vDir); - vDir = SMVector3Normalize(vDir); - - //! @todo: fix grid center pos! - float3 vGridCenter = vStart; - //float fGridRadius = sqrtf(16.0f * 16.0f * 3.0f); - float fGridRadius = sqrtf(64.0f * 64.0f * 3.0f); - - SMMATRIX mLight(SMMatrixTranspose(SMMATRIX( - float4(SMVector3Cross(vUpDir, vLightDir)), - float4(vUpDir), - float4(vLightDir), - float4(0.0f, 0.0f, 0.0f, 1.0f) - ))); - SMMATRIX mLightInv = SMMatrixInverse(NULL, mLight); - - vGridCenter = SMVector3Transform(vGridCenter, mLight); - float fStep = (fGridRadius * 2.0f / m_fSize); - vGridCenter.x -= fmodf(vGridCenter.x, fStep); - vGridCenter.y -= fmodf(vGridCenter.y, fStep); - - vGridCenter = SMVector3Transform(vGridCenter, mLightInv); - - float fMaxDistance = PSSM_LIGHT_FAR; - - m_mProj = SMMatrixOrthographicLH(fGridRadius * 2.0f, fGridRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance); - m_mView = SMMatrixLookToLH(vGridCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir); + ((CXLightSun*)m_pLight)->getReflectiveVP(&m_mView, &m_mProj); } - void CReflectiveShadowSun::genLPV(bool isDebug) { if(!m_pDevice || !(m_pLight->getRenderType() & LRT_LPV)) diff --git a/source/light/shadow.h b/source/light/shadow.h index 8c6411b2cf207fbfe8f5bba5f2bfcf4795be7d07..dd2850b062c22ecec635547d3810f209b182270e 100644 --- a/source/light/shadow.h +++ b/source/light/shadow.h @@ -182,7 +182,6 @@ private: //########################################################################## -#define PSSM_MAX_SPLITS 6 class CShadowPSSM: public IBaseShadowMap { public: @@ -215,6 +214,7 @@ private: IGXTextureCube *m_pDepthMap = NULL; +#if 0 struct Split { SX_ALIGNED_OP_MEM2(); @@ -224,6 +224,7 @@ private: float4x4 mProj; }; Split m_splits[PSSM_MAX_SPLITS]; +#endif float4x4 m_mScaleBiasMat; float m_fBias = 0.0001f; @@ -235,10 +236,6 @@ private: struct { - struct - { - SMMATRIX mVP[PSSM_MAX_SPLITS]; - } gs; struct { SMMATRIX mMatrixTextureV[PSSM_MAX_SPLITS]; diff --git a/source/render/RenderableVisibility.cpp b/source/render/RenderableVisibility.cpp index 5238e9dc5f72bdadad5235d5873bc8b9d5ceb543..c4dbf10e7ec169fc43804b175424efa13ca18fc1 100644 --- a/source/render/RenderableVisibility.cpp +++ b/source/render/RenderableVisibility.cpp @@ -17,7 +17,7 @@ CRenderableVisibility::~CRenderableVisibility() mem_delete_a(m_ppVisibilities); } -ID CRenderableVisibility::getPluginId() +ID CRenderableVisibility::getPluginId() const { return(m_idPlugin); } @@ -76,6 +76,13 @@ IXRenderableVisibility *CRenderableVisibility::getVisibility(ID id) return(m_ppVisibilities[id]); } +const IXRenderableVisibility *CRenderableVisibility::getVisibility(ID id) const +{ + assert(ID_VALID(id) && (UINT)id < m_uRenderSystems); + + return(m_ppVisibilities[id]); +} + void CRenderableVisibility::setVisibility(ID id, IXRenderableVisibility *pVisibility) { assert(ID_VALID(id) && (UINT)id < m_uRenderSystems); @@ -89,3 +96,31 @@ void CRenderableVisibility::setVisibility(ID id, IXRenderableVisibility *pVisibi pVisibility->AddRef(); } } + +void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) +{ + assert(pOther_->getPluginId() == getPluginId()); + const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; + + for(UINT i = 0; i < m_uRenderSystems; ++i) + { + if(m_ppVisibilities[i]) + { + m_ppVisibilities[i]->append(pOther->getVisibility(i)); + } + } +} + +void CRenderableVisibility::substract(const IXRenderableVisibility *pOther_) +{ + assert(pOther_->getPluginId() == getPluginId()); + const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; + + for(UINT i = 0; i < m_uRenderSystems; ++i) + { + if(m_ppVisibilities[i]) + { + m_ppVisibilities[i]->substract(pOther->getVisibility(i)); + } + } +} diff --git a/source/render/RenderableVisibility.h b/source/render/RenderableVisibility.h index 7da8d03dd6b1d128b681e0928afb965be03459e7..8dc72ff4983d10a975f32734cd5a44bda7553f2f 100644 --- a/source/render/RenderableVisibility.h +++ b/source/render/RenderableVisibility.h @@ -9,17 +9,22 @@ public: CRenderableVisibility(ID idPlugin, UINT uRenderSystems); ~CRenderableVisibility(); - ID getPluginId(); + ID getPluginId() const override; - void setOcclusionCuller(IXOcclusionCuller *pOcclusionCuller); + void setOcclusionCuller(IXOcclusionCuller *pOcclusionCuller) override; - void updateForCamera(ICamera *pCamera, const IXRenderableVisibility *pReference = NULL); + void updateForCamera(ICamera *pCamera, const IXRenderableVisibility *pReference = NULL) override; - void updateForFrustum(const IFrustum *pFrustum, const IXRenderableVisibility *pReference = NULL); + void updateForFrustum(const IFrustum *pFrustum, const IXRenderableVisibility *pReference = NULL) override; IXRenderableVisibility *getVisibility(ID id); + const IXRenderableVisibility *getVisibility(ID id) const; void setVisibility(ID id, IXRenderableVisibility *pVisibility); + void append(const IXRenderableVisibility *pOther) override; + + void substract(const IXRenderableVisibility *pOther) override; + protected: IXRenderableVisibility **m_ppVisibilities; UINT m_uRenderSystems; diff --git a/source/xcommon/IXRenderable.h b/source/xcommon/IXRenderable.h index b1938bb1cf56e59f951701ed4cde64f036a22494..eea46c646f954de194b4e0351e5cd1120ea2672d 100644 --- a/source/xcommon/IXRenderable.h +++ b/source/xcommon/IXRenderable.h @@ -21,7 +21,7 @@ class IFrustum; class IXRenderableVisibility: public IXUnknown { public: - virtual ID getPluginId() = 0; + virtual ID getPluginId() const = 0; //! Установка отсекателя по перекрытию virtual void setOcclusionCuller(IXOcclusionCuller *pOcclusionCuller) = 0; @@ -36,6 +36,12 @@ public: Возвращает ID задачи из менеджера задач для отслеживания завершения внутренних задач */ // virtual ID updateForCameraThreaded(ICamera *pCamera) = 0; + + //! Добввление к текущему набору видимости другого набора + virtual void append(const IXRenderableVisibility *pOther) = 0; + + //! Вычитание из текущего набора видимости другого набора + virtual void substract(const IXRenderableVisibility *pOther) = 0; }; struct XTransparentObject