mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Refactors ModelRenderer and makes it closer to DOD
Separates submitted models and moder renderer and makes relations explicit. Now it's clear that we don't need separate ModelRenderer and ModelVertexRenderer.
This commit is contained in:
parent
764a420797
commit
fa90ddc8b6
3 changed files with 142 additions and 189 deletions
|
|
@ -217,89 +217,6 @@ void ModelRenderer::BuildIndices(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal data of the ModelRenderer.
|
|
||||||
*
|
|
||||||
* Separated into the source file to increase implementation hiding (and to
|
|
||||||
* avoid some causes of recompiles).
|
|
||||||
*/
|
|
||||||
struct ModelRenderer::ModelRendererInternals
|
|
||||||
{
|
|
||||||
/// ModelVertexRenderer used for vertex transformations
|
|
||||||
ModelVertexRendererPtr vertexRenderer;
|
|
||||||
|
|
||||||
/// List of submitted models for rendering in this frame
|
|
||||||
std::vector<CModel*> submissions[CSceneRenderer::CULL_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
ModelRenderer::ModelRenderer(ModelVertexRendererPtr vertexrenderer)
|
|
||||||
{
|
|
||||||
m = std::unique_ptr<ModelRendererInternals>(new ModelRendererInternals());
|
|
||||||
m->vertexRenderer = vertexrenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelRenderer::~ModelRenderer() = default;
|
|
||||||
|
|
||||||
// Submit one model.
|
|
||||||
void ModelRenderer::Submit(int cullGroup, CModel* model)
|
|
||||||
{
|
|
||||||
CModelRData* rdata = (CModelRData*)model->GetRenderData();
|
|
||||||
|
|
||||||
// Ensure model data is valid
|
|
||||||
const void* key = m->vertexRenderer.get();
|
|
||||||
if (!rdata || rdata->GetKey() != key)
|
|
||||||
{
|
|
||||||
model->InvalidatePosition();
|
|
||||||
rdata = m->vertexRenderer->CreateModelData(key, model);
|
|
||||||
model->SetRenderData(rdata);
|
|
||||||
model->SetDirty(~0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->submissions[cullGroup].push_back(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Call update for all submitted models and enter the rendering phase
|
|
||||||
void ModelRenderer::PrepareModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
{
|
|
||||||
for (CModel* model : m->submissions[cullGroup])
|
|
||||||
{
|
|
||||||
model->ValidatePosition();
|
|
||||||
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
|
||||||
ENSURE(rdata->GetKey() == m->vertexRenderer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
m->vertexRenderer->UpdateModelsData(deviceCommandContext, m->submissions[cullGroup]);
|
|
||||||
|
|
||||||
for (CModel* model : m->submissions[cullGroup])
|
|
||||||
{
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
|
||||||
rdata->m_UpdateFlags = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModelRenderer::UploadModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
{
|
|
||||||
m->vertexRenderer->UploadModelsData(deviceCommandContext, m->submissions[cullGroup]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear the submissions list
|
|
||||||
void ModelRenderer::EndFrame()
|
|
||||||
{
|
|
||||||
for (int cullGroup = 0; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
|
||||||
m->submissions[cullGroup].clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Helper structs for ShaderModelRenderer::Render():
|
// Helper structs for ShaderModelRenderer::Render():
|
||||||
|
|
||||||
struct SMRSortByDistItem
|
struct SMRSortByDistItem
|
||||||
|
|
@ -389,10 +306,10 @@ struct SMRCompareTechBucket
|
||||||
|
|
||||||
void ModelRenderer::Render(
|
void ModelRenderer::Render(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const RenderModifierPtr& modifier, const CShaderDefines& context,
|
ModelVertexRenderer& modelVertexRenderer, const RenderModifierPtr& modifier, const CShaderDefines& context,
|
||||||
int cullGroup, int flags, const ERenderMode renderMode)
|
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions)
|
||||||
{
|
{
|
||||||
if (m->submissions[cullGroup].empty())
|
if (submissions.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CMatrix3D worldToCam;
|
CMatrix3D worldToCam;
|
||||||
|
|
@ -403,7 +320,7 @@ void ModelRenderer::Render(
|
||||||
/*
|
/*
|
||||||
* Rendering approach:
|
* Rendering approach:
|
||||||
*
|
*
|
||||||
* m->submissions contains the list of CModels to render.
|
* submissions contains the list of CModels to render.
|
||||||
*
|
*
|
||||||
* The data we need to render a model is:
|
* The data we need to render a model is:
|
||||||
* - CShaderTechnique
|
* - CShaderTechnique
|
||||||
|
|
@ -471,9 +388,8 @@ void ModelRenderer::Render(
|
||||||
{
|
{
|
||||||
PROFILE3("bucketing by material");
|
PROFILE3("bucketing by material");
|
||||||
|
|
||||||
for (size_t i = 0; i < m->submissions[cullGroup].size(); ++i)
|
for (CModel* model : submissions)
|
||||||
{
|
{
|
||||||
CModel* model = m->submissions[cullGroup][i];
|
|
||||||
const CMaterial material{model->GetMaterial()};
|
const CMaterial material{model->GetMaterial()};
|
||||||
const CShaderDefines& defines{material.GetShaderDefines()};
|
const CShaderDefines& defines{material.GetShaderDefines()};
|
||||||
const CStrIntern shaderEffect{material.GetShaderEffect(materialPass)};
|
const CStrIntern shaderEffect{material.GetShaderEffect(materialPass)};
|
||||||
|
|
@ -727,7 +643,7 @@ void ModelRenderer::Render(
|
||||||
if (newModeldef != currentModeldef)
|
if (newModeldef != currentModeldef)
|
||||||
{
|
{
|
||||||
currentModeldef = newModeldef;
|
currentModeldef = newModeldef;
|
||||||
m->vertexRenderer->PrepareModelDef(deviceCommandContext, *currentModeldef);
|
modelVertexRenderer.PrepareModelDef(deviceCommandContext, *currentModeldef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind all uniforms when any change
|
// Bind all uniforms when any change
|
||||||
|
|
@ -790,9 +706,9 @@ void ModelRenderer::Render(
|
||||||
modifier->PrepareModel(deviceCommandContext, model);
|
modifier->PrepareModel(deviceCommandContext, model);
|
||||||
|
|
||||||
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
ENSURE(rdata->GetKey() == m->vertexRenderer.get());
|
ENSURE(rdata->GetKey() == &modelVertexRenderer);
|
||||||
|
|
||||||
m->vertexRenderer->RenderModel(deviceCommandContext, shader, model, rdata);
|
modelVertexRenderer.RenderModel(deviceCommandContext, shader, model, rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
#include "lib/types.h"
|
#include "lib/types.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CModel;
|
class CModel;
|
||||||
|
|
@ -80,7 +81,7 @@ private:
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ModelRenderer manages a per-frame list of models. It loads the appropriate
|
* ModelRenderer renders a per-frame list of models. It loads the appropriate
|
||||||
* shaders for rendering each model, and that batches by shader technique (and
|
* shaders for rendering each model, and that batches by shader technique (and
|
||||||
* by mesh and texture).
|
* by mesh and texture).
|
||||||
*
|
*
|
||||||
|
|
@ -93,46 +94,6 @@ private:
|
||||||
class ModelRenderer
|
class ModelRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModelRenderer(ModelVertexRendererPtr vertexrenderer);
|
|
||||||
~ModelRenderer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit: Submit a model for rendering this frame.
|
|
||||||
*
|
|
||||||
* preconditions : The model must not have been submitted to any
|
|
||||||
* ModelRenderer in this frame. Submit may only be called
|
|
||||||
* after EndFrame and before PrepareModels.
|
|
||||||
*
|
|
||||||
* @param model The model that will be added to the list of models
|
|
||||||
* submitted this frame.
|
|
||||||
*/
|
|
||||||
void Submit(int cullGroup, CModel* model);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PrepareModels: Calculate renderer data for all previously
|
|
||||||
* submitted models.
|
|
||||||
*
|
|
||||||
* Must be called before any rendering calls and after all models
|
|
||||||
* for this frame have been submitted.
|
|
||||||
*/
|
|
||||||
void PrepareModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Upload renderer data for all previously submitted models to backend.
|
|
||||||
*
|
|
||||||
* Must be called before any rendering calls and after all models
|
|
||||||
* for this frame have been prepared.
|
|
||||||
*/
|
|
||||||
void UploadModels(
|
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EndFrame: Remove all models from the list of submitted
|
|
||||||
* models.
|
|
||||||
*/
|
|
||||||
void EndFrame();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render: Render submitted models, using the given RenderModifier to setup
|
* Render: Render submitted models, using the given RenderModifier to setup
|
||||||
* the fragment stage.
|
* the fragment stage.
|
||||||
|
|
@ -147,8 +108,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void Render(
|
void Render(
|
||||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
|
||||||
const RenderModifierPtr& modifier, const CShaderDefines& context,
|
ModelVertexRenderer& modelVertexRenderer, const RenderModifierPtr& modifier, const CShaderDefines& context,
|
||||||
int cullGroup, int flags, const ERenderMode renderMode);
|
int cullGroup, int flags, const ERenderMode renderMode, std::span<CModel*> submissions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
||||||
|
|
@ -233,10 +194,6 @@ public:
|
||||||
* The new vertices cannot be used with existing face index and must be welded/reindexed.
|
* The new vertices cannot be used with existing face index and must be welded/reindexed.
|
||||||
*/
|
*/
|
||||||
static void GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning);
|
static void GenTangents(const CModelDefPtr& mdef, std::vector<float>& newVertices, bool gpuSkinning);
|
||||||
|
|
||||||
private:
|
|
||||||
struct ModelRendererInternals;
|
|
||||||
std::unique_ptr<ModelRendererInternals> m;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INCLUDED_MODELRENDERER
|
#endif // INCLUDED_MODELRENDERER
|
||||||
|
|
|
||||||
|
|
@ -118,16 +118,6 @@ public:
|
||||||
/// Various model renderers
|
/// Various model renderers
|
||||||
struct Models
|
struct Models
|
||||||
{
|
{
|
||||||
// NOTE: The current renderer design (with ModelRenderer, ModelVertexRenderer,
|
|
||||||
// RenderModifier, etc) is mostly a relic of an older design that implemented
|
|
||||||
// the different materials and rendering modes through extensive subclassing
|
|
||||||
// and hooking objects together in various combinations.
|
|
||||||
// The new design uses the CShaderManager API to abstract away the details
|
|
||||||
// of rendering, and uses a data-driven approach to materials, so there are
|
|
||||||
// now a small number of generic subclasses instead of many specialised subclasses,
|
|
||||||
// but most of the old infrastructure hasn't been refactored out yet and leads to
|
|
||||||
// some unwanted complexity.
|
|
||||||
|
|
||||||
// Submitted models are split on two axes:
|
// Submitted models are split on two axes:
|
||||||
// - Opaque vs Transparent - alpha-blended models are stored in a separate
|
// - Opaque vs Transparent - alpha-blended models are stored in a separate
|
||||||
// list so we can draw them above/below the alpha-blended water plane correctly
|
// list so we can draw them above/below the alpha-blended water plane correctly
|
||||||
|
|
@ -135,13 +125,21 @@ public:
|
||||||
// model instance (except for skinned models), so non-skinned models
|
// model instance (except for skinned models), so non-skinned models
|
||||||
// get different ModelVertexRenderers
|
// get different ModelVertexRenderers
|
||||||
|
|
||||||
std::unique_ptr<ModelRenderer> OpaqueSkinned;
|
struct Submissions
|
||||||
std::unique_ptr<ModelRenderer> OpaqueUnskinned;
|
{
|
||||||
std::unique_ptr<ModelRenderer> TransparentSkinned;
|
ModelVertexRenderer* modelVertexRenderer{nullptr};
|
||||||
std::unique_ptr<ModelRenderer> TransparentUnskinned;
|
std::vector<CModel*> submissions[CSceneRenderer::CULL_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
Submissions OpaqueSkinned;
|
||||||
|
Submissions OpaqueUnskinned;
|
||||||
|
Submissions TransparentSkinned;
|
||||||
|
Submissions TransparentUnskinned;
|
||||||
|
|
||||||
|
ModelRenderer modelRenderer;
|
||||||
|
|
||||||
ModelVertexRendererPtr VertexRendererShader;
|
|
||||||
ModelVertexRendererPtr VertexInstancingShader;
|
ModelVertexRendererPtr VertexInstancingShader;
|
||||||
|
ModelVertexRendererPtr VertexCPUSkinningShader;
|
||||||
ModelVertexRendererPtr VertexGPUSkinningShader;
|
ModelVertexRendererPtr VertexGPUSkinningShader;
|
||||||
|
|
||||||
LitRenderModifierPtr ModShader;
|
LitRenderModifierPtr ModShader;
|
||||||
|
|
@ -149,6 +147,94 @@ public:
|
||||||
|
|
||||||
CShaderDefines globalContext;
|
CShaderDefines globalContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload renderer data for all previously submitted models to backend.
|
||||||
|
*
|
||||||
|
* Must be called before any rendering calls and after all models
|
||||||
|
* for this frame have been prepared.
|
||||||
|
*/
|
||||||
|
void UploadModels(Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
||||||
|
{
|
||||||
|
PROFILE3("upload models");
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
Model.OpaqueSkinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
|
Model.TransparentSkinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
|
Model.OpaqueUnskinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
|
Model.TransparentUnskinned.modelVertexRenderer->UploadModelsData(deviceCommandContext, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PrepareModels: Calculate renderer data for all previously
|
||||||
|
* submitted models.
|
||||||
|
*
|
||||||
|
* Must be called before any rendering calls and after all models
|
||||||
|
* for this frame have been submitted.
|
||||||
|
*/
|
||||||
|
void PrepareModels(
|
||||||
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
|
||||||
|
{
|
||||||
|
PROFILE3("prepare models");
|
||||||
|
|
||||||
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
|
{
|
||||||
|
PrepareModels(deviceCommandContext, *Model.OpaqueSkinned.modelVertexRenderer, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
|
PrepareModels(deviceCommandContext, *Model.TransparentSkinned.modelVertexRenderer, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
|
PrepareModels(deviceCommandContext, *Model.OpaqueUnskinned.modelVertexRenderer, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
|
PrepareModels(deviceCommandContext, *Model.TransparentUnskinned.modelVertexRenderer, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrepareModels(
|
||||||
|
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, ModelVertexRenderer& modelVertexRenderer, std::span<CModel*> submissions)
|
||||||
|
{
|
||||||
|
for (CModel* model : submissions)
|
||||||
|
{
|
||||||
|
model->ValidatePosition();
|
||||||
|
|
||||||
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
|
ENSURE(rdata->GetKey() == &modelVertexRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
modelVertexRenderer.UpdateModelsData(deviceCommandContext, submissions);
|
||||||
|
|
||||||
|
for (CModel* model : submissions)
|
||||||
|
{
|
||||||
|
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
|
||||||
|
rdata->m_UpdateFlags = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit: Submit a model for rendering this frame.
|
||||||
|
*
|
||||||
|
* preconditions : The model must not have been submitted to any
|
||||||
|
* ModelRenderer in this frame. Submit may only be called
|
||||||
|
* after EndFrame and before PrepareModels.
|
||||||
|
*
|
||||||
|
* @param model The model that will be added to the list of models
|
||||||
|
* submitted this frame.
|
||||||
|
*/
|
||||||
|
void Submit(const int cullGroup, ModelVertexRenderer& modelVertexRenderer, Models::Submissions& submissions, CModel* model)
|
||||||
|
{
|
||||||
|
CModelRData* rdata{static_cast<CModelRData*>(model->GetRenderData())};
|
||||||
|
|
||||||
|
// Ensure model data is valid.
|
||||||
|
// TODO: using a pointer as a key is unsafe.
|
||||||
|
const void* key{&modelVertexRenderer};
|
||||||
|
if (!rdata || rdata->GetKey() != key)
|
||||||
|
{
|
||||||
|
model->InvalidatePosition();
|
||||||
|
rdata = modelVertexRenderer.CreateModelData(key, model);
|
||||||
|
model->SetRenderData(rdata);
|
||||||
|
model->SetDirty(~0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
submissions.submissions[cullGroup].push_back(model);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders all non-alpha-blended models with the given context.
|
* Renders all non-alpha-blended models with the given context.
|
||||||
*/
|
*/
|
||||||
|
|
@ -159,11 +245,11 @@ public:
|
||||||
CShaderDefines contextSkinned = context;
|
CShaderDefines contextSkinned = context;
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
if (g_RenderingOptions.GetGPUSkinning())
|
||||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||||
Model.OpaqueSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags, renderMode);
|
Model.modelRenderer.Render(deviceCommandContext, *Model.OpaqueSkinned.modelVertexRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.OpaqueSkinned.submissions[cullGroup]);
|
||||||
|
|
||||||
CShaderDefines contextUnskinned = context;
|
CShaderDefines contextUnskinned = context;
|
||||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||||
Model.OpaqueUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode);
|
Model.modelRenderer.Render(deviceCommandContext, *Model.OpaqueUnskinned.modelVertexRenderer, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.OpaqueUnskinned.submissions[cullGroup]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -176,11 +262,11 @@ public:
|
||||||
CShaderDefines contextSkinned = context;
|
CShaderDefines contextSkinned = context;
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
if (g_RenderingOptions.GetGPUSkinning())
|
||||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||||
Model.TransparentSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags, renderMode);
|
Model.modelRenderer.Render(deviceCommandContext, *Model.TransparentSkinned.modelVertexRenderer, Model.ModShader, contextSkinned, cullGroup, flags, renderMode, Model.TransparentSkinned.submissions[cullGroup]);
|
||||||
|
|
||||||
CShaderDefines contextUnskinned = context;
|
CShaderDefines contextUnskinned = context;
|
||||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||||
Model.TransparentUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode);
|
Model.modelRenderer.Render(deviceCommandContext, *Model.TransparentUnskinned.modelVertexRenderer, Model.ModShader, contextUnskinned, cullGroup, flags, renderMode, Model.TransparentUnskinned.submissions[cullGroup]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -235,24 +321,24 @@ void CSceneRenderer::ReloadShaders([[maybe_unused]] Renderer::Backend::IDevice*
|
||||||
|
|
||||||
m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier());
|
m->Model.ModShader = LitRenderModifierPtr(new ShaderRenderModifier());
|
||||||
|
|
||||||
m->Model.VertexRendererShader = ModelVertexRendererPtr(new CPUSkinnedModelVertexRenderer());
|
m->Model.VertexCPUSkinningShader = ModelVertexRendererPtr(new CPUSkinnedModelVertexRenderer());
|
||||||
m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer());
|
m->Model.VertexInstancingShader = ModelVertexRendererPtr(new InstancingModelRenderer());
|
||||||
|
|
||||||
if (g_RenderingOptions.GetGPUSkinning())
|
if (g_RenderingOptions.GetGPUSkinning())
|
||||||
{
|
{
|
||||||
m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new GPUSkinnedModelModelRenderer());
|
m->Model.VertexGPUSkinningShader = ModelVertexRendererPtr(new GPUSkinnedModelModelRenderer());
|
||||||
m->Model.OpaqueSkinned = std::make_unique<ModelRenderer>(m->Model.VertexGPUSkinningShader);
|
m->Model.OpaqueSkinned.modelVertexRenderer = m->Model.VertexGPUSkinningShader.get();
|
||||||
m->Model.TransparentSkinned = std::make_unique<ModelRenderer>(m->Model.VertexGPUSkinningShader);
|
m->Model.TransparentSkinned.modelVertexRenderer = m->Model.VertexGPUSkinningShader.get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m->Model.VertexGPUSkinningShader.reset();
|
m->Model.VertexGPUSkinningShader.reset();
|
||||||
m->Model.OpaqueSkinned = std::make_unique<ModelRenderer>(m->Model.VertexRendererShader);
|
m->Model.OpaqueSkinned.modelVertexRenderer = m->Model.VertexCPUSkinningShader.get();
|
||||||
m->Model.TransparentSkinned = std::make_unique<ModelRenderer>(m->Model.VertexRendererShader);
|
m->Model.TransparentSkinned.modelVertexRenderer = m->Model.VertexCPUSkinningShader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
m->Model.OpaqueUnskinned = std::make_unique<ModelRenderer>(m->Model.VertexInstancingShader);
|
m->Model.OpaqueUnskinned.modelVertexRenderer = m->Model.VertexInstancingShader.get();
|
||||||
m->Model.TransparentUnskinned = std::make_unique<ModelRenderer>(m->Model.VertexInstancingShader);
|
m->Model.TransparentUnskinned.modelVertexRenderer = m->Model.VertexInstancingShader.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::Initialize()
|
void CSceneRenderer::Initialize()
|
||||||
|
|
@ -764,13 +850,7 @@ void CSceneRenderer::PrepareSubmissions(
|
||||||
CShaderDefines context = m->globalContext;
|
CShaderDefines context = m->globalContext;
|
||||||
|
|
||||||
// Prepare model renderers
|
// Prepare model renderers
|
||||||
{
|
m->PrepareModels(deviceCommandContext);
|
||||||
PROFILE3("prepare models");
|
|
||||||
m->Model.OpaqueSkinned->PrepareModels(deviceCommandContext);
|
|
||||||
m->Model.TransparentSkinned->PrepareModels(deviceCommandContext);
|
|
||||||
m->Model.OpaqueUnskinned->PrepareModels(deviceCommandContext);
|
|
||||||
m->Model.TransparentUnskinned->PrepareModels(deviceCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->terrainRenderer.PrepareForRendering();
|
m->terrainRenderer.PrepareForRendering();
|
||||||
|
|
||||||
|
|
@ -778,13 +858,7 @@ void CSceneRenderer::PrepareSubmissions(
|
||||||
|
|
||||||
m->particleRenderer.PrepareForRendering(context);
|
m->particleRenderer.PrepareForRendering(context);
|
||||||
|
|
||||||
{
|
m->UploadModels(deviceCommandContext);
|
||||||
PROFILE3("upload models");
|
|
||||||
m->Model.OpaqueSkinned->UploadModels(deviceCommandContext);
|
|
||||||
m->Model.TransparentSkinned->UploadModels(deviceCommandContext);
|
|
||||||
m->Model.OpaqueUnskinned->UploadModels(deviceCommandContext);
|
|
||||||
m->Model.TransparentUnskinned->UploadModels(deviceCommandContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
m->overlayRenderer.Upload(deviceCommandContext);
|
m->overlayRenderer.Upload(deviceCommandContext);
|
||||||
|
|
||||||
|
|
@ -898,11 +972,13 @@ void CSceneRenderer::EndFrame()
|
||||||
m->particleRenderer.EndFrame();
|
m->particleRenderer.EndFrame();
|
||||||
m->silhouetteRenderer.EndFrame();
|
m->silhouetteRenderer.EndFrame();
|
||||||
|
|
||||||
// Finish model renderers
|
for (int cullGroup{0}; cullGroup < CSceneRenderer::CULL_MAX; ++cullGroup)
|
||||||
m->Model.OpaqueSkinned->EndFrame();
|
{
|
||||||
m->Model.TransparentSkinned->EndFrame();
|
m->Model.OpaqueSkinned.submissions[cullGroup].clear();
|
||||||
m->Model.OpaqueUnskinned->EndFrame();
|
m->Model.TransparentSkinned.submissions[cullGroup].clear();
|
||||||
m->Model.TransparentUnskinned->EndFrame();
|
m->Model.OpaqueUnskinned.submissions[cullGroup].clear();
|
||||||
|
m->Model.TransparentUnskinned.submissions[cullGroup].clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSceneRenderer::DisplayFrustum(Renderer::Backend::IDeviceCommandContext& deviceCommandContext)
|
void CSceneRenderer::DisplayFrustum(Renderer::Backend::IDeviceCommandContext& deviceCommandContext)
|
||||||
|
|
@ -1017,21 +1093,25 @@ void CSceneRenderer::SubmitNonRecursive(CModel* model)
|
||||||
m->shadow.AddShadowCasterBound(cascade, model->GetWorldBounds());
|
m->shadow.AddShadowCasterBound(cascade, model->GetWorldBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool requiresSkinning = (model->GetModelDef()->GetNumBones() != 0);
|
const bool requiresSkinning{model->GetModelDef()->GetNumBones() != 0};
|
||||||
|
ModelVertexRenderer& modelVertexSkinningRenderer{
|
||||||
|
g_RenderingOptions.GetGPUSkinning() ? *m->Model.VertexGPUSkinningShader : *m->Model.VertexCPUSkinningShader};
|
||||||
|
ModelVertexRenderer& modelVertexRenderer{
|
||||||
|
requiresSkinning ? modelVertexSkinningRenderer : *m->Model.VertexInstancingShader};
|
||||||
|
|
||||||
if (model->GetMaterial().UsesAlphaBlending())
|
if (model->GetMaterial().UsesAlphaBlending())
|
||||||
{
|
{
|
||||||
if (requiresSkinning)
|
if (requiresSkinning)
|
||||||
m->Model.TransparentSkinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.TransparentSkinned, model);
|
||||||
else
|
else
|
||||||
m->Model.TransparentUnskinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.TransparentUnskinned, model);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (requiresSkinning)
|
if (requiresSkinning)
|
||||||
m->Model.OpaqueSkinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.OpaqueSkinned, model);
|
||||||
else
|
else
|
||||||
m->Model.OpaqueUnskinned->Submit(m_CurrentCullGroup, model);
|
m->Submit(m_CurrentCullGroup, modelVertexRenderer, m->Model.OpaqueUnskinned, model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue