From 15687609e42e8252e2b9ccaf0f9bcbe0749aba67 Mon Sep 17 00:00:00 2001 From: ducphamhong Date: Thu, 16 Jan 2020 23:07:24 +0700 Subject: [PATCH] feat: #47 Implement MRTT Deferred Rendering --- Assets/BuiltIn/Shader/Basic/TextureColor.xml | 2 +- .../Deferred/GLSL/SpecularGlossinessVS.glsl | 2 +- .../Deferred/HLSL/SpecularGlossinessVS.hlsl | 2 +- Projects/Demo/Source/Context/CContext.cpp | 2 +- Projects/Demo/Source/View/CViewDemo.cpp | 4 +- Projects/Demo/Source/View/CViewInit.cpp | 15 ++- .../Engine/Source/Material/CMaterial.cpp | 4 + .../Engine/Source/Material/Shader/CShader.cpp | 1 + .../Engine/Source/RenderPipeline/CBaseRP.cpp | 126 +++++++++++++++++- .../Engine/Source/RenderPipeline/CBaseRP.h | 22 ++- .../Source/RenderPipeline/CDeferredRP.cpp | 76 ++++++++++- .../Source/RenderPipeline/CDeferredRP.h | 16 ++- .../Source/RenderPipeline/CForwardRP.cpp | 4 +- .../Engine/Source/RenderPipeline/CForwardRP.h | 2 +- .../Source/RenderPipeline/IRenderPipeline.h | 6 +- 15 files changed, 264 insertions(+), 20 deletions(-) diff --git a/Assets/BuiltIn/Shader/Basic/TextureColor.xml b/Assets/BuiltIn/Shader/Basic/TextureColor.xml index 9c371b39f..f7fd941e7 100644 --- a/Assets/BuiltIn/Shader/Basic/TextureColor.xml +++ b/Assets/BuiltIn/Shader/Basic/TextureColor.xml @@ -9,7 +9,7 @@ - + diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/GLSL/SpecularGlossinessVS.glsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/GLSL/SpecularGlossinessVS.glsl index 1fe186c65..11498bc54 100644 --- a/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/GLSL/SpecularGlossinessVS.glsl +++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/GLSL/SpecularGlossinessVS.glsl @@ -29,7 +29,7 @@ void main(void) vWorldTangent = normalize(worldTangent.xyz); vWorldBinormal = cross(vWorldNormal.xyz, vWorldTangent.xyz); - vTexCoord0 = inTexCoord0 * uUVScale.xy + uUVScale.zw; + vTexCoord0 = inTexCoord0;// * uUVScale.xy + uUVScale.zw; vTangentW = inTangentW.x; gl_Position = uMvpMatrix * inPosition; diff --git a/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/HLSL/SpecularGlossinessVS.hlsl b/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/HLSL/SpecularGlossinessVS.hlsl index fc887bda7..919044c3e 100644 --- a/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/HLSL/SpecularGlossinessVS.hlsl +++ b/Assets/BuiltIn/Shader/SpecularGlossiness/Deferred/HLSL/SpecularGlossinessVS.hlsl @@ -31,7 +31,7 @@ VS_OUTPUT main(VS_INPUT input) { VS_OUTPUT output; output.pos = mul(input.pos, uMvpMatrix); - output.tex0 = input.tex0 * uUVScale.xy + uUVScale.zw; + output.tex0 = input.tex0;// * uUVScale.xy + uUVScale.zw; output.tangentw = input.tangentw.x; float4 worldPos = mul(input.pos, uWorldMatrix); diff --git a/Projects/Demo/Source/Context/CContext.cpp b/Projects/Demo/Source/Context/CContext.cpp index a8260cedb..ec5a7b235 100644 --- a/Projects/Demo/Source/Context/CContext.cpp +++ b/Projects/Demo/Source/Context/CContext.cpp @@ -35,7 +35,7 @@ void CContext::releaseScene() CBaseRP* CContext::initRenderPipeline(int w, int h) { - m_rendering = new CForwardRP(); + m_rendering = new CDeferredRP(); m_rendering->initRender(w, h); return m_rendering; } diff --git a/Projects/Demo/Source/View/CViewDemo.cpp b/Projects/Demo/Source/View/CViewDemo.cpp index 6788a82ed..c39e2e3f1 100644 --- a/Projects/Demo/Source/View/CViewDemo.cpp +++ b/Projects/Demo/Source/View/CViewDemo.cpp @@ -26,7 +26,7 @@ void CViewDemo::onDestroy() void CViewDemo::onUpdate() { CContext *context = CContext::getInstance(); - CScene *scene = context->getScene(); + CScene *scene = context->getScene(); if (scene != NULL) scene->update(); } @@ -40,6 +40,6 @@ void CViewDemo::onRender() if (camera != NULL && scene != NULL) { - context->getRenderPipeline()->render(camera, scene->getEntityManager()); + context->getRenderPipeline()->render(NULL, camera, scene->getEntityManager()); } } \ No newline at end of file diff --git a/Projects/Demo/Source/View/CViewInit.cpp b/Projects/Demo/Source/View/CViewInit.cpp index 20ccfcf7d..e476264f7 100644 --- a/Projects/Demo/Source/View/CViewInit.cpp +++ b/Projects/Demo/Source/View/CViewInit.cpp @@ -48,7 +48,9 @@ void CViewInit::onInit() { getApplication()->getFileSystem()->addFileArchive(getBuiltInPath("BuiltIn.zip"), false, false); - CShaderManager::getInstance()->initBasicShader(); + CShaderManager *shaderMgr = CShaderManager::getInstance(); + shaderMgr->initBasicShader(); + shaderMgr->loadShader("BuiltIn/Shader/SpecularGlossiness/Deferred/SpecularGlossiness.xml"); } void CViewInit::initScene() @@ -87,11 +89,16 @@ void CViewInit::initScene() textureFolders.push_back("Demo/Sponza/Textures"); // load model - prefab = meshManager->loadModel("Demo/Sponza/Sponza.dae", NULL, false); + prefab = meshManager->loadModel("Demo/Sponza/Sponza.dae", NULL, true); if (prefab != NULL) { // export model material ArrayMaterial& materials = CMaterialManager::getInstance()->loadMaterial("Demo/Sponza/Sponza.xml", true, textureFolders); + for (CMaterial *&material : materials) + { + material->changeShader("BuiltIn/Shader/SpecularGlossiness/Deferred/SpecularGlossiness.xml"); + material->autoDetectLoadTexture(); + } // create render mesh object CGameObject *sponza = zone->createEmptyObject(); @@ -190,8 +197,8 @@ void CViewInit::onUpdate() // retry download delete m_getFile; m_getFile = NULL; - } -} + } + } #else #if defined(WINDOWS_STORE) diff --git a/Projects/Skylicht/Engine/Source/Material/CMaterial.cpp b/Projects/Skylicht/Engine/Source/Material/CMaterial.cpp index dd4ce18be..db9427a0c 100644 --- a/Projects/Skylicht/Engine/Source/Material/CMaterial.cpp +++ b/Projects/Skylicht/Engine/Source/Material/CMaterial.cpp @@ -1017,6 +1017,10 @@ namespace Skylicht { t->Path = uniform->Path; t->Texture = uniform->Texture; + + if (t->Texture == NULL) + t->Texture = CTextureManager::getInstance()->getTexture(t->Path.c_str()); + break; } } diff --git a/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp b/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp index 336c947d5..78bbd5700 100644 --- a/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp +++ b/Projects/Skylicht/Engine/Source/Material/Shader/CShader.cpp @@ -957,6 +957,7 @@ namespace Skylicht break; case CShader::NODE_PARAM: { + } break; case CShader::SHADER_VEC2: diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.cpp b/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.cpp index e73f3efab..d3b6ce2c7 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.cpp +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.cpp @@ -27,21 +27,141 @@ This file is part of the "Skylicht Engine". namespace Skylicht { - CBaseRP::CBaseRP() + CBaseRP::CBaseRP() : + m_next(NULL) { + const core::dimension2du &size = getVideoDriver()->getCurrentRenderTargetSize(); + m_viewport2DW = (float)size.Width; + m_viewport2DH = (float)size.Height; + m_drawBuffer = new scene::CMeshBuffer(getVideoDriver()->getVertexDescriptor(video::EVT_2TCOORDS), video::EIT_16BIT); + m_drawBuffer->setHardwareMappingHint(EHM_STREAM); + + m_verticesImage = m_drawBuffer->getVertexBuffer(); + m_indicesImage = m_drawBuffer->getIndexBuffer(); + + // init index + m_indicesImage->set_used(6); + u16 *index = (u16*)m_indicesImage->getIndices(); + index[0] = 0; + index[1] = 1; + index[2] = 2; + index[3] = 0; + index[4] = 2; + index[5] = 3; } CBaseRP::~CBaseRP() { - + m_drawBuffer->drop(); + m_verticesImage = NULL; + m_indicesImage = NULL; } void CBaseRP::setCamera(CCamera *camera) { - const SViewFrustum& viewArea = camera->getViewFrustum(); + const SViewFrustum& viewArea = camera->getViewFrustum(); video::IVideoDriver* driver = getVideoDriver(); driver->setTransform(video::ETS_PROJECTION, viewArea.getTransform(video::ETS_PROJECTION)); driver->setTransform(video::ETS_VIEW, viewArea.getTransform(video::ETS_VIEW)); } + + void CBaseRP::setNextPipeLine(IRenderPipeline *next) + { + m_next = next; + } + + void CBaseRP::onNext(ITexture *target, CCamera *camera, CEntityManager* entity) + { + if (m_next != NULL) + m_next->render(target, camera, entity); + } + + void CBaseRP::beginRender2D(float w, float h) + { + core::matrix4 orthoMatrix; + orthoMatrix.makeIdentity(); + orthoMatrix.buildProjectionMatrixOrthoLH(w, -h, -1.0f, 1.0f); + orthoMatrix.setTranslation(core::vector3df(-1, 1, 0)); + + IVideoDriver *driver = getVideoDriver(); + + driver->setTransform(video::ETS_PROJECTION, orthoMatrix); + driver->setTransform(video::ETS_VIEW, core::IdentityMatrix); + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + + m_viewport2DW = w; + m_viewport2DH = h; + } + + void CBaseRP::renderBufferToTarget(float sx, float sy, float sw, float sh, SMaterial& material, bool flipY, bool flipX) + { + ITexture *tex = material.getTexture(0); + if (tex == NULL) + return; + + IVideoDriver *driver = getVideoDriver(); + + int numVerticesUse = 4; + + m_verticesImage->set_used(numVerticesUse); + S3DVertex2TCoords *vertices = (S3DVertex2TCoords*)m_verticesImage->getVertices(); + SColor color(255, 255, 255, 255); + + float x = 0; + float y = 0; + float w = m_viewport2DW; + float h = m_viewport2DH; + + float texW = (float)tex->getSize().Width; + float texH = (float)tex->getSize().Height; + + const f32 invW = 1.f / static_cast(texW); + const f32 invH = 1.f / static_cast(texH); + + float tx1 = sx * invW; + float ty1 = sy * invH; + float tw1 = tx1 + sw * invW; + float th1 = ty1 + sh * invH; + + float tx2 = 0.0f; + float ty2 = 0.0f; + float tw2 = 1.0f; + float th2 = 1.0f; + + if (driver->getDriverType() != EDT_DIRECT3D11) + { + if (flipY) + { + ty1 = 1.0f - ty1; + th1 = 1.0f - th1; + + ty2 = 1.0f - ty2; + th2 = 1.0f - th2; + } + + if (flipX) + { + tx1 = 1.0f - tx1; + tw1 = 1.0f - tw1; + + tx2 = 1.0f - tx2; + tw2 = 1.0f - tw2; + } + } + + // add vertices + vertices[0] = S3DVertex2TCoords(x, y, 0.0f, 0.0f, 0.0f, 1.0f, color, tx1, ty1, tx2, ty2); + vertices[1] = S3DVertex2TCoords(x + w, y, 0.0f, 0.0f, 0.0f, 1.0f, color, tw1, ty1, tw2, ty2); + vertices[2] = S3DVertex2TCoords(x + w, y + h, 0.0f, 0.0f, 0.0f, 1.0f, color, tw1, th1, tw2, th2); + vertices[3] = S3DVertex2TCoords(x, y + h, 0.0f, 0.0f, 0.0f, 1.0f, color, tx1, th1, tx2, th2); + + // no depth test + material.ZBuffer = video::ECFN_DISABLED; + material.ZWriteEnable = false; + + // draw buffer + driver->setMaterial(material); + driver->drawMeshBuffer(m_drawBuffer); + } } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.h b/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.h index 96c06b0f8..14b88b463 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.h +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CBaseRP.h @@ -30,13 +30,33 @@ namespace Skylicht { class CBaseRP : public IRenderPipeline { + protected: + IRenderPipeline *m_next; + + CMeshBuffer *m_drawBuffer; + IVertexBuffer* m_verticesImage; + IIndexBuffer* m_indicesImage; + + float m_viewport2DW; + float m_viewport2DH; + public: CBaseRP(); virtual ~CBaseRP(); - virtual void render(CCamera *camera, CEntityManager *entityManager) = 0; + virtual void render(ITexture *target, CCamera *camera, CEntityManager *entityManager) = 0; virtual void setCamera(CCamera *camera); + + virtual void setNextPipeLine(IRenderPipeline *next); + + virtual void onNext(ITexture *target, CCamera *camera, CEntityManager* entity); + + public: + + void beginRender2D(float w, float h); + + void renderBufferToTarget(float sx, float sy, float sw, float sh, SMaterial& material, bool flipY = true, bool flipX = false); }; } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp index 8f8baa7d3..f474f2e86 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.cpp @@ -24,32 +24,104 @@ This file is part of the "Skylicht Engine". #include "pch.h" #include "CDeferredRP.h" +#include "Material/Shader/CShaderManager.h" namespace Skylicht { - CDeferredRP::CDeferredRP() + CDeferredRP::CDeferredRP() : + m_albedo(NULL), + m_position(NULL), + m_normal(NULL), + m_data(NULL) { } CDeferredRP::~CDeferredRP() { + IVideoDriver *driver = getVideoDriver(); + + if (m_albedo != NULL) + driver->removeTexture(m_albedo); + + if (m_position != NULL) + driver->removeTexture(m_position); + + if (m_normal != NULL) + driver->removeTexture(m_normal); + + if (m_data != NULL) + driver->removeTexture(m_data); + + m_multiRenderTarget.clear(); } void CDeferredRP::initRender(int w, int h) { + IVideoDriver *driver = getVideoDriver(); + + // init render target + m_size = core::dimension2du((u32)w, (u32)h); + m_albedo = driver->addRenderTargetTexture(m_size, "albedo", ECF_A8R8G8B8); + m_position = driver->addRenderTargetTexture(m_size, "position", ECF_A32B32G32R32F); + m_normal = driver->addRenderTargetTexture(m_size, "normal", ECF_A32B32G32R32F); + m_data = driver->addRenderTargetTexture(m_size, "data", ECF_A8R8G8B8); + + // setup multi render target + m_multiRenderTarget.push_back(m_albedo); + m_multiRenderTarget.push_back(m_position); + m_multiRenderTarget.push_back(m_normal); + m_multiRenderTarget.push_back(m_data); + + // setup material + m_material.MaterialType = CShaderManager::getInstance()->getShaderIDByName("TextureColor"); + m_material.setTexture(0, m_albedo); + m_material.setTexture(1, m_position); + m_material.setTexture(2, m_normal); + m_material.setTexture(3, m_data); + + // turn off mipmap on float texture + m_material.TextureLayer[1].BilinearFilter = false; + m_material.TextureLayer[1].TrilinearFilter = false; + m_material.TextureLayer[1].AnisotropicFilter = 0; + + m_material.TextureLayer[2].BilinearFilter = false; + m_material.TextureLayer[2].TrilinearFilter = false; + m_material.TextureLayer[2].AnisotropicFilter = 0; + + // disable Z + m_material.ZBuffer = video::ECFN_DISABLED; + m_material.ZWriteEnable = false; } - void CDeferredRP::render(CCamera *camera, CEntityManager *entityManager) + void CDeferredRP::render(ITexture *target, CCamera *camera, CEntityManager *entityManager) { if (camera == NULL) return; + // set multi rtt + IVideoDriver *driver = getVideoDriver(); + driver->setRenderTarget(m_multiRenderTarget); + + // draw entity to buffer setCamera(camera); entityManager->setCamera(camera); entityManager->update(); entityManager->render(); + + // save camera transform + m_projectionMatrix = driver->getTransform(video::ETS_PROJECTION); + m_viewMatrix = driver->getTransform(video::ETS_VIEW); + + // render to screen + float renderW = (float)m_size.Width; + float renderH = (float)m_size.Height; + + driver->setRenderTarget(target, true, false); + + beginRender2D(renderW, renderH); + renderBufferToTarget(0.0f, 0.0f, renderW, renderH, m_material); } } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.h b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.h index cbb522399..b4b1548c8 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.h +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CDeferredRP.h @@ -30,6 +30,20 @@ namespace Skylicht { class CDeferredRP : public CBaseRP { + protected: + ITexture *m_albedo; + ITexture *m_position; + ITexture *m_normal; + ITexture *m_data; + + core::dimension2du m_size; + + core::array m_multiRenderTarget; + + core::matrix4 m_viewMatrix; + core::matrix4 m_projectionMatrix; + + SMaterial m_material; public: CDeferredRP(); @@ -37,6 +51,6 @@ namespace Skylicht virtual void initRender(int w, int h); - virtual void render(CCamera *camera, CEntityManager *entityManager); + virtual void render(ITexture *target, CCamera *camera, CEntityManager *entityManager); }; } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.cpp b/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.cpp index f63dde75b..a8e3b52ab 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.cpp +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.cpp @@ -42,11 +42,13 @@ namespace Skylicht } - void CForwardRP::render(CCamera *camera, CEntityManager *entityManager) + void CForwardRP::render(ITexture *target, CCamera *camera, CEntityManager *entityManager) { if (camera == NULL) return; + getVideoDriver()->setRenderTarget(target, true, false); + setCamera(camera); entityManager->setCamera(camera); entityManager->update(); diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.h b/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.h index ca369dde2..31553f6cb 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.h +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/CForwardRP.h @@ -37,6 +37,6 @@ namespace Skylicht virtual void initRender(int w, int h); - virtual void render(CCamera *camera, CEntityManager *entityManager); + virtual void render(ITexture *target, CCamera *camera, CEntityManager *entityManager); }; } \ No newline at end of file diff --git a/Projects/Skylicht/Engine/Source/RenderPipeline/IRenderPipeline.h b/Projects/Skylicht/Engine/Source/RenderPipeline/IRenderPipeline.h index 1a7264277..70e0a3349 100644 --- a/Projects/Skylicht/Engine/Source/RenderPipeline/IRenderPipeline.h +++ b/Projects/Skylicht/Engine/Source/RenderPipeline/IRenderPipeline.h @@ -44,8 +44,12 @@ namespace Skylicht virtual void initRender(int w, int h) = 0; - virtual void render(CCamera *camera, CEntityManager* entity) = 0; + virtual void render(ITexture *target, CCamera *camera, CEntityManager* entity) = 0; virtual void setCamera(CCamera *camera) = 0; + + virtual void setNextPipeLine(IRenderPipeline *next) = 0; + + virtual void onNext(ITexture *target, CCamera *camera, CEntityManager* entity) = 0; }; } \ No newline at end of file