Batches decals and reduces the number of state changes.
Reviewed By: wraitii Tested By: Langbart Differential Revision: https://code.wildfiregames.com/D3545 This was SVN commit r24867.
This commit is contained in:
parent
8ea4f3186c
commit
5e1b84ed64
@ -24,19 +24,45 @@
|
|||||||
#include "graphics/ShaderManager.h"
|
#include "graphics/ShaderManager.h"
|
||||||
#include "graphics/Terrain.h"
|
#include "graphics/Terrain.h"
|
||||||
#include "graphics/TextureManager.h"
|
#include "graphics/TextureManager.h"
|
||||||
|
#include "lib/allocators/DynamicArena.h"
|
||||||
|
#include "lib/allocators/STLAllocators.h"
|
||||||
#include "ps/CLogger.h"
|
#include "ps/CLogger.h"
|
||||||
#include "ps/Game.h"
|
#include "ps/Game.h"
|
||||||
#include "ps/Profile.h"
|
#include "ps/Profile.h"
|
||||||
#include "renderer/Renderer.h"
|
#include "renderer/Renderer.h"
|
||||||
#include "renderer/TerrainRenderer.h"
|
#include "renderer/TerrainRenderer.h"
|
||||||
#include "simulation2/Simulation2.h"
|
|
||||||
#include "simulation2/components/ICmpWaterManager.h"
|
#include "simulation2/components/ICmpWaterManager.h"
|
||||||
|
#include "simulation2/Simulation2.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// TODO: Currently each decal is a separate CDecalRData. We might want to use
|
// TODO: Currently each decal is a separate CDecalRData. We might want to use
|
||||||
// lots of decals for special effects like shadows, footprints, etc, in which
|
// lots of decals for special effects like shadows, footprints, etc, in which
|
||||||
// case we should probably redesign this to batch them all together for more
|
// case we should probably redesign this to batch them all together for more
|
||||||
// efficient rendering.
|
// efficient rendering.
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SDecalBatch
|
||||||
|
{
|
||||||
|
CDecalRData* decal;
|
||||||
|
CShaderTechniquePtr shaderTech;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SDecalBatchComparator
|
||||||
|
{
|
||||||
|
bool operator()(const SDecalBatch& lhs, const SDecalBatch& rhs) const
|
||||||
|
{
|
||||||
|
if (lhs.shaderTech != rhs.shaderTech)
|
||||||
|
return lhs.shaderTech < rhs.shaderTech;
|
||||||
|
return lhs.decal < rhs.decal;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
CDecalRData::CDecalRData(CModelDecal* decal, CSimulation2* simulation)
|
CDecalRData::CDecalRData(CModelDecal* decal, CSimulation2* simulation)
|
||||||
: m_Decal(decal), m_IndexArray(GL_STATIC_DRAW), m_Array(GL_STATIC_DRAW), m_Simulation(simulation)
|
: m_Decal(decal), m_IndexArray(GL_STATIC_DRAW), m_Array(GL_STATIC_DRAW), m_Simulation(simulation)
|
||||||
{
|
{
|
||||||
@ -70,21 +96,26 @@ void CDecalRData::Update(CSimulation2* simulation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CDecalRData::RenderDecals(
|
void CDecalRData::RenderDecals(
|
||||||
std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow)
|
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow)
|
||||||
{
|
{
|
||||||
|
PROFILE3("render terrain decals");
|
||||||
|
|
||||||
|
using Arena = Allocators::DynamicArena<512 * KiB>;
|
||||||
|
|
||||||
|
Arena arena;
|
||||||
|
|
||||||
|
using Batches = std::vector<SDecalBatch, ProxyAllocator<SDecalBatch, Arena>>;
|
||||||
|
Batches batches((Batches::allocator_type(arena)));
|
||||||
|
batches.reserve(decals.size());
|
||||||
|
|
||||||
CShaderDefines contextDecal = context;
|
CShaderDefines contextDecal = context;
|
||||||
contextDecal.Add(str_DECAL, str_1);
|
contextDecal.Add(str_DECAL, str_1);
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
for (CDecalRData *decal : decals)
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < decals.size(); ++i)
|
|
||||||
{
|
{
|
||||||
CDecalRData *decal = decals[i];
|
|
||||||
|
|
||||||
CMaterial &material = decal->m_Decal->m_Decal.m_Material;
|
CMaterial &material = decal->m_Decal->m_Decal.m_Material;
|
||||||
|
|
||||||
if (material.GetShaderEffect().length() == 0)
|
if (material.GetShaderEffect().empty())
|
||||||
{
|
{
|
||||||
LOGERROR("Terrain renderer failed to load shader effect.\n");
|
LOGERROR("Terrain renderer failed to load shader effect.\n");
|
||||||
continue;
|
continue;
|
||||||
@ -99,24 +130,46 @@ void CDecalRData::RenderDecals(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (material.GetSamplers().empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SDecalBatch batch;
|
||||||
|
batch.decal = decal;
|
||||||
|
batch.shaderTech = techBase;
|
||||||
|
|
||||||
|
batches.emplace_back(std::move(batch));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (batches.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::sort(batches.begin(), batches.end(), SDecalBatchComparator());
|
||||||
|
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
for (auto itTechBegin = batches.begin(), itTechEnd = batches.begin(); itTechBegin != batches.end(); itTechBegin = itTechEnd)
|
||||||
|
{
|
||||||
|
while (itTechEnd != batches.end() && itTechBegin->shaderTech == itTechEnd->shaderTech)
|
||||||
|
++itTechEnd;
|
||||||
|
|
||||||
|
const CShaderTechniquePtr& techBase = itTechBegin->shaderTech;
|
||||||
const int numPasses = techBase->GetNumPasses();
|
const int numPasses = techBase->GetNumPasses();
|
||||||
|
|
||||||
for (int pass = 0; pass < numPasses; ++pass)
|
for (int pass = 0; pass < numPasses; ++pass)
|
||||||
{
|
{
|
||||||
techBase->BeginPass(pass);
|
techBase->BeginPass(pass);
|
||||||
TerrainRenderer::PrepareShader(techBase->GetShader(), shadow);
|
|
||||||
|
|
||||||
const CShaderProgramPtr& shader = techBase->GetShader(pass);
|
const CShaderProgramPtr& shader = techBase->GetShader(pass);
|
||||||
|
TerrainRenderer::PrepareShader(shader, shadow);
|
||||||
|
|
||||||
if (material.GetSamplers().size() != 0)
|
for (auto itDecal = itTechBegin; itDecal != itTechEnd; ++itDecal)
|
||||||
{
|
{
|
||||||
const CMaterial::SamplersVector& samplers = material.GetSamplers();
|
CDecalRData* decal = itDecal->decal;
|
||||||
size_t samplersNum = samplers.size();
|
CMaterial& material = decal->m_Decal->m_Decal.m_Material;
|
||||||
|
|
||||||
for (size_t s = 0; s < samplersNum; ++s)
|
const CMaterial::SamplersVector& samplers = material.GetSamplers();
|
||||||
{
|
for (const CMaterial::TextureSampler& sampler : samplers)
|
||||||
const CMaterial::TextureSampler& samp = samplers[s];
|
shader->BindTexture(sampler.Name, sampler.Sampler);
|
||||||
shader->BindTexture(samp.Name, samp.Sampler);
|
|
||||||
}
|
|
||||||
|
|
||||||
material.GetStaticUniforms().BindUniforms(shader);
|
material.GetStaticUniforms().BindUniforms(shader);
|
||||||
|
|
||||||
@ -152,14 +205,14 @@ void CDecalRData::RenderDecals(
|
|||||||
// bump stats
|
// bump stats
|
||||||
g_Renderer.m_Stats.m_DrawCalls++;
|
g_Renderer.m_Stats.m_DrawCalls++;
|
||||||
g_Renderer.m_Stats.m_TerrainTris += decal->m_IndexArray.GetNumVertices() / 3;
|
g_Renderer.m_Stats.m_TerrainTris += decal->m_IndexArray.GetNumVertices() / 3;
|
||||||
|
|
||||||
CVertexBuffer::Unbind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
techBase->EndPass();
|
techBase->EndPass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CVertexBuffer::Unbind();
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
void Update(CSimulation2* simulation);
|
void Update(CSimulation2* simulation);
|
||||||
|
|
||||||
static void RenderDecals(
|
static void RenderDecals(
|
||||||
std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow);
|
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow);
|
||||||
|
|
||||||
CModelDecal* GetDecal() { return m_Decal; }
|
CModelDecal* GetDecal() { return m_Decal; }
|
||||||
|
|
||||||
|
@ -1147,6 +1147,8 @@ void CPatchRData::RenderOutline()
|
|||||||
|
|
||||||
void CPatchRData::RenderSides(const std::vector<CPatchRData*>& patches, const CShaderProgramPtr& shader)
|
void CPatchRData::RenderSides(const std::vector<CPatchRData*>& patches, const CShaderProgramPtr& shader)
|
||||||
{
|
{
|
||||||
|
PROFILE3("render terrain sides");
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
CVertexBuffer* lastVB = nullptr;
|
CVertexBuffer* lastVB = nullptr;
|
||||||
|
@ -291,27 +291,19 @@ void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cul
|
|||||||
shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
|
||||||
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
PROFILE_START("render terrain sides");
|
|
||||||
CPatchRData::RenderSides(visiblePatches, shaderSolid);
|
CPatchRData::RenderSides(visiblePatches, shaderSolid);
|
||||||
PROFILE_END("render terrain sides");
|
|
||||||
|
|
||||||
techSolid->EndPass();
|
techSolid->EndPass();
|
||||||
|
|
||||||
PROFILE_START("render terrain base");
|
|
||||||
CPatchRData::RenderBases(visiblePatches, context, shadow);
|
CPatchRData::RenderBases(visiblePatches, context, shadow);
|
||||||
PROFILE_END("render terrain base");
|
|
||||||
|
|
||||||
// no need to write to the depth buffer a second time
|
// no need to write to the depth buffer a second time
|
||||||
glDepthMask(0);
|
glDepthMask(0);
|
||||||
|
|
||||||
// render blend passes for each patch
|
// render blend passes for each patch
|
||||||
PROFILE_START("render terrain blends");
|
|
||||||
CPatchRData::RenderBlends(visiblePatches, context, shadow);
|
CPatchRData::RenderBlends(visiblePatches, context, shadow);
|
||||||
PROFILE_END("render terrain blends");
|
|
||||||
|
|
||||||
PROFILE_START("render terrain decals");
|
|
||||||
CDecalRData::RenderDecals(visibleDecals, context, shadow);
|
CDecalRData::RenderDecals(visibleDecals, context, shadow);
|
||||||
PROFILE_END("render terrain decals");
|
|
||||||
|
|
||||||
// restore OpenGL state
|
// restore OpenGL state
|
||||||
g_Renderer.BindTexture(1, 0);
|
g_Renderer.BindTexture(1, 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user