From e430ca5fd6e9ff1a44a8eafdf5d8cc821cc3d6d9 Mon Sep 17 00:00:00 2001 From: D-AIRY <admin@ds-servers.com> Date: Thu, 30 Apr 2020 12:34:29 +0300 Subject: [PATCH] Emissive materials --- build/engine/shaders/default/default.ps | 11 +++-- source/anim/DynamicModel.cpp | 10 ++++- source/anim/DynamicModel.h | 2 + source/anim/DynamicModelProvider.cpp | 34 +++++++++++++++ source/anim/DynamicModelProvider.h | 2 + source/anim/DynamicModelShared.cpp | 57 +++++++++++++++++++++++-- source/anim/DynamicModelShared.h | 5 ++- source/anim/Renderable.cpp | 3 +- source/anim/RenderableVisibility.cpp | 1 + source/anim/RenderableVisibility.h | 1 + source/game/GameData.cpp | 2 +- source/mtrl/IXMaterial.h | 3 ++ source/mtrl/MaterialSystem.cpp | 12 ++++++ source/mtrl/MaterialSystem.h | 4 ++ source/render/RenderPipeline.cpp | 10 ++++- source/xcommon/XEvents.h | 1 + 16 files changed, 145 insertions(+), 13 deletions(-) diff --git a/build/engine/shaders/default/default.ps b/build/engine/shaders/default/default.ps index 420e1d047..0d851c06e 100644 --- a/build/engine/shaders/default/default.ps +++ b/build/engine/shaders/default/default.ps @@ -47,13 +47,15 @@ XMaterial MainGBuffer(PSI_XMaterial IN) XMaterial MainIllimination(PSI_XMaterial IN) { XMaterial OUT = XMATERIAL_LOAD_DEFAULTS(); +#ifdef HAS_EMISSION +#ifdef HAS_EMISSIVE_MAP + float4 fColor = g_txEmissive.Sample(g_sScene, IN.vTexUV); +#else float4 fColor = g_txBase.Sample(g_sScene, IN.vTexUV); - // float4 fColor = IN.vPos; -#ifdef HAS_ALPHATEST - clip(fColor.a - g_xMaterialConstants.pbr_alphatest_threshold); #endif - OUT.vEmissiveColor = fColor.xyz; + + OUT.vEmissiveColor = fColor.xyz * fColor.w * g_xMaterialConstants.em_multiplier; #ifdef HAS_NORMALMAP OUT.vNormal = MixNormalMicro(IN.vNormal, @@ -63,6 +65,7 @@ XMaterial MainIllimination(PSI_XMaterial IN) OUT.vNormal = IN.vNormal; #endif +#endif return(OUT); } diff --git a/source/anim/DynamicModel.cpp b/source/anim/DynamicModel.cpp index 2819bd742..31bd43fd0 100644 --- a/source/anim/DynamicModel.cpp +++ b/source/anim/DynamicModel.cpp @@ -208,6 +208,10 @@ const IXResourceModel * XMETHODCALLTYPE CDynamicModel::getResource(UINT uIndex) } void XMETHODCALLTYPE CDynamicModel::render(UINT uLod, bool isTransparent) +{ + render(uLod, isTransparent, false); +} +void CDynamicModel::render(UINT uLod, bool isTransparent, bool isEmissiveOnly) { if(!m_pDevice || !m_isEnabled || !m_pWorldBuffer) { @@ -223,7 +227,7 @@ void XMETHODCALLTYPE CDynamicModel::render(UINT uLod, bool isTransparent) m_pProvider->bindVertexFormat(); m_pDevice->getThreadContext()->setVSConstant(m_pWorldBuffer, 1 /* SCR_OBJECT */); - m_pShared->render(m_uSkin, uLod, m_vColor, isTransparent); + m_pShared->render(m_uSkin, uLod, m_vColor, isTransparent, isEmissiveOnly); } CDynamicModelShared* CDynamicModel::getShared() @@ -251,6 +255,10 @@ bool CDynamicModel::hasTransparentSubsets(UINT uLod) const { return(m_pShared->hasTransparentSubsets(m_uSkin, uLod)); } +bool CDynamicModel::hasEmissiveSubsets(UINT uLod) const +{ + return(m_pShared->hasEmissiveSubsets(m_uSkin, uLod)); +} IXMaterial* CDynamicModel::getTransparentMaterial(UINT uLod) { diff --git a/source/anim/DynamicModel.h b/source/anim/DynamicModel.h index 51b829412..2c2f2b56f 100644 --- a/source/anim/DynamicModel.h +++ b/source/anim/DynamicModel.h @@ -41,6 +41,7 @@ public: const IXResourceModel* XMETHODCALLTYPE getResource(UINT uIndex = 0) override; void XMETHODCALLTYPE render(UINT uLod, bool isTransparent) override; + void render(UINT uLod, bool isTransparent, bool isEmissiveOnly); CDynamicModelShared* getShared(); void initGPUresources(); @@ -48,6 +49,7 @@ public: UINT getPSPcount(UINT uLod) const; SMPLANE getPSP(UINT uLod, UINT uPlane) const; bool hasTransparentSubsets(UINT uLod) const; + bool hasEmissiveSubsets(UINT uLod) const; IXMaterial* getTransparentMaterial(UINT uLod); protected: CDynamicModelProvider *m_pProvider; diff --git a/source/anim/DynamicModelProvider.cpp b/source/anim/DynamicModelProvider.cpp index e83f4bf87..64a948497 100644 --- a/source/anim/DynamicModelProvider.cpp +++ b/source/anim/DynamicModelProvider.cpp @@ -23,6 +23,10 @@ void CMaterialChangedEventListener::onEvent(const XEventMaterialChanged *pData) { m_pProvider->onMaterialTransparencyChanged(pData->pMaterial); } + if(pData->type == XEventMaterialChanged::TYPE_EMISSIVITY) + { + m_pProvider->onMaterialEmissivityChanged(pData->pMaterial); + } } /* //########################################################################## @@ -113,6 +117,7 @@ public: if(pItem->isVisible) { + pItem->isEmissive = pMdl->hasEmissiveSubsets(pItem->uLod); pItem->isTransparent = pMdl->hasTransparentSubsets(pItem->uLod); if(pItem->isTransparent) { @@ -347,6 +352,23 @@ void CDynamicModelProvider::render(bool isTransparent, CRenderableVisibility *pV m_pMaterialSystem->bindVS(NULL); } +void CDynamicModelProvider::renderEmissive(CRenderableVisibility *pVisibility) +{ + bindVertexFormat(); + for(UINT i = 0, l = m_apModels.size(); i < l; ++i) + { + auto pItem = pVisibility->getItemDynamic(i); + if(pItem->isVisible) + { + if(pItem->isEmissive) + { + m_apModels[i]->render(pItem->uLod, pItem->isTransparent, pItem->isEmissive); + } + } + } + m_pMaterialSystem->bindVS(NULL); +} + void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference) { pVisibility->setItemCountDynamic(m_apModels.size()); @@ -370,6 +392,7 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera if(pItem->isVisible) { pItem->isTransparent = pMdl->hasTransparentSubsets(pItem->uLod); + pItem->isEmissive = pMdl->hasEmissiveSubsets(pItem->uLod); if(pItem->isTransparent) { IXMaterial *pMaterial = pMdl->getTransparentMaterial(pItem->uLod); @@ -475,6 +498,17 @@ void CDynamicModelProvider::onMaterialTransparencyChanged(const IXMaterial *pMat } } +void CDynamicModelProvider::onMaterialEmissivityChanged(const IXMaterial *pMaterial) +{ + for(auto i = m_mModels.begin(); i; i++) + { + if(*i.second) + { + (*i.second)->onMaterialEmissivityChanged(pMaterial); + } + } +} + UINT CDynamicModelProvider::getTransparentCount(CRenderableVisibility *pVisibility) { return(pVisibility->getItemTransparentDynamicCount()); diff --git a/source/anim/DynamicModelProvider.h b/source/anim/DynamicModelProvider.h index 7aab732a1..b83dab01e 100644 --- a/source/anim/DynamicModelProvider.h +++ b/source/anim/DynamicModelProvider.h @@ -41,6 +41,7 @@ public: IGXVertexDeclaration *getVertexDeclaration(); void render(bool isTransparent, CRenderableVisibility *pVisibility = NULL); + void renderEmissive(CRenderableVisibility *pVisibility); void computeVisibility(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference=NULL); void getLevelSize(const XEventLevelSize *pData); @@ -58,6 +59,7 @@ public: void bindVertexFormat(); protected: + void onMaterialEmissivityChanged(const IXMaterial *pMaterial); void onMaterialTransparencyChanged(const IXMaterial *pMaterial); CMaterialChangedEventListener *m_pMaterialChangedEventListener; diff --git a/source/anim/DynamicModelShared.cpp b/source/anim/DynamicModelShared.cpp index 0d549a0f3..0b1a2acb7 100644 --- a/source/anim/DynamicModelShared.cpp +++ b/source/anim/DynamicModelShared.cpp @@ -24,6 +24,7 @@ CDynamicModelShared::~CDynamicModelShared() m_pppMaterials = NULL; mem_delete_a(m_isTransparent); + mem_delete_a(m_isEmissive); if(m_pDevice) { @@ -76,6 +77,7 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) m_uSkinCount = pResource->getSkinCount(); m_isTransparent = new bool[m_uSkinCount]; + m_isEmissive = new bool[m_uSkinCount]; m_ppMaterialsBlob = new void*[m_uMaterialCount * m_uSkinCount + m_uSkinCount]; m_pppMaterials = (IXMaterial***)m_ppMaterialsBlob; @@ -85,6 +87,7 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) { m_pppMaterials[i] = (IXMaterial**)(m_ppMaterialsBlob + m_uSkinCount + m_uMaterialCount * i); bool isTransparent = false; + bool isEmissive = false; for(UINT j = 0; j < m_uMaterialCount; ++j) { @@ -103,13 +106,21 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) m_pppMaterials[i][j]->AddRef(); } - if(m_pppMaterials[i][j] && m_pppMaterials[i][j]->isTransparent()) + if(m_pppMaterials[i][j]) { - isTransparent = true; + if(m_pppMaterials[i][j]->isTransparent()) + { + isTransparent = true; + } + if(m_pppMaterials[i][j]->isEmissive()) + { + isEmissive = true; + } } } m_isTransparent[i] = isTransparent; + m_isEmissive[i] = isEmissive; } } @@ -262,6 +273,24 @@ void CDynamicModelShared::onMaterialTransparencyChanged(const IXMaterial *pMater } } +void CDynamicModelShared::onMaterialEmissivityChanged(const IXMaterial *pMaterial) +{ + for(UINT i = 0; i < m_uSkinCount; ++i) + { + bool isEmissive = false; + + for(UINT j = 0; j < m_uMaterialCount; ++j) + { + if(m_pppMaterials[i][j] && m_pppMaterials[i][j]->isEmissive()) + { + isEmissive = true; + } + } + + m_isEmissive[i] = isEmissive; + } +} + void CDynamicModelShared::initGPUresources() { if(!m_ppTempIndices) @@ -317,7 +346,7 @@ float3 CDynamicModelShared::getLocalBoundMax() const return(m_vLocalMax); } -void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent) +void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent, bool isEmissiveOnly) { if(!m_pDevice) { @@ -334,6 +363,11 @@ void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, return; } + if(isEmissiveOnly && !hasEmissiveSubsets(uSkin, uLod)) + { + return; + } + if(uLod >= m_aLods.size()) { return; @@ -366,7 +400,10 @@ void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, { pSubset = &m_aLods[uLod][i]; - if(pSubset->uIndexCount != 0 && m_pppMaterials[uSkin][i] && ((!m_pppMaterials[uSkin][i] && !isTransparent) || m_pppMaterials[uSkin][i]->isTransparent() == isTransparent)) + if(pSubset->uIndexCount != 0 && m_pppMaterials[uSkin][i] + && (m_pppMaterials[uSkin][i]->isTransparent() == isTransparent) + && (!isEmissiveOnly || m_pppMaterials[uSkin][i]->isEmissive()) + ) { m_pMaterialSystem->bindMaterial(m_pppMaterials[uSkin][i]); @@ -397,6 +434,18 @@ bool CDynamicModelShared::hasTransparentSubsets(UINT uSkin, UINT uLod) return(m_isTransparent[uSkin]); } +bool CDynamicModelShared::hasEmissiveSubsets(UINT uSkin, UINT uLod) +{ + assert(uSkin < m_uSkinCount); + if(uSkin >= m_uSkinCount) + { + return(false); + } + //! @todo add uLod support + + return(m_isEmissive[uSkin]); +} + IXMaterial* CDynamicModelShared::getTransparentMaterial(UINT uSkin, UINT uLod) { assert(uSkin < m_uSkinCount); diff --git a/source/anim/DynamicModelShared.h b/source/anim/DynamicModelShared.h index a6177296d..0f2a5c1d0 100644 --- a/source/anim/DynamicModelShared.h +++ b/source/anim/DynamicModelShared.h @@ -26,15 +26,17 @@ public: float3 getLocalBoundMin() const; float3 getLocalBoundMax() const; - void render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent); + void render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent, bool isEmissiveOnly = false); void initGPUresources(); bool isReady() const; bool hasTransparentSubsets(UINT uSkin, UINT uLod); + bool hasEmissiveSubsets(UINT uSkin, UINT uLod); IXMaterial* getTransparentMaterial(UINT uSkin, UINT uLod); void onMaterialTransparencyChanged(const IXMaterial *pMaterial); + void onMaterialEmissivityChanged(const IXMaterial *pMaterial); float3 getTransparentBoundMin(UINT uSkin, UINT uLod) const; float3 getTransparentBoundMax(UINT uSkin, UINT uLod) const; @@ -64,6 +66,7 @@ protected: UINT m_uMaterialCount = 0; UINT m_uSkinCount = 0; bool *m_isTransparent = NULL; //!< По количеству скинов, истина если есть прозрачные материалы в любом сабсете + bool *m_isEmissive = NULL; //!< По количеству скинов, истина если есть светящиеся материалы в любом сабсете XPT_TOPOLOGY m_topology = XPT_TRIANGLELIST; diff --git a/source/anim/Renderable.cpp b/source/anim/Renderable.cpp index 37eb7b005..d3a492191 100644 --- a/source/anim/Renderable.cpp +++ b/source/anim/Renderable.cpp @@ -10,7 +10,7 @@ CRenderable::CRenderable(ID idPlugin, CAnimatedModelProvider *pProviderAnimated, X_RENDER_STAGE XMETHODCALLTYPE CRenderable::getStages() { - return(XRS_GBUFFER | XRS_SHADOWS | XRS_EDITOR_2D | XRS_TRANSPARENT); + return(XRS_GBUFFER | XRS_SHADOWS | XRS_EDITOR_2D | XRS_TRANSPARENT | XRS_GI); } UINT XMETHODCALLTYPE CRenderable::getPriorityForStage(X_RENDER_STAGE stage) @@ -41,6 +41,7 @@ void XMETHODCALLTYPE CRenderable::renderStage(X_RENDER_STAGE stage, IXRenderable m_pDynamicModelProvider->render(false, pVis); break; case XRS_GI: + m_pDynamicModelProvider->renderEmissive(pVis); break; case XRS_POSTPROCESS_MAIN: break; diff --git a/source/anim/RenderableVisibility.cpp b/source/anim/RenderableVisibility.cpp index 7f15e413e..2d8182f91 100644 --- a/source/anim/RenderableVisibility.cpp +++ b/source/anim/RenderableVisibility.cpp @@ -61,6 +61,7 @@ void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) else { pItem->isTransparent = pOtherItem->isTransparent; + pItem->isEmissive = pOtherItem->isEmissive; pItem->isVisible = true; pItem->uLod = pOtherItem->uLod; } diff --git a/source/anim/RenderableVisibility.h b/source/anim/RenderableVisibility.h index d0d4112e1..737b25166 100644 --- a/source/anim/RenderableVisibility.h +++ b/source/anim/RenderableVisibility.h @@ -28,6 +28,7 @@ public: bool isVisible = false; UINT uLod = 0; bool isTransparent = false; + bool isEmissive = false; }; struct TransparentModel diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp index ea289172e..a3f420e14 100644 --- a/source/game/GameData.cpp +++ b/source/game/GameData.cpp @@ -441,7 +441,7 @@ GameData::GameData(HWND hWnd, bool isGame): m_pLightSystem = (IXLightSystem*)Core_GetIXCore()->getPluginManager()->getInterface(IXLIGHTSYSTEM_GUID); - if(m_pLightSystem) + if(m_pLightSystem && false) { // 252, 212, 64 IXLightSun *pSun = m_pLightSystem->newSun(); diff --git a/source/mtrl/IXMaterial.h b/source/mtrl/IXMaterial.h index c843d48bc..e908ab004 100644 --- a/source/mtrl/IXMaterial.h +++ b/source/mtrl/IXMaterial.h @@ -112,6 +112,9 @@ public: virtual const char* XMETHODCALLTYPE getName() const = 0; virtual bool XMETHODCALLTYPE save() = 0; + + virtual void XMETHODCALLTYPE setEmissive(bool bValue) = 0; + virtual bool XMETHODCALLTYPE isEmissive() const = 0; }; #endif diff --git a/source/mtrl/MaterialSystem.cpp b/source/mtrl/MaterialSystem.cpp index b81431c1a..1a2f5a5a2 100644 --- a/source/mtrl/MaterialSystem.cpp +++ b/source/mtrl/MaterialSystem.cpp @@ -2197,6 +2197,7 @@ CMaterial::CMaterial(CMaterialSystem *pMaterialSystem, const char *szName): m_pTransparent = createFlag("transparent", XEventMaterialChanged::TYPE_TRANSPARENCY); m_pRefractive = createFlag("refractive", XEventMaterialChanged::TYPE_REFRACTIVITY); m_pBlurred = createFlag("blurred", XEventMaterialChanged::TYPE_BLURRED); + m_pEmissive = createFlag("emissive", XEventMaterialChanged::TYPE_EMISSIVITY); setShader("Default"); } @@ -2249,6 +2250,17 @@ bool XMETHODCALLTYPE CMaterial::isRefractive() const return(m_pRefractive->get()); } +void XMETHODCALLTYPE CMaterial::setEmissive(bool bValue) +{ + m_pEmissive->set(bValue); + + notifyChanged(XEventMaterialChanged::TYPE_EMISSIVITY); +} +bool XMETHODCALLTYPE CMaterial::isEmissive() const +{ + return(m_pEmissive->get()); +} + void XMETHODCALLTYPE CMaterial::setBlurred(bool bValue) { m_pBlurred->set(bValue); diff --git a/source/mtrl/MaterialSystem.h b/source/mtrl/MaterialSystem.h index 0eedd9341..860873670 100644 --- a/source/mtrl/MaterialSystem.h +++ b/source/mtrl/MaterialSystem.h @@ -150,6 +150,9 @@ public: void XMETHODCALLTYPE setBlurred(bool bValue) override; bool XMETHODCALLTYPE isBlurred() const override; + void XMETHODCALLTYPE setEmissive(bool bValue) override; + bool XMETHODCALLTYPE isEmissive() const override; + void XMETHODCALLTYPE setShader(const char *szShader) override; const char* XMETHODCALLTYPE getShader() const override; XMaterialShaderHandler* XMETHODCALLTYPE getShaderHandler() const override; @@ -280,6 +283,7 @@ private: CMaterialFlag *m_pTransparent = NULL; CMaterialFlag *m_pRefractive = NULL; CMaterialFlag *m_pBlurred = NULL; + CMaterialFlag *m_pEmissive = NULL; }; class CMaterialSystem: public IXMaterialSystem diff --git a/source/render/RenderPipeline.cpp b/source/render/RenderPipeline.cpp index e5efd5784..5e1e33b6f 100644 --- a/source/render/RenderPipeline.cpp +++ b/source/render/RenderPipeline.cpp @@ -268,6 +268,12 @@ CRenderPipeline::CRenderPipeline(IGXDevice *pDevice): XMATERIAL_PARAM_GROUP(NULL, "HAS_ALPHATEST"), XMATERIAL_PARAM_RANGE("Alphatest threshold", "pbr_alphatest_threshold", 0.0f, 1.0f, 0.8f), XMATERIAL_PARAM_GROUP_END(), + + XMATERIAL_PARAM_FLAG("Emissive", "emissive", "HAS_EMISSION"), + XMATERIAL_PARAM_GROUP(NULL, "HAS_EMISSION"), + XMATERIAL_PARAM_TEXTURE_OPT("Emissive map", "txEmissive", "HAS_EMISSIVE_MAP"), + XMATERIAL_PARAM_RANGE("Emissive multiplier", "em_multiplier", 0.0f, 1000.0f, 16.0f), + XMATERIAL_PARAM_GROUP_END(), XMATERIAL_PROPERTY_LIST_END() }; @@ -881,9 +887,11 @@ void CRenderPipeline::renderShadows() } void CRenderPipeline::renderGI() { + IGXContext *pCtx = m_pDevice->getThreadContext(); rfunc::SetRenderSceneFilter(); m_pMaterialSystem->bindRenderPass(m_pRenderPassIllumination); - renderStage(XRS_GI); + //pCtx->setDepthStencilState(gdata::rstates::pDepthStencilStateNoZ); + renderStage(XRS_GI, m_pMainCameraVisibility); } void CRenderPipeline::renderPostprocessMain() { diff --git a/source/xcommon/XEvents.h b/source/xcommon/XEvents.h index 727c9f767..a3fbfc39d 100644 --- a/source/xcommon/XEvents.h +++ b/source/xcommon/XEvents.h @@ -177,6 +177,7 @@ struct XEventMaterialChanged TYPE_PROPERTY, TYPE_FLAG, TYPE_SHADER, + TYPE_EMISSIVITY, // ... } type; IXMaterial *pMaterial; -- GitLab