|
|
@@ -36,14 +36,13 @@
|
|
|
#include "BsSkybox.h"
|
|
|
#include "BsShadowRendering.h"
|
|
|
#include "BsStandardDeferredLighting.h"
|
|
|
+#include "BsGlobalMaterials.h"
|
|
|
+#include "BsRenderCompositor.h"
|
|
|
|
|
|
using namespace std::placeholders;
|
|
|
|
|
|
namespace bs { namespace ct
|
|
|
{
|
|
|
- // Limited by max number of array elements in texture for DX11 hardware
|
|
|
- constexpr UINT32 MaxReflectionCubemaps = 2048 / 6;
|
|
|
-
|
|
|
RenderBeast::RenderBeast()
|
|
|
{
|
|
|
mOptions = bs_shared_ptr_new<RenderBeastOptions>();
|
|
|
@@ -73,27 +72,29 @@ namespace bs { namespace ct
|
|
|
void RenderBeast::initializeCore()
|
|
|
{
|
|
|
RendererUtility::startUp();
|
|
|
+ GpuResourcePool::startUp();
|
|
|
|
|
|
mCoreOptions = bs_shared_ptr_new<RenderBeastOptions>();
|
|
|
mScene = bs_shared_ptr_new<RendererScene>(mCoreOptions);
|
|
|
mObjectRenderer = bs_new<ObjectRenderer>();
|
|
|
|
|
|
- mSkyboxMat = bs_new<SkyboxMat<false>>();
|
|
|
- mSkyboxSolidColorMat = bs_new<SkyboxMat<true>>();
|
|
|
- mFlatFramebufferToTextureMat = bs_new<FlatFramebufferToTextureMat>();
|
|
|
-
|
|
|
- mTiledDeferredLightingMats = bs_new<TiledDeferredLightingMaterials>();
|
|
|
- mTileDeferredImageBasedLightingMats = bs_new<TiledDeferredImageBasedLightingMaterials>();
|
|
|
-
|
|
|
- mPreintegratedEnvBRDF = TiledDeferredImageBasedLighting::generatePreintegratedEnvBRDF();
|
|
|
- mVisibleLightInfo = bs_new<VisibleLightData>();
|
|
|
- mVisibleReflProbeInfo = bs_new<VisibleReflProbeData>();
|
|
|
- mLightGrid = bs_new<LightGrid>();
|
|
|
+ mMainViewGroup = bs_new<RendererViewGroup>();
|
|
|
|
|
|
- GpuResourcePool::startUp();
|
|
|
PostProcessing::startUp();
|
|
|
- ShadowRendering::startUp(mCoreOptions->shadowMapSize);
|
|
|
StandardDeferred::startUp();
|
|
|
+ GlobalMaterials::startUp();
|
|
|
+
|
|
|
+ RenderCompositor::registerNodeType<RCNodeSceneDepth>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeGBuffer>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeLightAccumulation>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeSceneColor>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeStandardDeferredLighting>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeTiledDeferredLighting>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeTiledDeferredIBL>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeUnflattenLightAccum>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeFinalResolve>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeSkybox>();
|
|
|
+ RenderCompositor::registerNodeType<RCNodeUnflattenSceneColor>();
|
|
|
}
|
|
|
|
|
|
void RenderBeast::destroyCore()
|
|
|
@@ -103,27 +104,15 @@ namespace bs { namespace ct
|
|
|
|
|
|
mScene = nullptr;
|
|
|
|
|
|
- mReflCubemapArrayTex = nullptr;
|
|
|
- mSkyboxTexture = nullptr;
|
|
|
- mSkyboxFilteredReflections = nullptr;
|
|
|
- mSkyboxIrradiance = nullptr;
|
|
|
+ RenderCompositor::cleanUp();
|
|
|
|
|
|
+ GlobalMaterials::shutDown();
|
|
|
StandardDeferred::shutDown();
|
|
|
- ShadowRendering::shutDown();
|
|
|
PostProcessing::shutDown();
|
|
|
- GpuResourcePool::shutDown();
|
|
|
|
|
|
- bs_delete(mSkyboxMat);
|
|
|
- bs_delete(mSkyboxSolidColorMat);
|
|
|
- bs_delete(mVisibleLightInfo);
|
|
|
- bs_delete(mVisibleReflProbeInfo);
|
|
|
- bs_delete(mLightGrid);
|
|
|
- bs_delete(mFlatFramebufferToTextureMat);
|
|
|
- bs_delete(mTiledDeferredLightingMats);
|
|
|
- bs_delete(mTileDeferredImageBasedLightingMats);
|
|
|
-
|
|
|
- mPreintegratedEnvBRDF = nullptr;
|
|
|
+ bs_delete(mMainViewGroup);
|
|
|
|
|
|
+ GpuResourcePool::shutDown();
|
|
|
RendererUtility::shutDown();
|
|
|
}
|
|
|
|
|
|
@@ -181,36 +170,6 @@ namespace bs { namespace ct
|
|
|
void RenderBeast::notifyReflectionProbeAdded(ReflectionProbe* probe)
|
|
|
{
|
|
|
mScene->registerReflectionProbe(probe);
|
|
|
-
|
|
|
- // Find a spot in cubemap array
|
|
|
- const SceneInfo& sceneInfo = mScene->getSceneInfo();
|
|
|
-
|
|
|
- UINT32 probeId = probe->getRendererId();
|
|
|
- const RendererReflectionProbe* probeInfo = &sceneInfo.reflProbes[probeId];
|
|
|
-
|
|
|
- UINT32 numArrayEntries = (UINT32)mCubemapArrayUsedSlots.size();
|
|
|
- for(UINT32 i = 0; i < numArrayEntries; i++)
|
|
|
- {
|
|
|
- if(!mCubemapArrayUsedSlots[i])
|
|
|
- {
|
|
|
- mScene->setReflectionProbeArrayIndex(probeId, i, false);
|
|
|
- mCubemapArrayUsedSlots[i] = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // No empty slot was found
|
|
|
- if (probeInfo->arrayIdx == -1)
|
|
|
- {
|
|
|
- mScene->setReflectionProbeArrayIndex(probeId, numArrayEntries, false);
|
|
|
- mCubemapArrayUsedSlots.push_back(true);
|
|
|
- }
|
|
|
-
|
|
|
- if(probeInfo->arrayIdx > MaxReflectionCubemaps)
|
|
|
- {
|
|
|
- LOGERR("Reached the maximum number of allowed reflection probe cubemaps at once. "
|
|
|
- "Ignoring reflection probe data.");
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
void RenderBeast::notifyReflectionProbeUpdated(ReflectionProbe* probe)
|
|
|
@@ -220,14 +179,6 @@ namespace bs { namespace ct
|
|
|
|
|
|
void RenderBeast::notifyReflectionProbeRemoved(ReflectionProbe* probe)
|
|
|
{
|
|
|
- const SceneInfo& sceneInfo = mScene->getSceneInfo();
|
|
|
-
|
|
|
- UINT32 probeId = probe->getRendererId();
|
|
|
- UINT32 arrayIdx = sceneInfo.reflProbes[probeId].arrayIdx;
|
|
|
-
|
|
|
- if (arrayIdx != -1)
|
|
|
- mCubemapArrayUsedSlots[arrayIdx] = false;
|
|
|
-
|
|
|
mScene->unregisterReflectionProbe(probe);
|
|
|
}
|
|
|
|
|
|
@@ -248,34 +199,17 @@ namespace bs { namespace ct
|
|
|
|
|
|
void RenderBeast::notifySkyboxAdded(Skybox* skybox)
|
|
|
{
|
|
|
- mSkybox = skybox;
|
|
|
-
|
|
|
- SPtr<Texture> skyTex = skybox->getTexture();
|
|
|
- if (skyTex != nullptr && skyTex->getProperties().getTextureType() == TEX_TYPE_CUBE_MAP)
|
|
|
- mSkyboxTexture = skyTex;
|
|
|
-
|
|
|
- mSkyboxFilteredReflections = nullptr;
|
|
|
- mSkyboxIrradiance = nullptr;
|
|
|
+ mScene->registerSkybox(skybox);
|
|
|
}
|
|
|
|
|
|
void RenderBeast::notifySkyboxTextureChanged(Skybox* skybox)
|
|
|
{
|
|
|
- LightProbeCache::instance().notifyDirty(skybox->getUUID());
|
|
|
-
|
|
|
- if (mSkybox == skybox)
|
|
|
- {
|
|
|
- mSkyboxTexture = skybox->getTexture();
|
|
|
- mSkyboxFilteredReflections = nullptr;
|
|
|
- mSkyboxIrradiance = nullptr;
|
|
|
- }
|
|
|
+ mScene->updateSkybox(skybox);
|
|
|
}
|
|
|
|
|
|
void RenderBeast::notifySkyboxRemoved(Skybox* skybox)
|
|
|
{
|
|
|
- LightProbeCache::instance().unloadCachedTexture(skybox->getUUID());
|
|
|
-
|
|
|
- if (mSkybox == skybox)
|
|
|
- mSkyboxTexture = nullptr;
|
|
|
+ mScene->unregisterSkybox(skybox);
|
|
|
}
|
|
|
|
|
|
SPtr<PostProcessSettings> RenderBeast::createPostProcessSettings() const
|
|
|
@@ -306,7 +240,9 @@ namespace bs { namespace ct
|
|
|
*mCoreOptions = options;
|
|
|
|
|
|
mScene->setOptions(mCoreOptions);
|
|
|
- ShadowRendering::instance().setShadowMapSize(mCoreOptions->shadowMapSize);
|
|
|
+
|
|
|
+ ShadowRendering& shadowRenderer = mMainViewGroup->getShadowRenderer();
|
|
|
+ shadowRenderer.setShadowMapSize(mCoreOptions->shadowMapSize);
|
|
|
}
|
|
|
|
|
|
void RenderBeast::renderAll()
|
|
|
@@ -365,17 +301,19 @@ namespace bs { namespace ct
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- mMainViewGroup.setViews(views.data(), (UINT32)views.size());
|
|
|
- mMainViewGroup.determineVisibility(sceneInfo);
|
|
|
+ mMainViewGroup->setViews(views.data(), (UINT32)views.size());
|
|
|
+ mMainViewGroup->determineVisibility(sceneInfo);
|
|
|
|
|
|
// Render shadow maps
|
|
|
- ShadowRendering::instance().renderShadowMaps(*mScene, mMainViewGroup, frameInfo);
|
|
|
+ ShadowRendering& shadowRenderer = mMainViewGroup->getShadowRenderer();
|
|
|
+ shadowRenderer.renderShadowMaps(*mScene, *mMainViewGroup, frameInfo);
|
|
|
|
|
|
- // Update reflection probes
|
|
|
- updateLightProbes(frameInfo);
|
|
|
+ // Update reflection probe and skybox textures, if required
|
|
|
+ renderReflectionProbes(frameInfo);
|
|
|
+ updateSkybox();
|
|
|
|
|
|
// Render everything
|
|
|
- renderViews(mMainViewGroup, frameInfo);
|
|
|
+ renderViews(*mMainViewGroup, frameInfo);
|
|
|
|
|
|
gProfilerGPU().endFrame();
|
|
|
|
|
|
@@ -394,16 +332,6 @@ namespace bs { namespace ct
|
|
|
const SceneInfo& sceneInfo = mScene->getSceneInfo();
|
|
|
const VisibilityInfo& visibility = viewGroup.getVisibilityInfo();
|
|
|
|
|
|
- // Note: I'm determining light and refl. probe visibility for the entire group. It might be more performance
|
|
|
- // efficient to do it per view. Additionally I'm using a single GPU buffer to hold their information, which is
|
|
|
- // then updated when each view group is rendered. It might be better to keep one buffer reserved per-view.
|
|
|
-
|
|
|
- // Update GPU light data
|
|
|
- mVisibleLightInfo->update(sceneInfo, viewGroup);
|
|
|
-
|
|
|
- // Update reflection probe data
|
|
|
- mVisibleReflProbeInfo->update(sceneInfo, viewGroup);
|
|
|
-
|
|
|
// Update various buffers required by each renderable
|
|
|
UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
|
|
|
for (UINT32 i = 0; i < numRenderables; i++)
|
|
|
@@ -422,11 +350,11 @@ namespace bs { namespace ct
|
|
|
if (view->getProperties().isOverlay)
|
|
|
renderOverlay(view);
|
|
|
else
|
|
|
- renderView(view, frameInfo.timeDelta);
|
|
|
+ renderView(viewGroup, view, frameInfo.timeDelta);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void RenderBeast::renderView(RendererView* viewInfo, float frameDelta)
|
|
|
+ void RenderBeast::renderView(const RendererViewGroup& viewGroup, RendererView* viewInfo, float frameDelta)
|
|
|
{
|
|
|
gProfilerCPU().beginSample("Render");
|
|
|
|
|
|
@@ -452,34 +380,27 @@ namespace bs { namespace ct
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- viewInfo->beginFrame(true);
|
|
|
+ viewInfo->beginFrame();
|
|
|
+
|
|
|
+ const VisibleLightData& visibleLightData = viewGroup.getVisibleLightData();
|
|
|
+ const VisibleReflProbeData& visibleReflProbeData = viewGroup.getVisibleReflProbeData();
|
|
|
|
|
|
- // Prepare light grid required for transparent object rendering
|
|
|
- mLightGrid->updateGrid(*viewInfo, *mVisibleLightInfo, *mVisibleReflProbeInfo, viewProps.noLighting);
|
|
|
+ const LightGrid& lightGrid = viewInfo->getLightGrid();
|
|
|
|
|
|
SPtr<GpuParamBlockBuffer> gridParams;
|
|
|
SPtr<GpuBuffer> gridLightOffsetsAndSize, gridLightIndices;
|
|
|
SPtr<GpuBuffer> gridProbeOffsetsAndSize, gridProbeIndices;
|
|
|
- mLightGrid->getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices,
|
|
|
+ lightGrid.getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices,
|
|
|
gridParams);
|
|
|
|
|
|
- // Prepare image based material and its param buffer
|
|
|
- ITiledDeferredImageBasedLightingMat* imageBasedLightingMat =
|
|
|
- mTileDeferredImageBasedLightingMats->get(numSamples);
|
|
|
-
|
|
|
- imageBasedLightingMat->setReflectionProbes(*mVisibleReflProbeInfo, mReflCubemapArrayTex, viewProps.renderingReflections);
|
|
|
-
|
|
|
- float skyBrightness = 1.0f;
|
|
|
- if (mSkybox != nullptr)
|
|
|
- skyBrightness = mSkybox->getBrightness();
|
|
|
-
|
|
|
- imageBasedLightingMat->setSky(mSkyboxFilteredReflections, mSkyboxIrradiance, skyBrightness);
|
|
|
+ // Prepare refl. probe param buffer
|
|
|
+ ReflProbeParamBuffer reflProbeParamBuffer;
|
|
|
+ reflProbeParamBuffer.populate(sceneInfo.sky, visibleReflProbeData, sceneInfo.reflProbeCubemapsTex,
|
|
|
+ viewProps.renderingReflections);
|
|
|
|
|
|
// Assign camera and per-call data to all relevant renderables
|
|
|
const VisibilityInfo& visibility = viewInfo->getVisibilityMasks();
|
|
|
UINT32 numRenderables = (UINT32)sceneInfo.renderables.size();
|
|
|
- SPtr<GpuParamBlockBuffer> reflParamBuffer = imageBasedLightingMat->getReflectionsParamBuffer();
|
|
|
- SPtr<SamplerState> reflSamplerState = imageBasedLightingMat->getReflectionsSamplerState();
|
|
|
for (UINT32 i = 0; i < numRenderables; i++)
|
|
|
{
|
|
|
if (!visibility.renderables[i])
|
|
|
@@ -502,33 +423,26 @@ namespace bs { namespace ct
|
|
|
|
|
|
element.gridLightOffsetsAndSizeParam.set(gridLightOffsetsAndSize);
|
|
|
element.gridLightIndicesParam.set(gridLightIndices);
|
|
|
- element.lightsBufferParam.set(mVisibleLightInfo->getLightBuffer());
|
|
|
+ element.lightsBufferParam.set(visibleLightData.getLightBuffer());
|
|
|
|
|
|
// Image based lighting params
|
|
|
ImageBasedLightingParams& iblParams = element.imageBasedParams;
|
|
|
if (iblParams.reflProbeParamsBindingIdx != -1)
|
|
|
- element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflParamBuffer);
|
|
|
+ element.params->setParamBlockBuffer(iblParams.reflProbeParamsBindingIdx, reflProbeParamBuffer.buffer);
|
|
|
|
|
|
element.gridProbeOffsetsAndSizeParam.set(gridProbeOffsetsAndSize);
|
|
|
|
|
|
iblParams.reflectionProbeIndicesParam.set(gridProbeIndices);
|
|
|
- iblParams.reflectionProbesParam.set(mVisibleReflProbeInfo->getProbeBuffer());
|
|
|
+ iblParams.reflectionProbesParam.set(visibleReflProbeData.getProbeBuffer());
|
|
|
|
|
|
- iblParams.skyReflectionsTexParam.set(mSkyboxFilteredReflections);
|
|
|
- iblParams.skyIrradianceTexParam.set(mSkyboxIrradiance);
|
|
|
+ iblParams.skyReflectionsTexParam.set(sceneInfo.sky.filteredReflections);
|
|
|
+ iblParams.skyIrradianceTexParam.set(sceneInfo.sky.irradiance);
|
|
|
|
|
|
- iblParams.reflectionProbeCubemapsTexParam.set(mReflCubemapArrayTex);
|
|
|
- iblParams.preintegratedEnvBRDFParam.set(mPreintegratedEnvBRDF);
|
|
|
-
|
|
|
- iblParams.reflectionProbeCubemapsSampParam.set(reflSamplerState);
|
|
|
- iblParams.skyReflectionsSampParam.set(reflSamplerState);
|
|
|
+ iblParams.reflectionProbeCubemapsTexParam.set(sceneInfo.reflProbeCubemapsTex);
|
|
|
+ iblParams.preintegratedEnvBRDFParam.set(IBLUtility::getPreintegratedEnvBRDF());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- SPtr<RenderTargets> renderTargets = viewInfo->getRenderTargets();
|
|
|
- renderTargets->allocate(RTT_GBuffer);
|
|
|
- renderTargets->bind(RTT_GBuffer);
|
|
|
-
|
|
|
// Trigger pre-base-pass callbacks
|
|
|
auto iterRenderCallback = mCallbacks.begin();
|
|
|
|
|
|
@@ -547,22 +461,14 @@ namespace bs { namespace ct
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Render base pass
|
|
|
- const Vector<RenderQueueElement>& opaqueElements = viewInfo->getOpaqueQueue()->getSortedElements();
|
|
|
- for (auto iter = opaqueElements.begin(); iter != opaqueElements.end(); ++iter)
|
|
|
- {
|
|
|
- BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
|
|
|
- renderElement(*renderElem, iter->passIdx, iter->applyPass, viewProj);
|
|
|
- }
|
|
|
-
|
|
|
// Build HiZ buffer
|
|
|
bool isMSAA = numSamples > 1;
|
|
|
- // TODO - Avoid generating it unless it actually gets used in some system
|
|
|
- if (isMSAA)
|
|
|
- {
|
|
|
- renderTargets->allocate(RTT_ResolvedDepth);
|
|
|
- renderTargets->generate(RTT_ResolvedDepth);
|
|
|
- }
|
|
|
+ //// TODO - Avoid generating it unless it actually gets used in some system
|
|
|
+ //if (isMSAA)
|
|
|
+ //{
|
|
|
+ // renderTargets->allocate(RTT_ResolvedDepth);
|
|
|
+ // renderTargets->generate(RTT_ResolvedDepth);
|
|
|
+ //}
|
|
|
|
|
|
// Trigger post-base-pass callbacks
|
|
|
if (viewProps.triggerCallbacks)
|
|
|
@@ -580,120 +486,37 @@ namespace bs { namespace ct
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- renderTargets->allocate(RTT_HiZ);
|
|
|
- renderTargets->generate(RTT_HiZ);
|
|
|
-
|
|
|
- // Build AO if required
|
|
|
- bool useSSAO = viewInfo->getPPInfo().settings->ambientOcclusion.enabled;
|
|
|
- if(useSSAO)
|
|
|
- {
|
|
|
- renderTargets->allocate(RTT_AmbientOcclusion);
|
|
|
-
|
|
|
- // Note: This could be done as async compute (and started earlier, right after base pass)
|
|
|
- PostProcessing::instance().buildSSAO(*viewInfo);
|
|
|
- }
|
|
|
-
|
|
|
- RenderAPI& rapi = RenderAPI::instance();
|
|
|
- rapi.setRenderTarget(nullptr);
|
|
|
-
|
|
|
- // Accumulate all direct lighting into the light accumulation texture
|
|
|
- renderTargets->allocate(RTT_LightAccumulation);
|
|
|
-
|
|
|
- // Render non-shadowed lights into light accumulation texture (or buffer if MSAA)
|
|
|
- ITiledDeferredLightingMat* lightingMat = mTiledDeferredLightingMats->get(numSamples);
|
|
|
- lightingMat->setLights(*mVisibleLightInfo);
|
|
|
- lightingMat->execute(renderTargets, perCameraBuffer, viewProps.noLighting, !allowShadows);
|
|
|
-
|
|
|
- // If we're using flattened accumulation buffer for MSAA we need to copy its contents to the MSAA texture before
|
|
|
- // continuing
|
|
|
- if(isMSAA)
|
|
|
- {
|
|
|
- renderTargets->bind(RTT_LightAccumulation);
|
|
|
- mFlatFramebufferToTextureMat->execute(renderTargets->getLightAccumulationBuffer(),
|
|
|
- renderTargets->get(RTT_LightAccumulation));
|
|
|
- }
|
|
|
-
|
|
|
- // Render shadowed lights into light accumulation texture, using standard deferred
|
|
|
- if (allowShadows)
|
|
|
- {
|
|
|
- renderTargets->allocate(RTT_LightOcclusion);
|
|
|
-
|
|
|
- UINT32 viewIdx = sceneCamera->getRendererId();
|
|
|
-
|
|
|
- for(UINT32 i = 0; i < (UINT32)LightType::Count; i++)
|
|
|
- {
|
|
|
- LightType lightType = (LightType)i;
|
|
|
-
|
|
|
- auto& lights = mVisibleLightInfo->getLights(lightType);
|
|
|
- UINT32 count = mVisibleLightInfo->getNumShadowedLights(lightType);
|
|
|
- UINT32 offset = mVisibleLightInfo->getNumUnshadowedLights(lightType);
|
|
|
-
|
|
|
- for (UINT32 j = 0; j < count; j++)
|
|
|
- {
|
|
|
- renderTargets->bind(RTT_LightOcclusion);
|
|
|
-
|
|
|
- UINT32 lightIdx = offset + j;
|
|
|
- const RendererLight& light = *lights[lightIdx];
|
|
|
- ShadowRendering::instance().renderShadowOcclusion(*mScene, mCoreOptions->shadowFilteringQuality,
|
|
|
- light, viewIdx);
|
|
|
-
|
|
|
- renderTargets->bind(RTT_LightAccumulation);
|
|
|
- StandardDeferred::instance().renderLight(lightType, light, *viewInfo, *renderTargets);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- renderTargets->release(RTT_LightOcclusion);
|
|
|
- }
|
|
|
-
|
|
|
- // Make sure light accumulation buffer isn't bound and can be read from
|
|
|
- rapi.setRenderTarget(nullptr);
|
|
|
-
|
|
|
- // Render image based lighting, add it to light accumulation and output scene color
|
|
|
- renderTargets->allocate(RTT_SceneColor);
|
|
|
- imageBasedLightingMat->execute(renderTargets, perCameraBuffer, mPreintegratedEnvBRDF);
|
|
|
-
|
|
|
- if (useSSAO)
|
|
|
- renderTargets->release(RTT_AmbientOcclusion);
|
|
|
+ const RenderCompositor& compositor = viewInfo->getCompositor();
|
|
|
+ compositor.execute(viewGroup, *viewInfo, sceneInfo, *mCoreOptions);
|
|
|
|
|
|
- renderTargets->release(RTT_LightAccumulation);
|
|
|
- renderTargets->release(RTT_GBuffer);
|
|
|
+ //renderTargets->allocate(RTT_HiZ);
|
|
|
+ //renderTargets->generate(RTT_HiZ);
|
|
|
|
|
|
- renderTargets->bind(RTT_SceneColor, true);
|
|
|
+ //// Build AO if required
|
|
|
+ //bool useSSAO = viewInfo->getPPInfo().settings->ambientOcclusion.enabled;
|
|
|
+ //if(useSSAO)
|
|
|
+ //{
|
|
|
+ // renderTargets->allocate(RTT_AmbientOcclusion);
|
|
|
|
|
|
- // If we're using flattened framebuffer for MSAA we need to copy its contents to the MSAA scene texture before
|
|
|
- // continuing
|
|
|
- if(isMSAA)
|
|
|
- mFlatFramebufferToTextureMat->execute(renderTargets->getSceneColorBuffer(), renderTargets->get(RTT_SceneColor));
|
|
|
-
|
|
|
- // Render skybox (if any)
|
|
|
- if (mSkyboxTexture != nullptr)
|
|
|
- {
|
|
|
- mSkyboxMat->bind(perCameraBuffer);
|
|
|
- mSkyboxMat->setParams(mSkyboxTexture, Color::White);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- Color clearColor = viewProps.clearColor;
|
|
|
-
|
|
|
- mSkyboxSolidColorMat->bind(perCameraBuffer);
|
|
|
- mSkyboxSolidColorMat->setParams(nullptr, clearColor);
|
|
|
- }
|
|
|
+ // // Note: This could be done as async compute (and started earlier, right after base pass)
|
|
|
+ // PostProcessing::instance().buildSSAO(*viewInfo);
|
|
|
+ //}
|
|
|
|
|
|
- SPtr<Mesh> mesh = gRendererUtility().getSkyBoxMesh();
|
|
|
- gRendererUtility().draw(mesh, mesh->getProperties().getSubMesh(0));
|
|
|
+ //if (useSSAO)
|
|
|
+ // renderTargets->release(RTT_AmbientOcclusion);
|
|
|
|
|
|
- renderTargets->bind(RTT_SceneColor, false);
|
|
|
+ //renderTargets->bind(RTT_SceneColor, false);
|
|
|
|
|
|
// Render transparent objects
|
|
|
// TODO: Transparent objects cannot receive shadows. In order to support this I'd have to render the light occlusion
|
|
|
// for all lights affecting this object into a single (or a few) textures. I can likely use texture arrays for this,
|
|
|
// or to avoid sampling many textures, perhaps just jam it all in one or few texture channels.
|
|
|
- const Vector<RenderQueueElement>& transparentElements = viewInfo->getTransparentQueue()->getSortedElements();
|
|
|
- for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
|
|
|
- {
|
|
|
- BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
|
|
|
- renderElement(*renderElem, iter->passIdx, iter->applyPass, viewProj);
|
|
|
- }
|
|
|
+ //const Vector<RenderQueueElement>& transparentElements = viewInfo->getTransparentQueue()->getSortedElements();
|
|
|
+ //for (auto iter = transparentElements.begin(); iter != transparentElements.end(); ++iter)
|
|
|
+ //{
|
|
|
+ // BeastRenderableElement* renderElem = static_cast<BeastRenderableElement*>(iter->renderElem);
|
|
|
+ // renderElement(*renderElem, iter->passIdx, iter->applyPass, viewProj);
|
|
|
+ //}
|
|
|
|
|
|
// Trigger post-light-pass callbacks
|
|
|
if (viewProps.triggerCallbacks)
|
|
|
@@ -714,28 +537,29 @@ namespace bs { namespace ct
|
|
|
// Post-processing and final resolve
|
|
|
Rect2 viewportArea = viewProps.nrmViewRect;
|
|
|
|
|
|
- if (viewProps.runPostProcessing)
|
|
|
+ //if (viewProps.runPostProcessing)
|
|
|
+ //{
|
|
|
+ // // Post-processing code also takes care of writting to the final output target
|
|
|
+ // PostProcessing::instance().postProcess(viewInfo, renderTargets, frameDelta);
|
|
|
+ //}
|
|
|
+ //else
|
|
|
{
|
|
|
- // Post-processing code also takes care of writting to the final output target
|
|
|
- PostProcessing::instance().postProcess(viewInfo, renderTargets, frameDelta);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Just copy from scene color to output if no post-processing
|
|
|
- SPtr<RenderTarget> target = viewProps.target;
|
|
|
+ //// Just copy from scene color to output if no post-processing
|
|
|
+ //SPtr<RenderTarget> target = viewProps.target;
|
|
|
|
|
|
- rapi.setRenderTarget(target);
|
|
|
- rapi.setViewport(viewportArea);
|
|
|
+ //RenderAPI& rapi = RenderAPI::instance();
|
|
|
+ //rapi.setRenderTarget(target);
|
|
|
+ //rapi.setViewport(viewportArea);
|
|
|
|
|
|
- SPtr<Texture> sceneColor = renderTargets->get(RTT_SceneColor);
|
|
|
- gRendererUtility().blit(sceneColor, Rect2I::EMPTY, viewProps.flipView);
|
|
|
+ //SPtr<Texture> sceneColor = renderTargets->get(RTT_SceneColor);
|
|
|
+ //gRendererUtility().blit(sceneColor, Rect2I::EMPTY, viewProps.flipView);
|
|
|
}
|
|
|
|
|
|
- renderTargets->release(RTT_HiZ);
|
|
|
- renderTargets->release(RTT_SceneColor);
|
|
|
+ //renderTargets->release(RTT_HiZ);
|
|
|
+ //renderTargets->release(RTT_SceneColor);
|
|
|
|
|
|
- if (isMSAA)
|
|
|
- renderTargets->release(RTT_ResolvedDepth);
|
|
|
+ //if (isMSAA)
|
|
|
+ // renderTargets->release(RTT_ResolvedDepth);
|
|
|
|
|
|
// Trigger overlay callbacks
|
|
|
if (viewProps.triggerCallbacks)
|
|
|
@@ -763,7 +587,7 @@ namespace bs { namespace ct
|
|
|
gProfilerCPU().beginSample("RenderOverlay");
|
|
|
|
|
|
viewInfo->getPerViewBuffer()->flushToGPU();
|
|
|
- viewInfo->beginFrame(false);
|
|
|
+ viewInfo->beginFrame();
|
|
|
|
|
|
auto& viewProps = viewInfo->getProperties();
|
|
|
const Camera* camera = viewInfo->getSceneCamera();
|
|
|
@@ -830,20 +654,20 @@ namespace bs { namespace ct
|
|
|
element.morphVertexDeclaration);
|
|
|
}
|
|
|
|
|
|
- void RenderBeast::updateLightProbes(const FrameInfo& frameInfo)
|
|
|
+ void RenderBeast::renderReflectionProbes(const FrameInfo& frameInfo)
|
|
|
{
|
|
|
- const SceneInfo& sceneInfo = mScene->getSceneInfo();
|
|
|
+ SceneInfo& sceneInfo = mScene->_getSceneInfo();
|
|
|
UINT32 numProbes = (UINT32)sceneInfo.reflProbes.size();
|
|
|
|
|
|
bs_frame_mark();
|
|
|
{
|
|
|
UINT32 currentCubeArraySize = 0;
|
|
|
|
|
|
- if(mReflCubemapArrayTex != nullptr)
|
|
|
- mReflCubemapArrayTex->getProperties().getNumArraySlices();
|
|
|
+ if(sceneInfo.reflProbeCubemapsTex != nullptr)
|
|
|
+ currentCubeArraySize = sceneInfo.reflProbeCubemapsTex->getProperties().getNumArraySlices();
|
|
|
|
|
|
bool forceArrayUpdate = false;
|
|
|
- if(mReflCubemapArrayTex == nullptr || (currentCubeArraySize < numProbes && currentCubeArraySize != MaxReflectionCubemaps))
|
|
|
+ if(sceneInfo.reflProbeCubemapsTex == nullptr || (currentCubeArraySize < numProbes && currentCubeArraySize != MaxReflectionCubemaps))
|
|
|
{
|
|
|
TEXTURE_DESC cubeMapDesc;
|
|
|
cubeMapDesc.type = TEX_TYPE_CUBE_MAP;
|
|
|
@@ -853,12 +677,12 @@ namespace bs { namespace ct
|
|
|
cubeMapDesc.numMips = PixelUtil::getMaxMipmaps(cubeMapDesc.width, cubeMapDesc.height, 1, cubeMapDesc.format);
|
|
|
cubeMapDesc.numArraySlices = std::min(MaxReflectionCubemaps, numProbes + 4); // Keep a few empty entries
|
|
|
|
|
|
- mReflCubemapArrayTex = Texture::create(cubeMapDesc);
|
|
|
+ sceneInfo.reflProbeCubemapsTex = Texture::create(cubeMapDesc);
|
|
|
|
|
|
forceArrayUpdate = true;
|
|
|
}
|
|
|
|
|
|
- auto& cubemapArrayProps = mReflCubemapArrayTex->getProperties();
|
|
|
+ auto& cubemapArrayProps = sceneInfo.reflProbeCubemapsTex->getProperties();
|
|
|
|
|
|
TEXTURE_DESC cubemapDesc;
|
|
|
cubemapDesc.type = TEX_TYPE_CUBE_MAP;
|
|
|
@@ -926,7 +750,7 @@ namespace bs { namespace ct
|
|
|
{
|
|
|
for(UINT32 face = 0; face < 6; face++)
|
|
|
for(UINT32 mip = 0; mip <= srcProps.getNumMipmaps(); mip++)
|
|
|
- probeInfo.texture->copy(mReflCubemapArrayTex, face, mip, probeInfo.arrayIdx * 6 + face, mip);
|
|
|
+ probeInfo.texture->copy(sceneInfo.reflProbeCubemapsTex, face, mip, probeInfo.arrayIdx * 6 + face, mip);
|
|
|
}
|
|
|
|
|
|
mScene->setReflectionProbeArrayIndex(i, probeInfo.arrayIdx, true);
|
|
|
@@ -934,56 +758,68 @@ namespace bs { namespace ct
|
|
|
|
|
|
// Note: Consider pruning the reflection cubemap array if empty slot count becomes too high
|
|
|
}
|
|
|
-
|
|
|
- // Get skybox image-based lighting textures if needed/available
|
|
|
- if (mSkybox != nullptr && mSkyboxTexture != nullptr)
|
|
|
- {
|
|
|
- // If haven't assigned them already, do it now
|
|
|
- if (mSkyboxFilteredReflections == nullptr)
|
|
|
- {
|
|
|
- if (!LightProbeCache::instance().isRadianceDirty(mSkybox->getUUID()))
|
|
|
- mSkyboxFilteredReflections = LightProbeCache::instance().getCachedRadianceTexture(mSkybox->getUUID());
|
|
|
- else
|
|
|
- {
|
|
|
- mSkyboxFilteredReflections = Texture::create(cubemapDesc);
|
|
|
-
|
|
|
- IBLUtility::scaleCubemap(mSkyboxTexture, 0, mSkyboxFilteredReflections, 0);
|
|
|
- IBLUtility::filterCubemapForSpecular(mSkyboxFilteredReflections, scratchCubemap);
|
|
|
- LightProbeCache::instance().setCachedRadianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(mSkyboxIrradiance == nullptr)
|
|
|
- {
|
|
|
- if (!LightProbeCache::instance().isIrradianceDirty(mSkybox->getUUID()))
|
|
|
- mSkyboxIrradiance = LightProbeCache::instance().getCachedIrradianceTexture(mSkybox->getUUID());
|
|
|
- else
|
|
|
- {
|
|
|
- TEXTURE_DESC irradianceCubemapDesc;
|
|
|
- irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
|
|
|
- irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
|
|
|
- irradianceCubemapDesc.width = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
|
|
|
- irradianceCubemapDesc.height = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
|
|
|
- irradianceCubemapDesc.numMips = 0;
|
|
|
- irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
|
|
|
-
|
|
|
- mSkyboxIrradiance = Texture::create(irradianceCubemapDesc);
|
|
|
-
|
|
|
- IBLUtility::filterCubemapForIrradiance(mSkyboxFilteredReflections, mSkyboxIrradiance);
|
|
|
- LightProbeCache::instance().setCachedIrradianceTexture(mSkybox->getUUID(), mSkyboxFilteredReflections);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- mSkyboxFilteredReflections = nullptr;
|
|
|
- mSkyboxIrradiance = nullptr;
|
|
|
- }
|
|
|
-
|
|
|
}
|
|
|
bs_frame_clear();
|
|
|
}
|
|
|
|
|
|
+ void RenderBeast::updateSkybox()
|
|
|
+ {
|
|
|
+ SkyInfo& sky = mScene->_getSceneInfo().sky;
|
|
|
+
|
|
|
+ // Get skybox image-based lighting textures if needed/available
|
|
|
+ if (sky.skybox != nullptr && sky.radiance != nullptr)
|
|
|
+ {
|
|
|
+ // If haven't assigned them already, do it now
|
|
|
+ if (sky.filteredReflections == nullptr)
|
|
|
+ {
|
|
|
+ if (!LightProbeCache::instance().isRadianceDirty(sky.skybox->getUUID()))
|
|
|
+ sky.filteredReflections = LightProbeCache::instance().getCachedRadianceTexture(sky.skybox->getUUID());
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TEXTURE_DESC cubemapDesc;
|
|
|
+ cubemapDesc.type = TEX_TYPE_CUBE_MAP;
|
|
|
+ cubemapDesc.format = PF_FLOAT_R11G11B10;
|
|
|
+ cubemapDesc.width = IBLUtility::REFLECTION_CUBEMAP_SIZE;
|
|
|
+ cubemapDesc.height = IBLUtility::REFLECTION_CUBEMAP_SIZE;
|
|
|
+ cubemapDesc.numMips = PixelUtil::getMaxMipmaps(cubemapDesc.width, cubemapDesc.height, 1, cubemapDesc.format);
|
|
|
+ cubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
|
|
|
+
|
|
|
+ sky.filteredReflections = Texture::create(cubemapDesc);
|
|
|
+
|
|
|
+ IBLUtility::scaleCubemap(sky.radiance, 0, sky.filteredReflections, 0);
|
|
|
+ IBLUtility::filterCubemapForSpecular(sky.filteredReflections, nullptr);
|
|
|
+ LightProbeCache::instance().setCachedRadianceTexture(sky.skybox->getUUID(), sky.filteredReflections);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(sky.irradiance == nullptr)
|
|
|
+ {
|
|
|
+ if (!LightProbeCache::instance().isIrradianceDirty(sky.skybox->getUUID()))
|
|
|
+ sky.irradiance = LightProbeCache::instance().getCachedIrradianceTexture(sky.skybox->getUUID());
|
|
|
+ else
|
|
|
+ {
|
|
|
+ TEXTURE_DESC irradianceCubemapDesc;
|
|
|
+ irradianceCubemapDesc.type = TEX_TYPE_CUBE_MAP;
|
|
|
+ irradianceCubemapDesc.format = PF_FLOAT_R11G11B10;
|
|
|
+ irradianceCubemapDesc.width = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
|
|
|
+ irradianceCubemapDesc.height = IBLUtility::IRRADIANCE_CUBEMAP_SIZE;
|
|
|
+ irradianceCubemapDesc.numMips = 0;
|
|
|
+ irradianceCubemapDesc.usage = TU_STATIC | TU_RENDERTARGET;
|
|
|
+
|
|
|
+ sky.irradiance = Texture::create(irradianceCubemapDesc);
|
|
|
+
|
|
|
+ IBLUtility::filterCubemapForIrradiance(sky.filteredReflections, sky.irradiance);
|
|
|
+ LightProbeCache::instance().setCachedIrradianceTexture(sky.skybox->getUUID(), sky.filteredReflections);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sky.filteredReflections = nullptr;
|
|
|
+ sky.irradiance = nullptr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
void RenderBeast::captureSceneCubeMap(const SPtr<Texture>& cubemap, const Vector3& position, bool hdr, const FrameInfo& frameInfo)
|
|
|
{
|
|
|
const SceneInfo& sceneInfo = mScene->getSceneInfo();
|
|
|
@@ -1090,13 +926,11 @@ namespace bs { namespace ct
|
|
|
|
|
|
views[i].setView(viewDesc);
|
|
|
views[i].updatePerViewBuffer();
|
|
|
-
|
|
|
- views[i].determineVisible(sceneInfo.renderables, sceneInfo.renderableCullInfos);
|
|
|
}
|
|
|
|
|
|
RendererView* viewPtrs[] = { &views[0], &views[1], &views[2], &views[3], &views[4], &views[5] };
|
|
|
|
|
|
- RendererViewGroup viewGroup(viewPtrs, 6);
|
|
|
+ RendererViewGroup viewGroup(viewPtrs, 6, mCoreOptions->shadowMapSize);
|
|
|
viewGroup.determineVisibility(sceneInfo);
|
|
|
|
|
|
renderViews(viewGroup, frameInfo);
|