Moves blend state management to DeviceCommandContext. Fixes #6420
Tested By: Langbart Comments By: Stan Differential Revision: https://code.wildfiregames.com/D4441 This was SVN commit r26228.
This commit is contained in:
parent
0b7a717c8a
commit
5adbe4f1a3
@ -1,40 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_solid"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_solid"/>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_solid"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_SHADOWCAST || MODE_SILHOUETTEOCCLUDER"/>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_solid"/>
|
||||
</technique>
|
||||
|
||||
|
||||
<technique>
|
||||
<require context="MODE_SILHOUETTEDISPLAY || MODE_WIREFRAME"/>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_solid_player"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_WIREFRAME"/>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_solid_player"/>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require context="MODE_SILHOUETTEDISPLAY || MODE_WIREFRAME"/>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_solid_player"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_WIREFRAME"/>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_solid_player"/>
|
||||
</technique>
|
||||
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_common"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_SILHOUETTEDISPLAY"/>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_solid_player">
|
||||
<blend src="constant_alpha" dst="one_minus_constant_alpha" constant="0 0 0 191"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_common"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require context="MODE_SILHOUETTEDISPLAY"/>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_solid_player">
|
||||
<blend src="constant_alpha" dst="one_minus_constant_alpha" constant="0 0 0 191"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/model_common"/>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/model_common"/>
|
||||
</technique>
|
||||
|
||||
</effect>
|
||||
|
20
binaries/data/mods/public/shaders/effects/particle_add.xml
Normal file
20
binaries/data/mods/public/shaders/effects/particle_add.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle">
|
||||
<blend src="src_alpha" dst="one"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle">
|
||||
<blend src="src_alpha" dst="one"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle">
|
||||
<blend src="zero" dst="one_minus_src_color"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle">
|
||||
<blend src="zero" dst="one_minus_src_color"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle">
|
||||
<blend src="src_alpha" dst="one_minus_src_alpha"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle">
|
||||
<blend src="src_alpha" dst="one_minus_src_alpha"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -1,14 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle_solid"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle_solid">
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle_solid"/>
|
||||
</technique>
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle_solid">
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
</effect>
|
||||
|
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<effect>
|
||||
|
||||
<technique>
|
||||
<require shaders="arb"/>
|
||||
<pass shader="arb/particle">
|
||||
<blend src="src_alpha" dst="one" op="REVERSE_SUBTRACT"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
<technique>
|
||||
<require shaders="glsl"/>
|
||||
<pass shader="glsl/particle">
|
||||
<blend src="src_alpha" dst="one" op="REVERSE_SUBTRACT"/>
|
||||
<depth mask="false"/>
|
||||
</pass>
|
||||
</technique>
|
||||
|
||||
</effect>
|
@ -27,6 +27,7 @@
|
||||
#include "maths/Rect.h"
|
||||
#include "maths/Vector2D.h"
|
||||
#include "ps/CStrInternStatic.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/Renderer.h"
|
||||
|
||||
#include <array>
|
||||
@ -75,6 +76,9 @@ public:
|
||||
Tech = g_Renderer.GetShaderManager().LoadEffect(str_canvas2d, defines);
|
||||
ENSURE(Tech);
|
||||
Tech->BeginPass();
|
||||
// TODO: remove global renderer access.
|
||||
g_Renderer.GetDeviceCommandContext()->SetGraphicsPipelineState(
|
||||
Tech->GetGraphicsPipelineStateDesc());
|
||||
}
|
||||
|
||||
void UnbindTech()
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -21,6 +21,7 @@
|
||||
#include "graphics/Texture.h"
|
||||
#include "maths/Vector2D.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class CRect;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -17,9 +17,6 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "graphics/CinemaManager.h"
|
||||
|
||||
#include "graphics/Camera.h"
|
||||
@ -37,6 +34,8 @@
|
||||
#include "ps/GameSetup/Config.h"
|
||||
#include "ps/Hotkey.h"
|
||||
#include "ps/World.h"
|
||||
#include "renderer/DebugRenderer.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "simulation2/components/ICmpCinemaManager.h"
|
||||
#include "simulation2/components/ICmpOverlayRenderer.h"
|
||||
#include "simulation2/components/ICmpRangeManager.h"
|
||||
@ -46,9 +45,6 @@
|
||||
#include "simulation2/MessageTypes.h"
|
||||
#include "simulation2/system/ComponentManager.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "renderer/DebugRenderer.h"
|
||||
#include "renderer/Renderer.h"
|
||||
|
||||
|
||||
CCinemaManager::CCinemaManager()
|
||||
: m_DrawPaths(false)
|
||||
@ -78,7 +74,6 @@ void CCinemaManager::DrawPaths() const
|
||||
return;
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
for (const std::pair<const CStrW, CCinemaPath>& p : cmpCinemaManager->GetPaths())
|
||||
{
|
||||
@ -92,7 +87,6 @@ void CCinemaManager::DrawPaths() const
|
||||
DrawNodes(p.second.GetTargetSpline(), CColor(1.f, 0.1f, 0.f, 1.f));
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
|
@ -144,9 +144,10 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (m_WhichTex ? m_SmoothFBO2 : m_SmoothFBO1));
|
||||
|
||||
m_SmoothTech->BeginPass();
|
||||
CShaderProgramPtr shader = m_SmoothTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
m_SmoothTech->GetGraphicsPipelineStateDesc());
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
const CShaderProgramPtr& shader = m_SmoothTech->GetShader();
|
||||
|
||||
shader->BindTexture(str_losTex1, m_Texture.get());
|
||||
shader->BindTexture(str_losTex2, (m_WhichTex ? m_TextureSmooth1 : m_TextureSmooth2).get());
|
||||
|
@ -201,7 +201,7 @@ void CMiniMapTexture::Render(Renderer::Backend::GL::CDeviceCommandContext* devic
|
||||
if (m_TerrainTextureDirty)
|
||||
RebuildTerrainTexture(deviceCommandContext, terrain);
|
||||
|
||||
RenderFinalTexture();
|
||||
RenderFinalTexture(deviceCommandContext);
|
||||
}
|
||||
|
||||
void CMiniMapTexture::CreateTextures(
|
||||
@ -322,7 +322,8 @@ void CMiniMapTexture::RebuildTerrainTexture(
|
||||
m_TerrainData.get(), width * height * 4, 0, 0, width, height);
|
||||
}
|
||||
|
||||
void CMiniMapTexture::RenderFinalTexture()
|
||||
void CMiniMapTexture::RenderFinalTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
// only update 2x / second
|
||||
// (note: since units only move a few pixels per second on the minimap,
|
||||
@ -356,7 +357,10 @@ void CMiniMapTexture::RenderFinalTexture()
|
||||
baseDefines.Add(str_MINIMAP_BASE, str_1);
|
||||
|
||||
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
tech->GetGraphicsPipelineStateDesc();
|
||||
tech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
shader = tech->GetShader();
|
||||
|
||||
if (m_TerrainTexture)
|
||||
@ -376,8 +380,14 @@ void CMiniMapTexture::RenderFinalTexture()
|
||||
if (m_TerrainTexture)
|
||||
DrawTexture(shader);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
glColorMask(1, 1, 1, 0);
|
||||
|
||||
// Draw territory boundaries
|
||||
@ -389,7 +399,8 @@ void CMiniMapTexture::RenderFinalTexture()
|
||||
|
||||
DrawTexture(shader);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
pipelineStateDesc.blendState.enabled = false;
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
glColorMask(0, 0, 0, 1);
|
||||
|
||||
shader->BindTexture(str_baseTex, losTexture.GetTexture());
|
||||
@ -406,6 +417,8 @@ void CMiniMapTexture::RenderFinalTexture()
|
||||
pointDefines.Add(str_MINIMAP_POINT, str_1);
|
||||
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, pointDefines);
|
||||
tech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
tech->GetGraphicsPipelineStateDesc());
|
||||
shader = tech->GetShader();
|
||||
shader->Uniform(str_transform, baseTransform);
|
||||
shader->Uniform(str_pointSize, 9.0f);
|
||||
|
@ -60,7 +60,8 @@ private:
|
||||
void RebuildTerrainTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CTerrain* terrain);
|
||||
void RenderFinalTexture();
|
||||
void RenderFinalTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
CSimulation2& m_Simulation;
|
||||
|
||||
|
@ -154,7 +154,8 @@ void CParticleEmitter::UpdateArrayData(int frameNumber)
|
||||
|
||||
// Special case: If the blending depends on the source color, not the source alpha,
|
||||
// then pre-multiply by the alpha. (This is kind of a hack.)
|
||||
if (m_Type->m_BlendFuncDst == GL_ONE_MINUS_SRC_COLOR)
|
||||
if (m_Type->m_BlendMode == CParticleEmitterType::BlendMode::OVERLAY ||
|
||||
m_Type->m_BlendMode == CParticleEmitterType::BlendMode::MULTIPLY)
|
||||
{
|
||||
color.R = (color.R * color.A) / 255;
|
||||
color.G = (color.G * color.A) / 255;
|
||||
@ -189,8 +190,6 @@ void CParticleEmitter::Bind(const CShaderProgramPtr& shader)
|
||||
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
||||
|
||||
shader->BindTexture(str_baseTex, m_Type->m_Texture);
|
||||
glBlendEquationEXT(m_Type->m_BlendEquation);
|
||||
glBlendFunc(m_Type->m_BlendFuncSrc, m_Type->m_BlendFuncDst);
|
||||
}
|
||||
|
||||
void CParticleEmitter::RenderArray(const CShaderProgramPtr& shader)
|
||||
|
@ -352,9 +352,7 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
||||
m_Variables[VAR_COLOR_R] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_COLOR_G] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_Variables[VAR_COLOR_B] = IParticleVarPtr(new CParticleVarConstant(1.f));
|
||||
m_BlendEquation = GL_FUNC_ADD;
|
||||
m_BlendFuncSrc = GL_SRC_ALPHA;
|
||||
m_BlendFuncDst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
m_BlendMode = BlendMode::ADD;
|
||||
m_StartFull = false;
|
||||
m_UseRelativeVelocity = false;
|
||||
m_Texture = g_Renderer.GetTextureManager().GetErrorTexture();
|
||||
@ -401,31 +399,15 @@ bool CParticleEmitterType::LoadXML(const VfsPath& path)
|
||||
}
|
||||
else if (Child.GetNodeName() == el_blend)
|
||||
{
|
||||
CStr mode = Child.GetAttributes().GetNamedItem(at_mode);
|
||||
const CStr mode = Child.GetAttributes().GetNamedItem(at_mode);
|
||||
if (mode == "add")
|
||||
{
|
||||
m_BlendEquation = GL_FUNC_ADD;
|
||||
m_BlendFuncSrc = GL_SRC_ALPHA;
|
||||
m_BlendFuncDst = GL_ONE;
|
||||
}
|
||||
m_BlendMode = BlendMode::ADD;
|
||||
else if (mode == "subtract")
|
||||
{
|
||||
m_BlendEquation = GL_FUNC_REVERSE_SUBTRACT;
|
||||
m_BlendFuncSrc = GL_SRC_ALPHA;
|
||||
m_BlendFuncDst = GL_ONE;
|
||||
}
|
||||
m_BlendMode = BlendMode::SUBTRACT;
|
||||
else if (mode == "over")
|
||||
{
|
||||
m_BlendEquation = GL_FUNC_ADD;
|
||||
m_BlendFuncSrc = GL_SRC_ALPHA;
|
||||
m_BlendFuncDst = GL_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
m_BlendMode = BlendMode::OVERLAY;
|
||||
else if (mode == "multiply")
|
||||
{
|
||||
m_BlendEquation = GL_FUNC_ADD;
|
||||
m_BlendFuncSrc = GL_ZERO;
|
||||
m_BlendFuncDst = GL_ONE_MINUS_SRC_COLOR;
|
||||
}
|
||||
m_BlendMode = BlendMode::MULTIPLY;
|
||||
}
|
||||
else if (Child.GetNodeName() == el_start_full)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -23,6 +23,9 @@
|
||||
#include "lib/file/vfs/vfs_path.h"
|
||||
#include "maths/BoundingBoxAligned.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class CVector3D;
|
||||
class CParticleEmitter;
|
||||
class CParticleManager;
|
||||
@ -74,6 +77,14 @@ private:
|
||||
VAR__MAX
|
||||
};
|
||||
|
||||
enum class BlendMode
|
||||
{
|
||||
ADD,
|
||||
SUBTRACT,
|
||||
OVERLAY,
|
||||
MULTIPLY
|
||||
};
|
||||
|
||||
int GetVariableID(const std::string& name);
|
||||
|
||||
bool LoadXML(const VfsPath& path);
|
||||
@ -93,9 +104,7 @@ private:
|
||||
|
||||
CTexturePtr m_Texture;
|
||||
|
||||
GLenum m_BlendEquation;
|
||||
GLenum m_BlendFuncSrc;
|
||||
GLenum m_BlendFuncDst;
|
||||
BlendMode m_BlendMode = BlendMode::ADD;
|
||||
bool m_StartFull;
|
||||
bool m_UseRelativeVelocity;
|
||||
|
||||
|
@ -298,42 +298,6 @@ static GLenum ParseComparisonFunc(const CStr& str)
|
||||
return GL_ALWAYS;
|
||||
}
|
||||
|
||||
static GLenum ParseBlendFunc(const CStr& str)
|
||||
{
|
||||
if (str == "zero")
|
||||
return GL_ZERO;
|
||||
if (str == "one")
|
||||
return GL_ONE;
|
||||
if (str == "src_color")
|
||||
return GL_SRC_COLOR;
|
||||
if (str == "one_minus_src_color")
|
||||
return GL_ONE_MINUS_SRC_COLOR;
|
||||
if (str == "dst_color")
|
||||
return GL_DST_COLOR;
|
||||
if (str == "one_minus_dst_color")
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
if (str == "src_alpha")
|
||||
return GL_SRC_ALPHA;
|
||||
if (str == "one_minus_src_alpha")
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
if (str == "dst_alpha")
|
||||
return GL_DST_ALPHA;
|
||||
if (str == "one_minus_dst_alpha")
|
||||
return GL_ONE_MINUS_DST_ALPHA;
|
||||
if (str == "constant_color")
|
||||
return GL_CONSTANT_COLOR;
|
||||
if (str == "one_minus_constant_color")
|
||||
return GL_ONE_MINUS_CONSTANT_COLOR;
|
||||
if (str == "constant_alpha")
|
||||
return GL_CONSTANT_ALPHA;
|
||||
if (str == "one_minus_constant_alpha")
|
||||
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||
if (str == "src_alpha_saturate")
|
||||
return GL_SRC_ALPHA_SATURATE;
|
||||
debug_warn("Invalid blend func");
|
||||
return GL_ZERO;
|
||||
}
|
||||
|
||||
size_t CShaderManager::EffectCacheKeyHash::operator()(const EffectCacheKey& key) const
|
||||
{
|
||||
size_t hash = 0;
|
||||
@ -393,9 +357,11 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin
|
||||
EL(pass);
|
||||
EL(require);
|
||||
EL(sort_by_distance);
|
||||
AT(constant);
|
||||
AT(context);
|
||||
AT(dst);
|
||||
AT(func);
|
||||
AT(op);
|
||||
AT(shader);
|
||||
AT(shaders);
|
||||
AT(src);
|
||||
@ -496,6 +462,8 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin
|
||||
CShaderDefines passDefines = techDefines;
|
||||
|
||||
CShaderPass pass;
|
||||
Renderer::Backend::GraphicsPipelineStateDesc passPipelineStateDesc =
|
||||
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc();
|
||||
|
||||
XERO_ITER_EL(Child, Element)
|
||||
{
|
||||
@ -505,9 +473,25 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin
|
||||
}
|
||||
else if (Element.GetNodeName() == el_blend)
|
||||
{
|
||||
GLenum src = ParseBlendFunc(Element.GetAttributes().GetNamedItem(at_src));
|
||||
GLenum dst = ParseBlendFunc(Element.GetAttributes().GetNamedItem(at_dst));
|
||||
pass.BlendFunc(src, dst);
|
||||
passPipelineStateDesc.blendState.enabled = true;
|
||||
passPipelineStateDesc.blendState.srcColorBlendFactor = passPipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::ParseBlendFactor(Element.GetAttributes().GetNamedItem(at_src));
|
||||
passPipelineStateDesc.blendState.dstColorBlendFactor = passPipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::ParseBlendFactor(Element.GetAttributes().GetNamedItem(at_dst));
|
||||
if (!Element.GetAttributes().GetNamedItem(at_op).empty())
|
||||
{
|
||||
passPipelineStateDesc.blendState.colorBlendOp = passPipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::ParseBlendOp(Element.GetAttributes().GetNamedItem(at_op));
|
||||
}
|
||||
if (!Element.GetAttributes().GetNamedItem(at_constant).empty())
|
||||
{
|
||||
if (!passPipelineStateDesc.blendState.constant.ParseString(
|
||||
Element.GetAttributes().GetNamedItem(at_constant)))
|
||||
{
|
||||
LOGERROR("Failed to parse blend constant: %s",
|
||||
Element.GetAttributes().GetNamedItem(at_constant).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Element.GetNodeName() == el_depth)
|
||||
{
|
||||
@ -519,6 +503,8 @@ bool CShaderManager::NewEffect(const char* name, const CShaderDefines& baseDefin
|
||||
}
|
||||
}
|
||||
|
||||
pass.SetPipelineStateDesc(passPipelineStateDesc);
|
||||
|
||||
// Load the shader program after we've read all the possibly-relevant <define>s
|
||||
pass.SetShader(LoadProgram(Child.GetAttributes().GetNamedItem(at_shader).c_str(), passDefines));
|
||||
|
||||
|
@ -30,12 +30,6 @@ void CShaderPass::Bind()
|
||||
// TODO: maybe emit some warning if GLSL shaders try to use alpha test;
|
||||
// the test should be done inside the shader itself
|
||||
|
||||
if (m_HasBlend)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(m_BlendSrc, m_BlendDst);
|
||||
}
|
||||
|
||||
if (m_HasColorMask)
|
||||
glColorMask(m_ColorMaskR, m_ColorMaskG, m_ColorMaskB, m_ColorMaskA);
|
||||
|
||||
@ -50,9 +44,6 @@ void CShaderPass::Unbind()
|
||||
{
|
||||
m_Shader->Unbind();
|
||||
|
||||
if (m_HasBlend)
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (m_HasColorMask)
|
||||
glColorMask(1, 1, 1, 1);
|
||||
|
||||
@ -63,13 +54,6 @@ void CShaderPass::Unbind()
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
}
|
||||
|
||||
void CShaderPass::BlendFunc(GLenum src, GLenum dst)
|
||||
{
|
||||
m_HasBlend = true;
|
||||
m_BlendSrc = src;
|
||||
m_BlendDst = dst;
|
||||
}
|
||||
|
||||
void CShaderPass::ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a)
|
||||
{
|
||||
m_HasColorMask = true;
|
||||
@ -91,6 +75,11 @@ void CShaderPass::DepthFunc(GLenum func)
|
||||
m_DepthFunc = func;
|
||||
}
|
||||
|
||||
void CShaderPass::SetPipelineStateDesc(
|
||||
const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc)
|
||||
{
|
||||
m_PipelineStateDesc = pipelineStateDesc;
|
||||
}
|
||||
|
||||
CShaderTechnique::CShaderTechnique() = default;
|
||||
|
||||
@ -122,6 +111,13 @@ const CShaderProgramPtr& CShaderTechnique::GetShader(int pass) const
|
||||
return m_Passes[pass].GetShader();
|
||||
}
|
||||
|
||||
const Renderer::Backend::GraphicsPipelineStateDesc&
|
||||
CShaderTechnique::GetGraphicsPipelineStateDesc(int pass) const
|
||||
{
|
||||
ENSURE(0 <= pass && pass < static_cast<int>(m_Passes.size()));
|
||||
return m_Passes[pass].GetPipelineStateDesc();
|
||||
}
|
||||
|
||||
bool CShaderTechnique::GetSortByDistance() const
|
||||
{
|
||||
return m_SortByDistance;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "graphics/ShaderProgramPtr.h"
|
||||
#include "graphics/ShaderTechniquePtr.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "renderer/backend/PipelineState.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -39,10 +40,11 @@ public:
|
||||
void SetShader(const CShaderProgramPtr& shader) { m_Shader = shader; }
|
||||
|
||||
// Add various bits of GL state to the pass:
|
||||
void BlendFunc(GLenum src, GLenum dst);
|
||||
void ColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a);
|
||||
void DepthMask(GLboolean mask);
|
||||
void DepthFunc(GLenum func);
|
||||
void SetPipelineStateDesc(
|
||||
const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc);
|
||||
|
||||
/**
|
||||
* Set up all the GL state that was previously specified on this pass.
|
||||
@ -56,12 +58,13 @@ public:
|
||||
|
||||
const CShaderProgramPtr& GetShader() const { return m_Shader; }
|
||||
|
||||
const Renderer::Backend::GraphicsPipelineStateDesc&
|
||||
GetPipelineStateDesc() const { return m_PipelineStateDesc; }
|
||||
|
||||
private:
|
||||
CShaderProgramPtr m_Shader;
|
||||
|
||||
bool m_HasBlend = false;
|
||||
GLenum m_BlendSrc;
|
||||
GLenum m_BlendDst;
|
||||
Renderer::Backend::GraphicsPipelineStateDesc m_PipelineStateDesc{};
|
||||
|
||||
bool m_HasColorMask = false;
|
||||
GLboolean m_ColorMaskR;
|
||||
@ -92,6 +95,9 @@ public:
|
||||
void EndPass(int pass = 0);
|
||||
const CShaderProgramPtr& GetShader(int pass = 0) const;
|
||||
|
||||
const Renderer::Backend::GraphicsPipelineStateDesc&
|
||||
GetGraphicsPipelineStateDesc(int pass = 0) const;
|
||||
|
||||
/**
|
||||
* Whether this technique uses alpha blending that requires objects to be
|
||||
* drawn from furthest to nearest.
|
||||
|
@ -411,7 +411,17 @@ void CMiniMap::Draw(CCanvas2D& canvas)
|
||||
baseDefines.Add(str_MINIMAP_BASE, str_1);
|
||||
|
||||
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
tech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
tech->BeginPass();
|
||||
g_Renderer.GetDeviceCommandContext()->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
shader = tech->GetShader();
|
||||
|
||||
shader->BindTexture(str_baseTex, miniMapTexture.GetTexture());
|
||||
@ -421,17 +431,12 @@ void CMiniMap::Draw(CCanvas2D& canvas)
|
||||
shader->Uniform(str_transform, baseTransform);
|
||||
shader->Uniform(str_textureTransform, baseTextureTransform);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
|
||||
const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
|
||||
const float angle = GetAngle();
|
||||
DrawTexture(shader, angle, x, y, x2, y2, m_MapScale);
|
||||
|
||||
tech->EndPass();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
PROFILE_START("minimap flares");
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -129,8 +129,11 @@ X(normalMap2)
|
||||
X(objectColor)
|
||||
X(overlay_line)
|
||||
X(overlay_solid)
|
||||
X(particle)
|
||||
X(particle_add)
|
||||
X(particle_multiply)
|
||||
X(particle_overlay)
|
||||
X(particle_solid)
|
||||
X(particle_subtract)
|
||||
X(playerColor)
|
||||
X(pointSize)
|
||||
X(projInvTransform)
|
||||
|
@ -29,11 +29,37 @@
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "maths/Vector3D.h"
|
||||
#include "ps/CStrInternStatic.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/SceneRenderer.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void SetGraphicsPipelineStateFromTechAndColor(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderTechniquePtr& tech, const CColor& color)
|
||||
{
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc = tech->GetGraphicsPipelineStateDesc();
|
||||
if (color.a != 1.0f)
|
||||
{
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
}
|
||||
else
|
||||
pipelineStateDesc.blendState.enabled = false;
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void CDebugRenderer::DrawLine(const CVector3D& from, const CVector3D& to, const CColor& color, const float width)
|
||||
{
|
||||
if (from == to)
|
||||
@ -51,6 +77,7 @@ void CDebugRenderer::DrawLine(const std::vector<CVector3D>& line, const CColor&
|
||||
CShaderTechniquePtr debugLineTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
|
||||
debugLineTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugLineTech, color);
|
||||
|
||||
const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera();
|
||||
|
||||
@ -104,6 +131,7 @@ void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, con
|
||||
CShaderTechniquePtr debugCircleTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
|
||||
debugCircleTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), debugCircleTech, color);
|
||||
|
||||
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
|
||||
|
||||
@ -160,6 +188,7 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
|
||||
CShaderTechniquePtr overlayTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
|
||||
overlayTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), overlayTech, color);
|
||||
|
||||
CShaderProgramPtr overlayShader = overlayTech->GetShader();
|
||||
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
@ -234,6 +263,7 @@ void CDebugRenderer::DrawBoundingBox(const CBoundingBoxAligned& boundingBox, con
|
||||
{
|
||||
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
shaderTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), shaderTech, color);
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
shader->Uniform(str_color, color);
|
||||
@ -280,6 +310,7 @@ void CDebugRenderer::DrawBoundingBoxOutline(const CBoundingBoxAligned& boundingB
|
||||
{
|
||||
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
shaderTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), shaderTech, color);
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
shader->Uniform(str_color, color);
|
||||
@ -323,6 +354,7 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color)
|
||||
{
|
||||
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
shaderTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), shaderTech, color);
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
shader->Uniform(str_color, color);
|
||||
@ -370,6 +402,7 @@ void CDebugRenderer::DrawBrushOutline(const CBrush& brush, const CColor& color)
|
||||
{
|
||||
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
shaderTech->BeginPass();
|
||||
SetGraphicsPipelineStateFromTechAndColor(g_Renderer.GetDeviceCommandContext(), shaderTech, color);
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
shader->Uniform(str_color, color);
|
||||
|
@ -36,7 +36,6 @@
|
||||
#include "simulation2/Simulation2.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
// 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
|
||||
@ -89,6 +88,7 @@ void CDecalRData::Update(CSimulation2* simulation)
|
||||
}
|
||||
|
||||
void CDecalRData::RenderDecals(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow)
|
||||
{
|
||||
PROFILE3("render terrain decals");
|
||||
@ -142,9 +142,6 @@ void CDecalRData::RenderDecals(
|
||||
|
||||
std::sort(batches.begin(), batches.end(), SDecalBatchComparator());
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
CVertexBuffer* lastIB = nullptr;
|
||||
for (auto itTechBegin = batches.begin(), itTechEnd = batches.begin(); itTechBegin != batches.end(); itTechBegin = itTechEnd)
|
||||
{
|
||||
@ -156,7 +153,18 @@ void CDecalRData::RenderDecals(
|
||||
|
||||
for (int pass = 0; pass < numPasses; ++pass)
|
||||
{
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
techBase->GetGraphicsPipelineStateDesc(pass);
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
techBase->BeginPass(pass);
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
const CShaderProgramPtr& shader = techBase->GetShader(pass);
|
||||
TerrainRenderer::PrepareShader(shader, shadow);
|
||||
|
||||
@ -216,8 +224,6 @@ void CDecalRData::RenderDecals(
|
||||
}
|
||||
|
||||
CVertexBuffer::Unbind();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void CDecalRData::BuildVertexData()
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -21,8 +21,11 @@
|
||||
#include "graphics/RenderableObject.h"
|
||||
#include "maths/Vector2D.h"
|
||||
#include "maths/Vector3D.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/VertexBufferManager.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class CModelDecal;
|
||||
class CShaderDefines;
|
||||
class CSimulation2;
|
||||
@ -37,6 +40,7 @@ public:
|
||||
void Update(CSimulation2* simulation);
|
||||
|
||||
static void RenderDecals(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CDecalRData*>& decals, const CShaderDefines& context, ShadowMap* shadow);
|
||||
|
||||
CModelDecal* GetDecal() { return m_Decal; }
|
||||
|
@ -345,7 +345,9 @@ struct SMRCompareTechBucket
|
||||
}
|
||||
};
|
||||
|
||||
void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags)
|
||||
void ShaderModelRenderer::Render(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags)
|
||||
{
|
||||
if (m->submissions[cullGroup].empty())
|
||||
return;
|
||||
@ -626,6 +628,8 @@ void ShaderModelRenderer::Render(const RenderModifierPtr& modifier, const CShade
|
||||
for (int pass = 0; pass < currentTech->GetNumPasses(); ++pass)
|
||||
{
|
||||
currentTech->BeginPass(pass);
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
currentTech->GetGraphicsPipelineStateDesc(pass));
|
||||
|
||||
const CShaderProgramPtr& shader = currentTech->GetShader(pass);
|
||||
int streamflags = shader->GetStreamFlags();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -29,6 +29,7 @@
|
||||
#include "graphics/MeshManager.h"
|
||||
#include "graphics/RenderableObject.h"
|
||||
#include "graphics/SColor.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
|
||||
class RenderModifier;
|
||||
@ -157,7 +158,9 @@ public:
|
||||
* If flags is non-zero, only models that contain flags in their
|
||||
* CModel::GetFlags() are rendered.
|
||||
*/
|
||||
virtual void Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags) = 0;
|
||||
virtual void Render(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags) = 0;
|
||||
|
||||
/**
|
||||
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
||||
@ -264,7 +267,9 @@ public:
|
||||
virtual void Submit(int cullGroup, CModel* model);
|
||||
virtual void PrepareModels();
|
||||
virtual void EndFrame();
|
||||
virtual void Render(const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags);
|
||||
virtual void Render(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const RenderModifierPtr& modifier, const CShaderDefines& context, int cullGroup, int flags);
|
||||
|
||||
private:
|
||||
struct ShaderModelRendererInternals;
|
||||
|
@ -378,7 +378,6 @@ void OverlayRenderer::RenderOverlaysBeforeWater()
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement OverlayRenderer::RenderOverlaysBeforeWater for GLES
|
||||
#else
|
||||
glEnable(GL_BLEND);
|
||||
// Ignore z so that we draw behind terrain (but don't disable GL_DEPTH_TEST
|
||||
// since we still want to write to the z buffer)
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
@ -392,20 +391,20 @@ void OverlayRenderer::RenderOverlaysBeforeWater()
|
||||
}
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDisable(GL_BLEND);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderOverlaysAfterWater()
|
||||
void OverlayRenderer::RenderOverlaysAfterWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
PROFILE3_GPU("overlays (after)");
|
||||
|
||||
RenderTexturedOverlayLines();
|
||||
RenderQuadOverlays();
|
||||
RenderSphereOverlays();
|
||||
RenderTexturedOverlayLines(deviceCommandContext);
|
||||
RenderQuadOverlays(deviceCommandContext);
|
||||
RenderSphereOverlays(deviceCommandContext);
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderTexturedOverlayLines()
|
||||
void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement OverlayRenderer::RenderTexturedOverlayLines for GLES
|
||||
@ -417,7 +416,6 @@ void OverlayRenderer::RenderTexturedOverlayLines()
|
||||
ogl_WarnIfError();
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(0);
|
||||
|
||||
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
|
||||
@ -427,7 +425,17 @@ void OverlayRenderer::RenderTexturedOverlayLines()
|
||||
CShaderTechniquePtr shaderTechTexLineNormal = GetOverlayLineShaderTechnique(m->defsOverlayLineNormal);
|
||||
if (shaderTechTexLineNormal)
|
||||
{
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
shaderTechTexLineNormal->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
shaderTechTexLineNormal->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr shaderTexLineNormal = shaderTechTexLineNormal->GetShader();
|
||||
|
||||
@ -447,7 +455,17 @@ void OverlayRenderer::RenderTexturedOverlayLines()
|
||||
CShaderTechniquePtr shaderTechTexLineAlwaysVisible = GetOverlayLineShaderTechnique(m->defsOverlayLineAlwaysVisible);
|
||||
if (shaderTechTexLineAlwaysVisible)
|
||||
{
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
shaderTechTexLineAlwaysVisible->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
shaderTechTexLineAlwaysVisible->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr shaderTexLineAlwaysVisible = shaderTechTexLineAlwaysVisible->GetShader();
|
||||
|
||||
@ -472,10 +490,9 @@ void OverlayRenderer::RenderTexturedOverlayLines()
|
||||
CVertexBuffer::Unbind();
|
||||
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shader, bool alwaysVisible)
|
||||
void OverlayRenderer::RenderTexturedOverlayLines(const CShaderProgramPtr& shader, bool alwaysVisible)
|
||||
{
|
||||
#if !CONFIG2_GLES
|
||||
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
|
||||
@ -498,7 +515,8 @@ void OverlayRenderer::RenderTexturedOverlayLines(CShaderProgramPtr shader, bool
|
||||
#endif
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderQuadOverlays()
|
||||
void OverlayRenderer::RenderQuadOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement OverlayRenderer::RenderQuadOverlays for GLES
|
||||
@ -512,7 +530,17 @@ void OverlayRenderer::RenderQuadOverlays()
|
||||
if (!shaderTech)
|
||||
return;
|
||||
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
shaderTech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
shaderTech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
|
||||
@ -522,7 +550,6 @@ void OverlayRenderer::RenderQuadOverlays()
|
||||
#endif
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(0);
|
||||
|
||||
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
|
||||
@ -582,7 +609,6 @@ void OverlayRenderer::RenderQuadOverlays()
|
||||
CVertexBuffer::Unbind();
|
||||
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
#if !CONFIG2_GLES
|
||||
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
|
||||
@ -590,11 +616,14 @@ void OverlayRenderer::RenderQuadOverlays()
|
||||
#endif
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera)
|
||||
void OverlayRenderer::RenderForegroundOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CCamera& viewCamera)
|
||||
{
|
||||
PROFILE3_GPU("overlays (fg)");
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(viewCamera);
|
||||
#warning TODO: implement OverlayRenderer::RenderForegroundOverlays for GLES
|
||||
#else
|
||||
@ -602,14 +631,24 @@ void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
CVector3D right = -viewCamera.GetOrientation().GetLeft();
|
||||
CVector3D up = viewCamera.GetOrientation().GetUp();
|
||||
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_foreground_overlay);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
tech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
tech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
|
||||
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
@ -644,7 +683,6 @@ void OverlayRenderer::RenderForegroundOverlays(const CCamera& viewCamera)
|
||||
tech->EndPass();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (g_Renderer.GetSceneRenderer().GetOverlayRenderMode() == WIREFRAME)
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
@ -712,24 +750,36 @@ void OverlayRendererInternals::GenerateSphere()
|
||||
TessellateSphere(sphereVertexes, sphereIndexes, 3);
|
||||
}
|
||||
|
||||
void OverlayRenderer::RenderSphereOverlays()
|
||||
void OverlayRenderer::RenderSphereOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
PROFILE3_GPU("overlays (spheres)");
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
#warning TODO: implement OverlayRenderer::RenderSphereOverlays for GLES
|
||||
#else
|
||||
if (m->spheres.empty())
|
||||
return;
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glDepthMask(0);
|
||||
|
||||
CShaderProgramPtr shader;
|
||||
CShaderTechniquePtr tech;
|
||||
|
||||
tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
tech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
tech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
shader = tech->GetShader();
|
||||
|
||||
m->GenerateSphere();
|
||||
@ -759,6 +809,5 @@ void OverlayRenderer::RenderSphereOverlays()
|
||||
tech->EndPass();
|
||||
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
#define INCLUDED_OVERLAYRENDERER
|
||||
|
||||
#include "graphics/ShaderProgramPtr.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
|
||||
struct SOverlayLine;
|
||||
struct SOverlayTexturedLine;
|
||||
@ -106,14 +107,16 @@ public:
|
||||
* (i.e. rendered behind other objects in the normal 3D way)
|
||||
* and should be drawn after water (i.e. may be visible on top of the water)
|
||||
*/
|
||||
void RenderOverlaysAfterWater();
|
||||
void RenderOverlaysAfterWater(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
/**
|
||||
* Render all the submitted overlays that should appear on top of everything
|
||||
* in the world.
|
||||
* @param viewCamera camera to be used for billboard computations
|
||||
*/
|
||||
void RenderForegroundOverlays(const CCamera& viewCamera);
|
||||
void RenderForegroundOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CCamera& viewCamera);
|
||||
|
||||
/// Small vertical offset of overlays from terrain to prevent visual glitches
|
||||
static const float OVERLAY_VOFFSET;
|
||||
@ -125,7 +128,7 @@ private:
|
||||
* renders textured overlay lines batched according to their visibility status by delegating
|
||||
* to RenderTexturedOverlayLines(CShaderProgramPtr, bool).
|
||||
*/
|
||||
void RenderTexturedOverlayLines();
|
||||
void RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
/**
|
||||
* Helper method; renders those overlay lines currently registered in the internals (i.e.
|
||||
@ -133,17 +136,17 @@ private:
|
||||
* batch rendering the overlay lines according to their alwaysVisible status, as this
|
||||
* requires a separate shader to be used.
|
||||
*/
|
||||
void RenderTexturedOverlayLines(CShaderProgramPtr shader, bool alwaysVisible);
|
||||
void RenderTexturedOverlayLines(const CShaderProgramPtr& shader, bool alwaysVisible);
|
||||
|
||||
/**
|
||||
* Helper method; batch-renders all registered quad overlays, batched by their texture for effiency.
|
||||
*/
|
||||
void RenderQuadOverlays();
|
||||
void RenderQuadOverlays(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
/**
|
||||
* Helper method; batch-renders all sphere quad overlays.
|
||||
*/
|
||||
void RenderSphereOverlays();
|
||||
void RenderSphereOverlays(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
private:
|
||||
OverlayRendererInternals* m;
|
||||
|
@ -32,7 +32,10 @@
|
||||
struct ParticleRendererInternals
|
||||
{
|
||||
int frameNumber;
|
||||
CShaderTechniquePtr tech;
|
||||
CShaderTechniquePtr techAdd;
|
||||
CShaderTechniquePtr techSubtract;
|
||||
CShaderTechniquePtr techOverlay;
|
||||
CShaderTechniquePtr techMultiply;
|
||||
CShaderTechniquePtr techSolid;
|
||||
std::vector<CParticleEmitter*> emitters[CSceneRenderer::CULL_MAX];
|
||||
};
|
||||
@ -87,9 +90,12 @@ void ParticleRenderer::PrepareForRendering(const CShaderDefines& context)
|
||||
|
||||
// Can't load the shader in the constructor because it's called before the
|
||||
// renderer initialisation is complete, so load it the first time through here
|
||||
if (!m->tech)
|
||||
if (!m->techSolid)
|
||||
{
|
||||
m->tech = g_Renderer.GetShaderManager().LoadEffect(str_particle, context);
|
||||
m->techAdd = g_Renderer.GetShaderManager().LoadEffect(str_particle_add, context);
|
||||
m->techSubtract = g_Renderer.GetShaderManager().LoadEffect(str_particle_subtract, context);
|
||||
m->techOverlay = g_Renderer.GetShaderManager().LoadEffect(str_particle_overlay, context);
|
||||
m->techMultiply = g_Renderer.GetShaderManager().LoadEffect(str_particle_multiply, context);
|
||||
m->techSolid = g_Renderer.GetShaderManager().LoadEffect(str_particle_solid, context);
|
||||
}
|
||||
|
||||
@ -118,32 +124,45 @@ void ParticleRenderer::PrepareForRendering(const CShaderDefines& context)
|
||||
// TODO: should batch by texture here when possible, maybe
|
||||
}
|
||||
|
||||
void ParticleRenderer::RenderParticles(int cullGroup, bool solidColor)
|
||||
void ParticleRenderer::RenderParticles(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, bool solidColor)
|
||||
{
|
||||
const CShaderTechniquePtr& tech = solidColor ? m->techSolid : m->tech;
|
||||
|
||||
tech->BeginPass();
|
||||
|
||||
const CShaderProgramPtr& shader = tech->GetShader();
|
||||
|
||||
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
shader->Uniform(str_modelViewMatrix, g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse());
|
||||
|
||||
glDepthMask(0);
|
||||
|
||||
CShaderTechnique* lastTech = nullptr;
|
||||
for (CParticleEmitter* emitter : m->emitters[cullGroup])
|
||||
{
|
||||
emitter->Bind(shader);
|
||||
emitter->RenderArray(shader);
|
||||
CShaderTechnique* currentTech = nullptr;
|
||||
if (solidColor)
|
||||
solidColor = m->techSolid.get();
|
||||
else
|
||||
{
|
||||
switch (emitter->m_Type->m_BlendMode)
|
||||
{
|
||||
case CParticleEmitterType::BlendMode::ADD: currentTech = m->techAdd.get(); break;
|
||||
case CParticleEmitterType::BlendMode::SUBTRACT: currentTech = m->techSubtract.get(); break;
|
||||
case CParticleEmitterType::BlendMode::OVERLAY: currentTech = m->techOverlay.get(); break;
|
||||
case CParticleEmitterType::BlendMode::MULTIPLY: currentTech = m->techMultiply.get(); break;
|
||||
}
|
||||
}
|
||||
ENSURE(currentTech);
|
||||
if (lastTech != currentTech)
|
||||
{
|
||||
lastTech = currentTech;
|
||||
lastTech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(lastTech->GetGraphicsPipelineStateDesc());
|
||||
|
||||
const CShaderProgramPtr& shader = lastTech->GetShader();
|
||||
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
shader->Uniform(str_modelViewMatrix, g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse());
|
||||
}
|
||||
emitter->Bind(lastTech->GetShader());
|
||||
emitter->RenderArray(lastTech->GetShader());
|
||||
}
|
||||
|
||||
if (lastTech)
|
||||
lastTech->EndPass();
|
||||
|
||||
CVertexBuffer::Unbind();
|
||||
|
||||
glBlendEquationEXT(GL_FUNC_ADD);
|
||||
|
||||
glDepthMask(1);
|
||||
|
||||
tech->EndPass();
|
||||
}
|
||||
|
||||
void ParticleRenderer::RenderBounds(int cullGroup)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -18,6 +18,8 @@
|
||||
#ifndef INCLUDED_PARTICLERENDERER
|
||||
#define INCLUDED_PARTICLERENDERER
|
||||
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
|
||||
class CParticleEmitter;
|
||||
class CShaderDefines;
|
||||
struct ParticleRendererInternals;
|
||||
@ -53,7 +55,9 @@ public:
|
||||
/**
|
||||
* Render all the submitted particles.
|
||||
*/
|
||||
void RenderParticles(int cullGroup, bool solidColor = false);
|
||||
void RenderParticles(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, bool solidColor = false);
|
||||
|
||||
/**
|
||||
* Render bounding boxes for all the submitted emitters.
|
||||
|
@ -692,6 +692,7 @@ using TextureBatches = PooledBatchMap<CTerrainTextureEntry*, VertexBufferBatches
|
||||
using ShaderTechniqueBatches = PooledBatchMap<CShaderTechniquePtr, TextureBatches>;
|
||||
|
||||
void CPatchRData::RenderBases(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow)
|
||||
{
|
||||
PROFILE3("render terrain bases");
|
||||
@ -748,6 +749,8 @@ void CPatchRData::RenderBases(
|
||||
for (int pass = 0; pass < numPasses; ++pass)
|
||||
{
|
||||
techBase->BeginPass(pass);
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
techBase->GetGraphicsPipelineStateDesc(pass));
|
||||
const CShaderProgramPtr& shader = techBase->GetShader(pass);
|
||||
TerrainRenderer::PrepareShader(shader, shadow);
|
||||
|
||||
@ -838,6 +841,7 @@ struct SBlendStackItem
|
||||
};
|
||||
|
||||
void CPatchRData::RenderBlends(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow)
|
||||
{
|
||||
PROFILE3("render terrain blends");
|
||||
@ -933,9 +937,6 @@ void CPatchRData::RenderBlends(
|
||||
|
||||
PROFILE_END("compute batches");
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
CVertexBuffer* lastVB = nullptr;
|
||||
CShaderProgramPtr previousShader;
|
||||
for (BatchesStack::iterator itTechBegin = batches.begin(), itTechEnd = batches.begin(); itTechBegin != batches.end(); itTechBegin = itTechEnd)
|
||||
@ -947,7 +948,18 @@ void CPatchRData::RenderBlends(
|
||||
const int numPasses = techBase->GetNumPasses();
|
||||
for (int pass = 0; pass < numPasses; ++pass)
|
||||
{
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
techBase->GetGraphicsPipelineStateDesc(pass);
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
techBase->BeginPass(pass);
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
const CShaderProgramPtr& shader = techBase->GetShader(pass);
|
||||
TerrainRenderer::PrepareShader(shader, shadow);
|
||||
|
||||
@ -1019,8 +1031,6 @@ void CPatchRData::RenderBlends(
|
||||
}
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
CVertexBuffer::Unbind();
|
||||
}
|
||||
|
||||
@ -1370,7 +1380,7 @@ void CPatchRData::BuildWater()
|
||||
}
|
||||
}
|
||||
|
||||
void CPatchRData::RenderWaterSurface(CShaderProgramPtr& shader, const bool bindWaterData)
|
||||
void CPatchRData::RenderWaterSurface(const CShaderProgramPtr& shader, const bool bindWaterData)
|
||||
{
|
||||
ASSERT(m_UpdateFlags == 0);
|
||||
|
||||
@ -1398,7 +1408,7 @@ void CPatchRData::RenderWaterSurface(CShaderProgramPtr& shader, const bool bindW
|
||||
CVertexBuffer::Unbind();
|
||||
}
|
||||
|
||||
void CPatchRData::RenderWaterShore(CShaderProgramPtr& shader)
|
||||
void CPatchRData::RenderWaterShore(const CShaderProgramPtr& shader)
|
||||
{
|
||||
ASSERT(m_UpdateFlags == 0);
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "graphics/ShaderProgramPtr.h"
|
||||
#include "maths/Vector2D.h"
|
||||
#include "maths/Vector3D.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/VertexBufferManager.h"
|
||||
|
||||
#include <vector>
|
||||
@ -47,16 +48,18 @@ public:
|
||||
void RenderOutline();
|
||||
void RenderPriorities(CTextRenderer& textRenderer);
|
||||
|
||||
void RenderWaterSurface(CShaderProgramPtr& shader, const bool bindWaterData);
|
||||
void RenderWaterShore(CShaderProgramPtr& shader);
|
||||
void RenderWaterSurface(const CShaderProgramPtr& shader, const bool bindWaterData);
|
||||
void RenderWaterShore(const CShaderProgramPtr& shader);
|
||||
|
||||
CPatch* GetPatch() { return m_Patch; }
|
||||
|
||||
const CBoundingBoxAligned& GetWaterBounds() const { return m_WaterBounds; }
|
||||
|
||||
static void RenderBases(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow);
|
||||
static void RenderBlends(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow);
|
||||
static void RenderStreams(const std::vector<CPatchRData*>& patches, const CShaderProgramPtr& shader, int streamflags);
|
||||
static void RenderSides(const std::vector<CPatchRData*>& patches, const CShaderProgramPtr& shader);
|
||||
|
@ -209,6 +209,7 @@ void CPostprocManager::RecreateBuffers()
|
||||
|
||||
|
||||
void CPostprocManager::ApplyBlurDownscale2x(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
Renderer::Backend::GL::CTexture* inTex, Renderer::Backend::GL::CTexture* outTex, int inWidth, int inHeight)
|
||||
{
|
||||
// Bind inTex to framebuffer for rendering.
|
||||
@ -221,7 +222,9 @@ void CPostprocManager::ApplyBlurDownscale2x(
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines);
|
||||
|
||||
tech->BeginPass();
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
tech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& shader = tech->GetShader();
|
||||
|
||||
shader->BindTexture(str_renderedTex, inTex);
|
||||
|
||||
@ -260,6 +263,7 @@ void CPostprocManager::ApplyBlurDownscale2x(
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyBlurGauss(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
Renderer::Backend::GL::CTexture* inOutTex, Renderer::Backend::GL::CTexture* tempTex, int inWidth, int inHeight)
|
||||
{
|
||||
// Set tempTex as our rendering target.
|
||||
@ -272,6 +276,8 @@ void CPostprocManager::ApplyBlurGauss(
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_bloom, defines2);
|
||||
|
||||
tech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
tech->GetGraphicsPipelineStateDesc());
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
shader->BindTexture(str_renderedTex, inOutTex);
|
||||
shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
|
||||
@ -337,17 +343,16 @@ void CPostprocManager::ApplyBlurGauss(
|
||||
tech->EndPass();
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyBlur()
|
||||
void CPostprocManager::ApplyBlur(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
int width = m_Width, height = m_Height;
|
||||
|
||||
#define SCALE_AND_BLUR(tex1, tex2, temptex) \
|
||||
ApplyBlurDownscale2x((tex1).get(), (tex2).get(), width, height); \
|
||||
ApplyBlurDownscale2x(deviceCommandContext, (tex1).get(), (tex2).get(), width, height); \
|
||||
width /= 2; \
|
||||
height /= 2; \
|
||||
ApplyBlurGauss((tex2).get(), (temptex).get(), width, height);
|
||||
ApplyBlurGauss(deviceCommandContext, (tex2).get(), (temptex).get(), width, height);
|
||||
|
||||
// We do the same thing for each scale, incrementally adding more and more blur.
|
||||
SCALE_AND_BLUR(m_WhichBuffer ? m_ColorTex1 : m_ColorTex2, m_BlurTex2a, m_BlurTex2b);
|
||||
@ -402,7 +407,9 @@ void CPostprocManager::ReleaseRenderOutput()
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
|
||||
void CPostprocManager::ApplyEffect(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderTechniquePtr& shaderTech1, int pass)
|
||||
{
|
||||
// select the other FBO for rendering
|
||||
if (!m_WhichBuffer)
|
||||
@ -414,7 +421,9 @@ void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
shaderTech1->BeginPass(pass);
|
||||
CShaderProgramPtr shader = shaderTech1->GetShader(pass);
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
shaderTech1->GetGraphicsPipelineStateDesc(pass));
|
||||
const CShaderProgramPtr& shader = shaderTech1->GetShader(pass);
|
||||
|
||||
// Use the textures from the current FBO as input to the shader.
|
||||
// We also bind a bunch of other textures and parameters, but since
|
||||
@ -475,7 +484,8 @@ void CPostprocManager::ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass)
|
||||
m_WhichBuffer = !m_WhichBuffer;
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyPostproc()
|
||||
void CPostprocManager::ApplyPostproc(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
ENSURE(m_IsInitialized);
|
||||
|
||||
@ -507,22 +517,22 @@ void CPostprocManager::ApplyPostproc()
|
||||
{
|
||||
// First render blur textures. Note that this only happens ONLY ONCE, before any effects are applied!
|
||||
// (This may need to change depending on future usage, however that will have a fps hit)
|
||||
ApplyBlur();
|
||||
ApplyBlur(deviceCommandContext);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PingFbo);
|
||||
for (int pass = 0; pass < m_PostProcTech->GetNumPasses(); ++pass)
|
||||
ApplyEffect(m_PostProcTech, pass);
|
||||
ApplyEffect(deviceCommandContext, m_PostProcTech, pass);
|
||||
}
|
||||
|
||||
if (hasAA)
|
||||
{
|
||||
for (int pass = 0; pass < m_AATech->GetNumPasses(); ++pass)
|
||||
ApplyEffect(m_AATech, pass);
|
||||
ApplyEffect(deviceCommandContext, m_AATech, pass);
|
||||
}
|
||||
|
||||
if (hasSharp)
|
||||
{
|
||||
for (int pass = 0; pass < m_SharpTech->GetNumPasses(); ++pass)
|
||||
ApplyEffect(m_SharpTech, pass);
|
||||
ApplyEffect(deviceCommandContext, m_SharpTech, pass);
|
||||
}
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_PongFbo);
|
||||
@ -734,6 +744,7 @@ void CPostprocManager::ResolveMultisampleFramebuffer()
|
||||
#warning TODO: implement PostprocManager for GLES
|
||||
|
||||
void ApplyBlurDownscale2x(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext),
|
||||
Renderer::Backend::GL::CTexture* UNUSED(inTex),
|
||||
Renderer::Backend::GL::CTexture* UNUSED(outTex),
|
||||
int UNUSED(inWidth), int UNUSED(inHeight))
|
||||
@ -741,13 +752,16 @@ void ApplyBlurDownscale2x(
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyBlurGauss(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext),
|
||||
Renderer::Backend::GL::CTexture* UNUSED(inOutTex),
|
||||
Renderer::Backend::GL::CTexture* UNUSED(tempTex),
|
||||
int UNUSED(inWidth), int UNUSED(inHeight))
|
||||
{
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyEffect(CShaderTechniquePtr &UNUSED(shaderTech1), int UNUSED(pass))
|
||||
void CPostprocManager::ApplyEffect(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext),
|
||||
const CShaderTechniquePtr& UNUSED(shaderTech1), int UNUSED(pass))
|
||||
{
|
||||
}
|
||||
|
||||
@ -804,7 +818,8 @@ void CPostprocManager::CaptureRenderOutput()
|
||||
{
|
||||
}
|
||||
|
||||
void CPostprocManager::ApplyPostproc()
|
||||
void CPostprocManager::ApplyPostproc(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -21,6 +21,7 @@
|
||||
#include "graphics/ShaderTechniquePtr.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/backend/gl/Texture.h"
|
||||
|
||||
#include <vector>
|
||||
@ -65,7 +66,8 @@ public:
|
||||
// First renders blur textures, then calls ApplyEffect for each effect pass,
|
||||
// ping-ponging the buffers at each step.
|
||||
// @note CPostprocManager must be initialized first
|
||||
void ApplyPostproc();
|
||||
void ApplyPostproc(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
// Blits the final postprocessed texture to the system framebuffer. The system framebuffer
|
||||
// is selected as the output buffer. Should be called before silhouette rendering.
|
||||
@ -125,22 +127,29 @@ private:
|
||||
bool m_IsInitialized;
|
||||
|
||||
// Creates blur textures at various scales, for bloom, DOF, etc.
|
||||
void ApplyBlur();
|
||||
void ApplyBlur(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
// High quality GPU image scaling to half size. outTex must have exactly half the size
|
||||
// of inTex. inWidth and inHeight are the dimensions of inTex in texels.
|
||||
void ApplyBlurDownscale2x(Renderer::Backend::GL::CTexture* inTex, Renderer::Backend::GL::CTexture* outTex, int inWidth, int inHeight);
|
||||
void ApplyBlurDownscale2x(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
Renderer::Backend::GL::CTexture* inTex, Renderer::Backend::GL::CTexture* outTex, int inWidth, int inHeight);
|
||||
|
||||
// GPU-based Gaussian blur in two passes. inOutTex contains the input image and will be filled
|
||||
// with the blurred image. tempTex must have the same size as inOutTex.
|
||||
// inWidth and inHeight are the dimensions of the images in texels.
|
||||
void ApplyBlurGauss(Renderer::Backend::GL::CTexture* inOutTex, Renderer::Backend::GL::CTexture* tempTex, int inWidth, int inHeight);
|
||||
void ApplyBlurGauss(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
Renderer::Backend::GL::CTexture* inOutTex, Renderer::Backend::GL::CTexture* tempTex, int inWidth, int inHeight);
|
||||
|
||||
// Applies a pass of a given effect to the entire current framebuffer. The shader is
|
||||
// provided with a number of general-purpose variables, including the rendered screen so far,
|
||||
// the depth buffer, a number of blur textures, the screen size, the zNear/zFar planes and
|
||||
// some other parameters used by the optional bloom/HDR pass.
|
||||
void ApplyEffect(CShaderTechniquePtr &shaderTech1, int pass);
|
||||
void ApplyEffect(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderTechniquePtr& shaderTech1, int pass);
|
||||
|
||||
// Delete all allocated buffers/textures from GPU memory.
|
||||
void Cleanup();
|
||||
|
@ -471,6 +471,7 @@ void CRenderer::RenderFrame(const bool needsPresent)
|
||||
else
|
||||
RenderFrameImpl(true, true);
|
||||
|
||||
m->deviceCommandContext->Flush();
|
||||
if (needsPresent)
|
||||
g_VideoMode.GetBackendDevice()->Present();
|
||||
}
|
||||
@ -708,6 +709,8 @@ void CRenderer::RenderBigScreenShot(const bool needsPresent)
|
||||
void* src = static_cast<char*>(tileData) + y * tileWidth * bpp / 8;
|
||||
memcpy(dest, src, tileWidth * bpp / 8);
|
||||
}
|
||||
|
||||
m->deviceCommandContext->Flush();
|
||||
if (needsPresent)
|
||||
g_VideoMode.GetBackendDevice()->Present();
|
||||
}
|
||||
|
@ -142,7 +142,9 @@ public:
|
||||
/**
|
||||
* Renders all non-alpha-blended models with the given context.
|
||||
*/
|
||||
void CallModelRenderers(const CShaderDefines& context, int cullGroup, int flags)
|
||||
void CallModelRenderers(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, int flags)
|
||||
{
|
||||
CShaderDefines contextSkinned = context;
|
||||
if (g_RenderingOptions.GetGPUSkinning())
|
||||
@ -150,20 +152,22 @@ public:
|
||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||
contextSkinned.Add(str_USE_GPU_SKINNING, str_1);
|
||||
}
|
||||
Model.NormalSkinned->Render(Model.ModShader, contextSkinned, cullGroup, flags);
|
||||
Model.NormalSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags);
|
||||
|
||||
if (Model.NormalUnskinned != Model.NormalSkinned)
|
||||
{
|
||||
CShaderDefines contextUnskinned = context;
|
||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.NormalUnskinned->Render(Model.ModShader, contextUnskinned, cullGroup, flags);
|
||||
Model.NormalUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders all alpha-blended models with the given context.
|
||||
*/
|
||||
void CallTranspModelRenderers(const CShaderDefines& context, int cullGroup, int flags)
|
||||
void CallTranspModelRenderers(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, int flags)
|
||||
{
|
||||
CShaderDefines contextSkinned = context;
|
||||
if (g_RenderingOptions.GetGPUSkinning())
|
||||
@ -171,13 +175,13 @@ public:
|
||||
contextSkinned.Add(str_USE_INSTANCING, str_1);
|
||||
contextSkinned.Add(str_USE_GPU_SKINNING, str_1);
|
||||
}
|
||||
Model.TranspSkinned->Render(Model.ModShader, contextSkinned, cullGroup, flags);
|
||||
Model.TranspSkinned->Render(deviceCommandContext, Model.ModShader, contextSkinned, cullGroup, flags);
|
||||
|
||||
if (Model.TranspUnskinned != Model.TranspSkinned)
|
||||
{
|
||||
CShaderDefines contextUnskinned = context;
|
||||
contextUnskinned.Add(str_USE_INSTANCING, str_1);
|
||||
Model.TranspUnskinned->Render(Model.ModShader, contextUnskinned, cullGroup, flags);
|
||||
Model.TranspUnskinned->Render(deviceCommandContext, Model.ModShader, contextUnskinned, cullGroup, flags);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -297,7 +301,9 @@ void CSceneRenderer::SetSimulation(CSimulation2* simulation)
|
||||
m->terrainRenderer.SetSimulation(simulation);
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderShadowMap(const CShaderDefines& context)
|
||||
void CSceneRenderer::RenderShadowMap(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context)
|
||||
{
|
||||
PROFILE3_GPU("shadow map");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render shadow map");
|
||||
@ -318,20 +324,20 @@ void CSceneRenderer::RenderShadowMap(const CShaderDefines& context)
|
||||
PROFILE("render patches");
|
||||
glCullFace(GL_FRONT);
|
||||
glEnable(GL_CULL_FACE);
|
||||
m->terrainRenderer.RenderPatches(cullGroup);
|
||||
m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE("render models");
|
||||
m->CallModelRenderers(contextCast, cullGroup, MODELFLAG_CASTSHADOWS);
|
||||
m->CallModelRenderers(deviceCommandContext, contextCast, cullGroup, MODELFLAG_CASTSHADOWS);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE("render transparent models");
|
||||
// disable face-culling for two-sided models
|
||||
glDisable(GL_CULL_FACE);
|
||||
m->CallTranspModelRenderers(contextCast, cullGroup, MODELFLAG_CASTSHADOWS);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextCast, cullGroup, MODELFLAG_CASTSHADOWS);
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
@ -341,7 +347,9 @@ void CSceneRenderer::RenderShadowMap(const CShaderDefines& context)
|
||||
g_Renderer.SetViewport(m_ViewCamera.GetViewPort());
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderPatches(const CShaderDefines& context, int cullGroup)
|
||||
void CSceneRenderer::RenderPatches(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup)
|
||||
{
|
||||
PROFILE3_GPU("patches");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render patches");
|
||||
@ -358,7 +366,7 @@ void CSceneRenderer::RenderPatches(const CShaderDefines& context, int cullGroup)
|
||||
|
||||
// render all the patches, including blend pass
|
||||
const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities();
|
||||
m->terrainRenderer.RenderTerrainShader(context, cullGroup,
|
||||
m->terrainRenderer.RenderTerrainShader(deviceCommandContext, context, cullGroup,
|
||||
(capabilities.m_Shadows && g_RenderingOptions.GetShadows()) ? &m->shadow : 0);
|
||||
|
||||
#if !CONFIG2_GLES
|
||||
@ -378,7 +386,7 @@ void CSceneRenderer::RenderPatches(const CShaderDefines& context, int cullGroup)
|
||||
glLineWidth(2.0f);
|
||||
|
||||
// render tiles edges
|
||||
m->terrainRenderer.RenderPatches(cullGroup, CColor(0.5f, 0.5f, 1.0f, 1.0f));
|
||||
m->terrainRenderer.RenderPatches(deviceCommandContext, cullGroup, CColor(0.5f, 0.5f, 1.0f, 1.0f));
|
||||
|
||||
glLineWidth(4.0f);
|
||||
|
||||
@ -392,7 +400,9 @@ void CSceneRenderer::RenderPatches(const CShaderDefines& context, int cullGroup)
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderModels(const CShaderDefines& context, int cullGroup)
|
||||
void CSceneRenderer::RenderModels(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup)
|
||||
{
|
||||
PROFILE3_GPU("models");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render models");
|
||||
@ -406,7 +416,7 @@ void CSceneRenderer::RenderModels(const CShaderDefines& context, int cullGroup)
|
||||
}
|
||||
#endif
|
||||
|
||||
m->CallModelRenderers(context, cullGroup, flags);
|
||||
m->CallModelRenderers(deviceCommandContext, context, cullGroup, flags);
|
||||
|
||||
#if !CONFIG2_GLES
|
||||
if (m_ModelRenderMode == WIREFRAME)
|
||||
@ -420,14 +430,16 @@ void CSceneRenderer::RenderModels(const CShaderDefines& context, int cullGroup)
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
m->CallModelRenderers(contextWireframe, cullGroup, flags);
|
||||
m->CallModelRenderers(deviceCommandContext, contextWireframe, cullGroup, flags);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderTransparentModels(const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling)
|
||||
void CSceneRenderer::RenderTransparentModels(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling)
|
||||
{
|
||||
PROFILE3_GPU("transparent models");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render transparent models");
|
||||
@ -453,10 +465,10 @@ void CSceneRenderer::RenderTransparentModels(const CShaderDefines& context, int
|
||||
contextBlend.Add(str_ALPHABLEND_PASS_BLEND, str_1);
|
||||
|
||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_OPAQUE)
|
||||
m->CallTranspModelRenderers(contextOpaque, cullGroup, flags);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextOpaque, cullGroup, flags);
|
||||
|
||||
if (transparentMode == TRANSPARENT || transparentMode == TRANSPARENT_BLEND)
|
||||
m->CallTranspModelRenderers(contextBlend, cullGroup, flags);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextBlend, cullGroup, flags);
|
||||
|
||||
if (disableFaceCulling)
|
||||
glEnable(GL_CULL_FACE);
|
||||
@ -474,7 +486,7 @@ void CSceneRenderer::RenderTransparentModels(const CShaderDefines& context, int
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
m->CallTranspModelRenderers(contextWireframe, cullGroup, flags);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextWireframe, cullGroup, flags);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
@ -600,7 +612,9 @@ void CSceneRenderer::ComputeRefractionCamera(CCamera& camera, const CBoundingBox
|
||||
}
|
||||
|
||||
// RenderReflections: render the water reflections to the reflection texture
|
||||
void CSceneRenderer::RenderReflections(const CShaderDefines& context, const CBoundingBoxAligned& scissor)
|
||||
void CSceneRenderer::RenderReflections(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, const CBoundingBoxAligned& scissor)
|
||||
{
|
||||
PROFILE3_GPU("water reflections");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render water reflections");
|
||||
@ -641,17 +655,17 @@ void CSceneRenderer::RenderReflections(const CShaderDefines& context, const CBou
|
||||
|
||||
if (!g_RenderingOptions.GetWaterReflection())
|
||||
{
|
||||
m->skyManager.RenderSky();
|
||||
m->skyManager.RenderSky(deviceCommandContext);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Render terrain and models
|
||||
RenderPatches(context, CULL_REFLECTIONS);
|
||||
RenderPatches(deviceCommandContext, context, CULL_REFLECTIONS);
|
||||
ogl_WarnIfError();
|
||||
RenderModels(context, CULL_REFLECTIONS);
|
||||
RenderModels(deviceCommandContext, context, CULL_REFLECTIONS);
|
||||
ogl_WarnIfError();
|
||||
RenderTransparentModels(context, CULL_REFLECTIONS, TRANSPARENT, true);
|
||||
RenderTransparentModels(deviceCommandContext, context, CULL_REFLECTIONS, TRANSPARENT, true);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
glFrontFace(GL_CCW);
|
||||
@ -660,7 +674,7 @@ void CSceneRenderer::RenderReflections(const CShaderDefines& context, const CBou
|
||||
// so they don't need the inverted glFrontFace
|
||||
if (g_RenderingOptions.GetParticles())
|
||||
{
|
||||
RenderParticles(CULL_REFLECTIONS);
|
||||
RenderParticles(deviceCommandContext, CULL_REFLECTIONS);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
@ -674,7 +688,9 @@ void CSceneRenderer::RenderReflections(const CShaderDefines& context, const CBou
|
||||
}
|
||||
|
||||
// RenderRefractions: render the water refractions to the refraction texture
|
||||
void CSceneRenderer::RenderRefractions(const CShaderDefines& context, const CBoundingBoxAligned &scissor)
|
||||
void CSceneRenderer::RenderRefractions(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, const CBoundingBoxAligned &scissor)
|
||||
{
|
||||
PROFILE3_GPU("water refractions");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render water refractions");
|
||||
@ -717,11 +733,11 @@ void CSceneRenderer::RenderRefractions(const CShaderDefines& context, const CBou
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Render terrain and models
|
||||
RenderPatches(context, CULL_REFRACTIONS);
|
||||
RenderPatches(deviceCommandContext, context, CULL_REFRACTIONS);
|
||||
ogl_WarnIfError();
|
||||
RenderModels(context, CULL_REFRACTIONS);
|
||||
RenderModels(deviceCommandContext, context, CULL_REFRACTIONS);
|
||||
ogl_WarnIfError();
|
||||
RenderTransparentModels(context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE, false);
|
||||
RenderTransparentModels(deviceCommandContext, context, CULL_REFRACTIONS, TRANSPARENT_OPAQUE, false);
|
||||
ogl_WarnIfError();
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
@ -733,7 +749,9 @@ void CSceneRenderer::RenderRefractions(const CShaderDefines& context, const CBou
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderSilhouettes(const CShaderDefines& context)
|
||||
void CSceneRenderer::RenderSilhouettes(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context)
|
||||
{
|
||||
PROFILE3_GPU("silhouettes");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render water silhouettes");
|
||||
@ -764,18 +782,18 @@ void CSceneRenderer::RenderSilhouettes(const CShaderDefines& context)
|
||||
// protrude into the ground, only occlude with the back faces of the
|
||||
// terrain (so silhouettes will still display when behind hills)
|
||||
glCullFace(GL_FRONT);
|
||||
m->terrainRenderer.RenderPatches(CULL_SILHOUETTE_OCCLUDER);
|
||||
m->terrainRenderer.RenderPatches(deviceCommandContext, CULL_SILHOUETTE_OCCLUDER);
|
||||
glCullFace(GL_BACK);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE("render model occluders");
|
||||
m->CallModelRenderers(contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0);
|
||||
m->CallModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE("render transparent occluders");
|
||||
m->CallTranspModelRenderers(contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextOccluder, CULL_SILHOUETTE_OCCLUDER, 0);
|
||||
}
|
||||
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
@ -783,46 +801,42 @@ void CSceneRenderer::RenderSilhouettes(const CShaderDefines& context)
|
||||
|
||||
// Since we can't sort, we'll use the stencil buffer to ensure we only draw
|
||||
// a pixel once (using the color of whatever model happens to be drawn first).
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
|
||||
const float silhouetteAlpha = 0.75f;
|
||||
glBlendColorEXT(0, 0, 0, silhouetteAlpha);
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilFunc(GL_NOTEQUAL, 1, (GLuint)-1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
{
|
||||
PROFILE("render model casters");
|
||||
m->CallModelRenderers(contextDisplay, CULL_SILHOUETTE_CASTER, 0);
|
||||
m->CallModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE("render transparent casters");
|
||||
m->CallTranspModelRenderers(contextDisplay, CULL_SILHOUETTE_CASTER, 0);
|
||||
m->CallTranspModelRenderers(deviceCommandContext, contextDisplay, CULL_SILHOUETTE_CASTER, 0);
|
||||
}
|
||||
|
||||
// Restore state
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDisable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendColorEXT(0, 0, 0, 0);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void CSceneRenderer::RenderParticles(int cullGroup)
|
||||
void CSceneRenderer::RenderParticles(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup)
|
||||
{
|
||||
PROFILE3_GPU("particles");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render particles");
|
||||
|
||||
m->particleRenderer.RenderParticles(cullGroup);
|
||||
m->particleRenderer.RenderParticles(
|
||||
deviceCommandContext, cullGroup);
|
||||
|
||||
#if !CONFIG2_GLES
|
||||
if (m_ModelRenderMode == EDGED_FACES)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
m->particleRenderer.RenderParticles(true);
|
||||
m->particleRenderer.RenderParticles(
|
||||
deviceCommandContext, cullGroup, true);
|
||||
m->particleRenderer.RenderBounds(cullGroup);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
@ -873,7 +887,7 @@ void CSceneRenderer::RenderSubmissions(
|
||||
const CRenderer::Caps& capabilities = g_Renderer.GetCapabilities();
|
||||
if (capabilities.m_Shadows && g_RenderingOptions.GetShadows())
|
||||
{
|
||||
RenderShadowMap(context);
|
||||
RenderShadowMap(deviceCommandContext, context);
|
||||
}
|
||||
|
||||
ogl_WarnIfError();
|
||||
@ -885,12 +899,12 @@ void CSceneRenderer::RenderSubmissions(
|
||||
m->waterManager.UpdateQuality();
|
||||
|
||||
PROFILE3_GPU("water scissor");
|
||||
RenderReflections(context, waterScissor);
|
||||
RenderReflections(deviceCommandContext, context, waterScissor);
|
||||
|
||||
if (g_RenderingOptions.GetWaterRefraction())
|
||||
RenderRefractions(context, waterScissor);
|
||||
RenderRefractions(deviceCommandContext, context, waterScissor);
|
||||
|
||||
m->terrainRenderer.RenderWaterFoamOccluders(cullGroup);
|
||||
m->terrainRenderer.RenderWaterFoamOccluders(deviceCommandContext, cullGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,21 +926,21 @@ void CSceneRenderer::RenderSubmissions(
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
|
||||
m->skyManager.RenderSky();
|
||||
m->skyManager.RenderSky(deviceCommandContext);
|
||||
|
||||
// render submitted patches and models
|
||||
RenderPatches(context, cullGroup);
|
||||
RenderPatches(deviceCommandContext, context, cullGroup);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// render debug-related terrain overlays
|
||||
ITerrainOverlay::RenderOverlaysBeforeWater();
|
||||
ITerrainOverlay::RenderOverlaysBeforeWater(deviceCommandContext);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// render other debug-related overlays before water (so they can be seen when underwater)
|
||||
m->overlayRenderer.RenderOverlaysBeforeWater();
|
||||
ogl_WarnIfError();
|
||||
|
||||
RenderModels(context, cullGroup);
|
||||
RenderModels(deviceCommandContext, context, cullGroup);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// render water
|
||||
@ -935,30 +949,30 @@ void CSceneRenderer::RenderSubmissions(
|
||||
if (m->waterManager.WillRenderFancyWater())
|
||||
{
|
||||
// Render transparent stuff, but only the solid parts that can occlude block water.
|
||||
RenderTransparentModels(context, cullGroup, TRANSPARENT_OPAQUE, false);
|
||||
RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_OPAQUE, false);
|
||||
ogl_WarnIfError();
|
||||
|
||||
m->terrainRenderer.RenderWater(context, cullGroup, &m->shadow);
|
||||
m->terrainRenderer.RenderWater(deviceCommandContext, context, cullGroup, &m->shadow);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// Render transparent stuff again, but only the blended parts that overlap water.
|
||||
RenderTransparentModels(context, cullGroup, TRANSPARENT_BLEND, false);
|
||||
RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT_BLEND, false);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
else
|
||||
{
|
||||
m->terrainRenderer.RenderWater(context, cullGroup, &m->shadow);
|
||||
m->terrainRenderer.RenderWater(deviceCommandContext, context, cullGroup, &m->shadow);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// Render transparent stuff, so it can overlap models/terrain.
|
||||
RenderTransparentModels(context, cullGroup, TRANSPARENT, false);
|
||||
RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// render transparent stuff, so it can overlap models/terrain
|
||||
RenderTransparentModels(context, cullGroup, TRANSPARENT, false);
|
||||
RenderTransparentModels(deviceCommandContext, context, cullGroup, TRANSPARENT, false);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
@ -967,13 +981,13 @@ void CSceneRenderer::RenderSubmissions(
|
||||
ogl_WarnIfError();
|
||||
|
||||
// render some other overlays after water (so they can be displayed on top of water)
|
||||
m->overlayRenderer.RenderOverlaysAfterWater();
|
||||
m->overlayRenderer.RenderOverlaysAfterWater(deviceCommandContext);
|
||||
ogl_WarnIfError();
|
||||
|
||||
// particles are transparent so render after water
|
||||
if (g_RenderingOptions.GetParticles())
|
||||
{
|
||||
RenderParticles(cullGroup);
|
||||
RenderParticles(deviceCommandContext, cullGroup);
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
@ -982,13 +996,13 @@ void CSceneRenderer::RenderSubmissions(
|
||||
if (g_Renderer.GetPostprocManager().IsMultisampleEnabled())
|
||||
g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer();
|
||||
|
||||
postprocManager.ApplyPostproc();
|
||||
postprocManager.ApplyPostproc(deviceCommandContext);
|
||||
postprocManager.ReleaseRenderOutput();
|
||||
}
|
||||
|
||||
if (g_RenderingOptions.GetSilhouettes())
|
||||
{
|
||||
RenderSilhouettes(context);
|
||||
RenderSilhouettes(deviceCommandContext, context);
|
||||
}
|
||||
|
||||
// render debug lines
|
||||
@ -998,13 +1012,13 @@ void CSceneRenderer::RenderSubmissions(
|
||||
if (g_RenderingOptions.GetDisplayShadowsFrustum())
|
||||
{
|
||||
m->shadow.RenderDebugBounds();
|
||||
m->shadow.RenderDebugTexture();
|
||||
m->shadow.RenderDebugTexture(deviceCommandContext);
|
||||
}
|
||||
|
||||
m->silhouetteRenderer.RenderDebugOverlays(m_ViewCamera);
|
||||
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext, m_ViewCamera);
|
||||
|
||||
// render overlays that should appear on top of all other objects
|
||||
m->overlayRenderer.RenderForegroundOverlays(m_ViewCamera);
|
||||
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
|
||||
ogl_WarnIfError();
|
||||
|
||||
}
|
||||
@ -1037,10 +1051,7 @@ void CSceneRenderer::DisplayFrustum()
|
||||
glDepthMask(0);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 0.25f), 2);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
g_Renderer.GetDebugRenderer().DrawCameraFrustum(m_CullCamera, CColor(1.0f, 1.0f, 1.0f, 1.0f), 2);
|
||||
@ -1247,7 +1258,7 @@ void CSceneRenderer::RenderScene(
|
||||
}
|
||||
|
||||
// Render the waves to the Fancy effects texture
|
||||
m->waterManager.RenderWaves(frustum);
|
||||
m->waterManager.RenderWaves(deviceCommandContext, frustum);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,22 +198,38 @@ protected:
|
||||
const CBoundingBoxAligned& waterScissor);
|
||||
|
||||
// patch rendering stuff
|
||||
void RenderPatches(const CShaderDefines& context, int cullGroup);
|
||||
void RenderPatches(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup);
|
||||
|
||||
// model rendering stuff
|
||||
void RenderModels(const CShaderDefines& context, int cullGroup);
|
||||
void RenderTransparentModels(const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling);
|
||||
void RenderModels(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup);
|
||||
void RenderTransparentModels(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ETransparentMode transparentMode, bool disableFaceCulling);
|
||||
|
||||
void RenderSilhouettes(const CShaderDefines& context);
|
||||
void RenderSilhouettes(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context);
|
||||
|
||||
void RenderParticles(int cullGroup);
|
||||
void RenderParticles(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup);
|
||||
|
||||
// shadow rendering stuff
|
||||
void RenderShadowMap(const CShaderDefines& context);
|
||||
void RenderShadowMap(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context);
|
||||
|
||||
// render water reflection and refraction textures
|
||||
void RenderReflections(const CShaderDefines& context, const CBoundingBoxAligned& scissor);
|
||||
void RenderRefractions(const CShaderDefines& context, const CBoundingBoxAligned& scissor);
|
||||
void RenderReflections(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, const CBoundingBoxAligned& scissor);
|
||||
void RenderRefractions(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, const CBoundingBoxAligned& scissor);
|
||||
|
||||
void ComputeReflectionCamera(CCamera& camera, const CBoundingBoxAligned& scissor) const;
|
||||
void ComputeRefractionCamera(CCamera& camera, const CBoundingBoxAligned& scissor) const;
|
||||
|
@ -736,16 +736,12 @@ void ShadowMap::RenderDebugBounds()
|
||||
|
||||
const CMatrix3D transform = g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection() * m->InvLightTransform;
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
g_Renderer.GetDebugRenderer().DrawBoundingBoxOutline(m->ShadowReceiverBound, CColor(1.0f, 1.0f, 0.0f, 1.0f), transform);
|
||||
|
||||
for (int cascade = 0; cascade < GetCascadeCount(); ++cascade)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
g_Renderer.GetDebugRenderer().DrawBoundingBox(m->Cascades[cascade].ShadowRenderBound, CColor(0.0f, 0.0f, 1.0f, 0.10f), transform);
|
||||
g_Renderer.GetDebugRenderer().DrawBoundingBoxOutline(m->Cascades[cascade].ShadowRenderBound, CColor(0.0f, 0.0f, 1.0f, 0.5f), transform);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
const CFrustum frustum = GetShadowCasterCullFrustum(cascade);
|
||||
// We don't have a function to create a brush directly from a frustum, so use
|
||||
@ -755,10 +751,8 @@ void ShadowMap::RenderDebugBounds()
|
||||
CBrush frustumBrush;
|
||||
brush.Intersect(frustum, frustumBrush);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
g_Renderer.GetDebugRenderer().DrawBrush(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.1f));
|
||||
g_Renderer.GetDebugRenderer().DrawBrushOutline(frustumBrush, CColor(1.0f, 0.0f, 0.0f, 0.5f));
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
@ -767,7 +761,8 @@ void ShadowMap::RenderDebugBounds()
|
||||
ogl_WarnIfError();
|
||||
}
|
||||
|
||||
void ShadowMap::RenderDebugTexture()
|
||||
void ShadowMap::RenderDebugTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
if (!m->Texture)
|
||||
return;
|
||||
@ -783,7 +778,10 @@ void ShadowMap::RenderDebugTexture()
|
||||
|
||||
CShaderTechniquePtr texTech = g_Renderer.GetShaderManager().LoadEffect(str_canvas2d);
|
||||
texTech->BeginPass();
|
||||
CShaderProgramPtr texShader = texTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
texTech->GetGraphicsPipelineStateDesc());
|
||||
|
||||
const CShaderProgramPtr& texShader = texTech->GetShader();
|
||||
|
||||
texShader->Uniform(str_transform, GetDefaultGuiMatrix());
|
||||
texShader->BindTexture(str_tex, m->Texture.get());
|
||||
@ -792,11 +790,13 @@ void ShadowMap::RenderDebugTexture()
|
||||
texShader->Uniform(str_grayscaleFactor, 0.0f);
|
||||
|
||||
float s = 256.f;
|
||||
float boxVerts[] = {
|
||||
float boxVerts[] =
|
||||
{
|
||||
0,0, 0,s, s,0,
|
||||
s,0, 0,s, s,s
|
||||
};
|
||||
float boxUV[] = {
|
||||
float boxUV[] =
|
||||
{
|
||||
0,0, 0,1, 1,0,
|
||||
1,0, 0,1, 1,1
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "graphics/ShaderProgramPtr.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
|
||||
class CBoundingBoxAligned;
|
||||
class CCamera;
|
||||
@ -137,7 +138,8 @@ public:
|
||||
/**
|
||||
* Visualize shadow map texture to help in debugging.
|
||||
*/
|
||||
void RenderDebugTexture();
|
||||
void RenderDebugTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
private:
|
||||
ShadowMapInternals* m;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -443,7 +443,9 @@ void SilhouetteRenderer::RenderSubmitCasters(SceneCollector& collector)
|
||||
collector.SubmitNonRecursive(m_VisibleModelCasters[i]);
|
||||
}
|
||||
|
||||
void SilhouetteRenderer::RenderDebugOverlays(const CCamera& UNUSED(camera))
|
||||
void SilhouetteRenderer::RenderDebugOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CCamera& UNUSED(camera))
|
||||
{
|
||||
if (m_DebugBounds.empty() && m_DebugRects.empty())
|
||||
return;
|
||||
@ -466,6 +468,8 @@ void SilhouetteRenderer::RenderDebugOverlays(const CCamera& UNUSED(camera))
|
||||
|
||||
CShaderTechniquePtr shaderTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
shaderTech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
shaderTech->GetGraphicsPipelineStateDesc());
|
||||
|
||||
CShaderProgramPtr shader = shaderTech->GetShader();
|
||||
shader->Uniform(str_transform, proj);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2014 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "graphics/Overlay.h"
|
||||
#include "maths/BoundingBoxAligned.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
|
||||
class CCamera;
|
||||
class CModel;
|
||||
@ -40,7 +41,9 @@ public:
|
||||
void RenderSubmitOccluders(SceneCollector& collector);
|
||||
void RenderSubmitCasters(SceneCollector& collector);
|
||||
|
||||
void RenderDebugOverlays(const CCamera& camera);
|
||||
void RenderDebugOverlays(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CCamera& camera);
|
||||
|
||||
void EndFrame();
|
||||
|
||||
|
@ -188,10 +188,12 @@ std::vector<CStrW> SkyManager::GetSkySets() const
|
||||
return skies;
|
||||
}
|
||||
|
||||
void SkyManager::RenderSky()
|
||||
void SkyManager::RenderSky(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
OGL_SCOPED_DEBUG_GROUP("Render Sky");
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
#warning TODO: implement SkyManager::RenderSky for GLES
|
||||
#else
|
||||
if (!m_RenderSky)
|
||||
@ -212,7 +214,9 @@ void SkyManager::RenderSky()
|
||||
CShaderTechniquePtr skytech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_sky_simple);
|
||||
skytech->BeginPass();
|
||||
CShaderProgramPtr shader = skytech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
skytech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& shader = skytech->GetShader();
|
||||
shader->BindTexture(str_baseTex, m_SkyCubeMap.get());
|
||||
|
||||
// Translate so the sky center is at the camera space origin.
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
/**
|
||||
* Render the sky.
|
||||
*/
|
||||
void RenderSky();
|
||||
void RenderSky(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
/**
|
||||
* Return the currently selected sky set name.
|
||||
|
@ -63,7 +63,8 @@ ITerrainOverlay::~ITerrainOverlay()
|
||||
}
|
||||
|
||||
|
||||
void ITerrainOverlay::RenderOverlaysBeforeWater()
|
||||
void ITerrainOverlay::RenderOverlaysBeforeWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
if (g_TerrainOverlayList.empty())
|
||||
return;
|
||||
@ -71,7 +72,7 @@ void ITerrainOverlay::RenderOverlaysBeforeWater()
|
||||
PROFILE3_GPU("terrain overlays (before)");
|
||||
|
||||
for (size_t i = 0; i < g_TerrainOverlayList.size(); ++i)
|
||||
g_TerrainOverlayList[i].first->RenderBeforeWater();
|
||||
g_TerrainOverlayList[i].first->RenderBeforeWater(deviceCommandContext);
|
||||
}
|
||||
|
||||
void ITerrainOverlay::RenderOverlaysAfterWater(
|
||||
@ -110,16 +111,16 @@ void TerrainOverlay::GetTileExtents(
|
||||
max_i_inclusive = max_j_inclusive = m_Terrain->GetTilesPerSide()-1;
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderBeforeWater()
|
||||
void TerrainOverlay::RenderBeforeWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
|
||||
{
|
||||
if (!m_Terrain)
|
||||
return; // should never happen, but let's play it safe
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
#warning TODO: implement TerrainOverlay::RenderOverlays for GLES
|
||||
#else
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDepthMask(GL_FALSE);
|
||||
// To ensure that outlines are drawn on top of the terrain correctly (and
|
||||
// don't Z-fight and flicker nastily), draw them as QUADS with the LINE
|
||||
@ -145,7 +146,7 @@ void TerrainOverlay::RenderBeforeWater()
|
||||
|
||||
for (m_j = min_j; m_j <= max_j; ++m_j)
|
||||
for (m_i = min_i; m_i <= max_i; ++m_i)
|
||||
ProcessTile(m_i, m_j);
|
||||
ProcessTile(deviceCommandContext, m_i, m_j);
|
||||
|
||||
EndRender();
|
||||
|
||||
@ -156,16 +157,19 @@ void TerrainOverlay::RenderBeforeWater()
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTile(const CColor& color, bool draw_hidden)
|
||||
void TerrainOverlay::RenderTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, bool draw_hidden)
|
||||
{
|
||||
RenderTile(color, draw_hidden, m_i, m_j);
|
||||
RenderTile(deviceCommandContext, color, draw_hidden, m_i, m_j);
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTile(const CColor& color, bool draw_hidden, ssize_t i, ssize_t j)
|
||||
void TerrainOverlay::RenderTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, bool draw_hidden, ssize_t i, ssize_t j)
|
||||
{
|
||||
// TODO: unnecessary computation calls has been removed but we should use
|
||||
// a vertex buffer or a vertex shader with a texture.
|
||||
@ -183,7 +187,10 @@ void TerrainOverlay::RenderTile(const CColor& color, bool draw_hidden, ssize_t i
|
||||
}
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(color); UNUSED2(i); UNUSED2(j);
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(color);
|
||||
UNUSED2(i);
|
||||
UNUSED2(j);
|
||||
#warning TODO: implement TerrainOverlay::RenderTile for GLES
|
||||
#else
|
||||
|
||||
@ -222,7 +229,18 @@ void TerrainOverlay::RenderTile(const CColor& color, bool draw_hidden, ssize_t i
|
||||
|
||||
CShaderTechniquePtr overlayTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
overlayTech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
overlayTech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr overlayShader = overlayTech->GetShader();
|
||||
|
||||
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
@ -238,12 +256,16 @@ void TerrainOverlay::RenderTile(const CColor& color, bool draw_hidden, ssize_t i
|
||||
#endif
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTileOutline(const CColor& color, int line_width, bool draw_hidden)
|
||||
void TerrainOverlay::RenderTileOutline(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, int line_width, bool draw_hidden)
|
||||
{
|
||||
RenderTileOutline(color, line_width, draw_hidden, m_i, m_j);
|
||||
RenderTileOutline(deviceCommandContext, color, line_width, draw_hidden, m_i, m_j);
|
||||
}
|
||||
|
||||
void TerrainOverlay::RenderTileOutline(const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j)
|
||||
void TerrainOverlay::RenderTileOutline(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j)
|
||||
{
|
||||
if (draw_hidden)
|
||||
{
|
||||
@ -257,7 +279,11 @@ void TerrainOverlay::RenderTileOutline(const CColor& color, int line_width, bool
|
||||
}
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(color); UNUSED2(line_width); UNUSED2(i); UNUSED2(j);
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(color);
|
||||
UNUSED2(line_width);
|
||||
UNUSED2(i);
|
||||
UNUSED2(j);
|
||||
#warning TODO: implement TerrainOverlay::RenderTileOutline for GLES
|
||||
#else
|
||||
|
||||
@ -282,7 +308,18 @@ void TerrainOverlay::RenderTileOutline(const CColor& color, int line_width, bool
|
||||
|
||||
CShaderTechniquePtr overlayTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_line);
|
||||
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
|
||||
overlayTech->GetGraphicsPipelineStateDesc();
|
||||
pipelineStateDesc.blendState.enabled = true;
|
||||
pipelineStateDesc.blendState.srcColorBlendFactor = pipelineStateDesc.blendState.srcAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.dstColorBlendFactor = pipelineStateDesc.blendState.dstAlphaBlendFactor =
|
||||
Renderer::Backend::BlendFactor::ONE_MINUS_SRC_ALPHA;
|
||||
pipelineStateDesc.blendState.colorBlendOp = pipelineStateDesc.blendState.alphaBlendOp =
|
||||
Renderer::Backend::BlendOp::ADD;
|
||||
overlayTech->BeginPass();
|
||||
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
|
||||
|
||||
CShaderProgramPtr overlayShader = overlayTech->GetShader();
|
||||
|
||||
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
@ -346,7 +383,8 @@ void TerrainTextureOverlay::RenderAfterWater(
|
||||
matrix._23 = m_TexelsPerTile / (m_Texture->GetHeight() * TERRAIN_TILE_SIZE);
|
||||
matrix._44 = 1;
|
||||
|
||||
g_Renderer.GetSceneRenderer().GetTerrainRenderer().RenderTerrainOverlayTexture(cullGroup, matrix, m_Texture.get());
|
||||
g_Renderer.GetSceneRenderer().GetTerrainRenderer().RenderTerrainOverlayTexture(
|
||||
deviceCommandContext, cullGroup, matrix, m_Texture.get());
|
||||
}
|
||||
|
||||
SColor4ub TerrainTextureOverlay::GetColor(size_t idx, u8 alpha) const
|
||||
|
@ -44,7 +44,7 @@ class ITerrainOverlay
|
||||
public:
|
||||
virtual ~ITerrainOverlay();
|
||||
|
||||
virtual void RenderBeforeWater() { }
|
||||
virtual void RenderBeforeWater(Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext)) { }
|
||||
|
||||
virtual void RenderAfterWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* UNUSED(deviceCommandContext), int UNUSED(cullGroup)) { }
|
||||
@ -53,7 +53,8 @@ public:
|
||||
* Draw all ITerrainOverlay objects that exist
|
||||
* and that should be drawn before water.
|
||||
*/
|
||||
static void RenderOverlaysBeforeWater();
|
||||
static void RenderOverlaysBeforeWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
|
||||
|
||||
/**
|
||||
* Draw all ITerrainOverlay objects that exist
|
||||
@ -127,7 +128,9 @@ protected:
|
||||
* @param i <i>i</i> coordinate of tile being processed
|
||||
* @param j <i>j</i> coordinate of tile being processed
|
||||
*/
|
||||
virtual void ProcessTile(ssize_t i, ssize_t j) = 0;
|
||||
virtual void ProcessTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
ssize_t i, ssize_t j) = 0;
|
||||
|
||||
/**
|
||||
* Draw a filled quad on top of the current tile.
|
||||
@ -136,12 +139,16 @@ protected:
|
||||
* @param draw_hidden true if hidden tiles (i.e. those behind other tiles)
|
||||
* should be drawn
|
||||
*/
|
||||
void RenderTile(const CColor& color, bool draw_hidden);
|
||||
void RenderTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, bool draw_hidden);
|
||||
|
||||
/**
|
||||
* Draw a filled quad on top of the given tile.
|
||||
*/
|
||||
void RenderTile(const CColor& color, bool draw_hidden, ssize_t i, ssize_t j);
|
||||
void RenderTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, bool draw_hidden, ssize_t i, ssize_t j);
|
||||
|
||||
/**
|
||||
* Draw an outlined quad on top of the current tile.
|
||||
@ -151,16 +158,21 @@ protected:
|
||||
* @param draw_hidden true if hidden tiles (i.e. those behind other tiles)
|
||||
* should be drawn
|
||||
*/
|
||||
void RenderTileOutline(const CColor& color, int line_width, bool draw_hidden);
|
||||
void RenderTileOutline(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, int line_width, bool draw_hidden);
|
||||
|
||||
/**
|
||||
* Draw an outlined quad on top of the given tile.
|
||||
*/
|
||||
void RenderTileOutline(const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j);
|
||||
void RenderTileOutline(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CColor& color, int line_width, bool draw_hidden, ssize_t i, ssize_t j);
|
||||
|
||||
private:
|
||||
// Process all tiles
|
||||
virtual void RenderBeforeWater();
|
||||
void RenderBeforeWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) override;
|
||||
|
||||
// Temporary storage of tile coordinates, so ProcessTile doesn't need to
|
||||
// pass it to RenderTile/etc (and doesn't have a chance to get it wrong)
|
||||
|
@ -158,11 +158,14 @@ void TerrainRenderer::EndFrame()
|
||||
m->phase = Phase_Submit;
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& textureMatrix,
|
||||
void TerrainRenderer::RenderTerrainOverlayTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, CMatrix3D& textureMatrix,
|
||||
Renderer::Backend::GL::CTexture* texture)
|
||||
{
|
||||
#if CONFIG2_GLES
|
||||
#warning TODO: implement TerrainRenderer::RenderTerrainOverlayTexture for GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(cullGroup);
|
||||
UNUSED2(textureMatrix);
|
||||
UNUSED2(texture);
|
||||
@ -177,7 +180,9 @@ void TerrainRenderer::RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& text
|
||||
CShaderTechniquePtr debugOverlayTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_debug_overlay);
|
||||
debugOverlayTech->BeginPass();
|
||||
CShaderProgramPtr debugOverlayShader = debugOverlayTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
debugOverlayTech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& debugOverlayShader = debugOverlayTech->GetShader();
|
||||
|
||||
debugOverlayShader->BindTexture(str_baseTex, texture);
|
||||
debugOverlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
@ -246,7 +251,9 @@ void TerrainRenderer::PrepareShader(const CShaderProgramPtr& shader, ShadowMap*
|
||||
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
void TerrainRenderer::RenderTerrainShader(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
{
|
||||
ENSURE(m->phase == Phase_Render);
|
||||
|
||||
@ -258,7 +265,10 @@ void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cul
|
||||
// render the solid black sides of the map first
|
||||
CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
techSolid->BeginPass();
|
||||
CShaderProgramPtr shaderSolid = techSolid->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
techSolid->GetGraphicsPipelineStateDesc());
|
||||
|
||||
const CShaderProgramPtr& shaderSolid = techSolid->GetShader();
|
||||
shaderSolid->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
@ -266,15 +276,15 @@ void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cul
|
||||
|
||||
techSolid->EndPass();
|
||||
|
||||
CPatchRData::RenderBases(visiblePatches, context, shadow);
|
||||
CPatchRData::RenderBases(deviceCommandContext, visiblePatches, context, shadow);
|
||||
|
||||
// no need to write to the depth buffer a second time
|
||||
glDepthMask(0);
|
||||
|
||||
// render blend passes for each patch
|
||||
CPatchRData::RenderBlends(visiblePatches, context, shadow);
|
||||
CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow);
|
||||
|
||||
CDecalRData::RenderDecals(visibleDecals, context, shadow);
|
||||
CDecalRData::RenderDecals(deviceCommandContext, visibleDecals, context, shadow);
|
||||
|
||||
// restore OpenGL state
|
||||
g_Renderer.BindTexture(1, 0);
|
||||
@ -287,7 +297,9 @@ void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, int cul
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Render un-textured patches as polygons
|
||||
void TerrainRenderer::RenderPatches(int cullGroup, const CColor& color)
|
||||
void TerrainRenderer::RenderPatches(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, const CColor& color)
|
||||
{
|
||||
ENSURE(m->phase == Phase_Render);
|
||||
|
||||
@ -296,13 +308,17 @@ void TerrainRenderer::RenderPatches(int cullGroup, const CColor& color)
|
||||
return;
|
||||
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(color);
|
||||
#warning TODO: implement TerrainRenderer::RenderPatches for GLES
|
||||
#else
|
||||
|
||||
CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_dummy);
|
||||
dummyTech->BeginPass();
|
||||
CShaderProgramPtr dummyShader = dummyTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
dummyTech->GetGraphicsPipelineStateDesc());
|
||||
|
||||
const CShaderProgramPtr& dummyShader = dummyTech->GetShader();
|
||||
dummyShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
|
||||
dummyShader->Uniform(str_color, color);
|
||||
|
||||
@ -349,7 +365,9 @@ CBoundingBoxAligned TerrainRenderer::ScissorWater(int cullGroup, const CCamera&
|
||||
}
|
||||
|
||||
// Render fancy water
|
||||
bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
bool TerrainRenderer::RenderFancyWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
{
|
||||
PROFILE3_GPU("fancy water");
|
||||
OGL_SCOPED_DEBUG_GROUP("Render Fancy Water");
|
||||
@ -403,7 +421,9 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
|
||||
#endif
|
||||
|
||||
m->fancyWaterTech->BeginPass();
|
||||
CShaderProgramPtr fancyWaterShader = m->fancyWaterTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
m->fancyWaterTech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& fancyWaterShader = m->fancyWaterTech->GetShader();
|
||||
|
||||
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
|
||||
|
||||
@ -501,9 +521,12 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
|
||||
return true;
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderSimpleWater(int cullGroup)
|
||||
void TerrainRenderer::RenderSimpleWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup)
|
||||
{
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(cullGroup);
|
||||
#else
|
||||
PROFILE3_GPU("simple water");
|
||||
@ -523,7 +546,9 @@ void TerrainRenderer::RenderSimpleWater(int cullGroup)
|
||||
CShaderTechniquePtr waterSimpleTech =
|
||||
g_Renderer.GetShaderManager().LoadEffect(str_water_simple);
|
||||
waterSimpleTech->BeginPass();
|
||||
CShaderProgramPtr waterSimpleShader = waterSimpleTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
waterSimpleTech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& waterSimpleShader = waterSimpleTech->GetShader();
|
||||
|
||||
waterSimpleShader->BindTexture(str_baseTex, waterManager.m_WaterTexture[waterManager.GetCurrentTextureIndex(1.6)]);
|
||||
waterSimpleShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
|
||||
@ -552,17 +577,21 @@ void TerrainRenderer::RenderSimpleWater(int cullGroup)
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Render water that is part of the terrain
|
||||
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
void TerrainRenderer::RenderWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||
{
|
||||
const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
|
||||
|
||||
if (!waterManager.WillRenderFancyWater())
|
||||
RenderSimpleWater(cullGroup);
|
||||
RenderSimpleWater(deviceCommandContext, cullGroup);
|
||||
else
|
||||
RenderFancyWater(context, cullGroup, shadow);
|
||||
RenderFancyWater(deviceCommandContext, context, cullGroup, shadow);
|
||||
}
|
||||
|
||||
void TerrainRenderer::RenderWaterFoamOccluders(int cullGroup)
|
||||
void TerrainRenderer::RenderWaterFoamOccluders(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup)
|
||||
{
|
||||
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
|
||||
const WaterManager& waterManager = sceneRenderer.GetWaterManager();
|
||||
@ -572,7 +601,6 @@ void TerrainRenderer::RenderWaterFoamOccluders(int cullGroup)
|
||||
// Render normals and foam to a framebuffer if we're using fancy effects.
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
@ -580,7 +608,9 @@ void TerrainRenderer::RenderWaterFoamOccluders(int cullGroup)
|
||||
// Overwrite waves that would be behind the ground.
|
||||
CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||
dummyTech->BeginPass();
|
||||
CShaderProgramPtr dummyShader = dummyTech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
dummyTech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& dummyShader = dummyTech->GetShader();
|
||||
|
||||
dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
|
||||
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "maths/BoundingBoxAligned.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/backend/gl/Texture.h"
|
||||
|
||||
class CCamera;
|
||||
@ -96,9 +97,12 @@ public:
|
||||
* preconditions : PrepareForRendering must have been called this
|
||||
* frame before calling RenderTerrain.
|
||||
*
|
||||
* @param deviceCommandContext A context to submit commands.
|
||||
* @param shadow A prepared shadow map, in case rendering with shadows is enabled.
|
||||
*/
|
||||
void RenderTerrainShader(const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
void RenderTerrainShader(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
|
||||
/**
|
||||
* RenderPatches: Render all patches un-textured as polygons.
|
||||
@ -109,7 +113,9 @@ public:
|
||||
* @param filtered If true then only render objects that passed CullPatches.
|
||||
* @param color Fill color of the patches.
|
||||
*/
|
||||
void RenderPatches(int cullGroup, const CColor& color = CColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
void RenderPatches(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, const CColor& color = CColor(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
/**
|
||||
* RenderOutlines: Render the outline of patches as lines.
|
||||
@ -128,12 +134,16 @@ public:
|
||||
* preconditions : PrepareForRendering must have been called this
|
||||
* frame before calling RenderWater.
|
||||
*/
|
||||
void RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
void RenderWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
|
||||
/**
|
||||
* Renders terrain to a framebuffer to occlude shore foams.
|
||||
*/
|
||||
void RenderWaterFoamOccluders(int cullGroup);
|
||||
void RenderWaterFoamOccluders(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup);
|
||||
|
||||
/**
|
||||
* Calculate a scissor rectangle for the visible water patches.
|
||||
@ -150,7 +160,9 @@ public:
|
||||
* by the given texture matrix.
|
||||
* Intended for use by TerrainTextureOverlay.
|
||||
*/
|
||||
void RenderTerrainOverlayTexture(int cullGroup, CMatrix3D& textureMatrix, Renderer::Backend::GL::CTexture* texture);
|
||||
void RenderTerrainOverlayTexture(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup, CMatrix3D& textureMatrix, Renderer::Backend::GL::CTexture* texture);
|
||||
|
||||
private:
|
||||
TerrainRendererInternals* m;
|
||||
@ -159,12 +171,16 @@ private:
|
||||
* RenderFancyWater: internal rendering method for fancy water.
|
||||
* Returns false if unable to render with fancy water.
|
||||
*/
|
||||
bool RenderFancyWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
bool RenderFancyWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||
|
||||
/**
|
||||
* RenderSimpleWater: internal rendering method for water
|
||||
*/
|
||||
void RenderSimpleWater(int cullGroup);
|
||||
void RenderSimpleWater(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
int cullGroup);
|
||||
|
||||
static void PrepareShader(const CShaderProgramPtr& shader, ShadowMap* shadow);
|
||||
};
|
||||
|
@ -795,10 +795,13 @@ void WaterManager::CreateWaveMeshes()
|
||||
}
|
||||
}
|
||||
|
||||
void WaterManager::RenderWaves(const CFrustum& frustrum)
|
||||
void WaterManager::RenderWaves(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CFrustum& frustrum)
|
||||
{
|
||||
OGL_SCOPED_DEBUG_GROUP("Render Waves");
|
||||
#if CONFIG2_GLES
|
||||
UNUSED2(deviceCommandContext);
|
||||
UNUSED2(frustrum);
|
||||
#warning Fix WaterManager::RenderWaves on GLES
|
||||
#else
|
||||
@ -818,7 +821,9 @@ void WaterManager::RenderWaves(const CFrustum& frustrum)
|
||||
|
||||
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves);
|
||||
tech->BeginPass();
|
||||
CShaderProgramPtr shader = tech->GetShader();
|
||||
deviceCommandContext->SetGraphicsPipelineState(
|
||||
tech->GetGraphicsPipelineStateDesc());
|
||||
const CShaderProgramPtr& shader = tech->GetShader();
|
||||
|
||||
shader->BindTexture(str_waveTex, m_WaveTex);
|
||||
shader->BindTexture(str_foamTex, m_FoamTex);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "graphics/Texture.h"
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "maths/Vector2D.h"
|
||||
#include "renderer/backend/gl/DeviceCommandContext.h"
|
||||
#include "renderer/backend/gl/Texture.h"
|
||||
#include "renderer/VertexBufferManager.h"
|
||||
|
||||
@ -190,7 +191,9 @@ public:
|
||||
*/
|
||||
bool WillRenderFancyWater() const;
|
||||
|
||||
void RenderWaves(const CFrustum& frustrum);
|
||||
void RenderWaves(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
const CFrustum& frustrum);
|
||||
|
||||
/**
|
||||
* Returns an index of the current texture that should be used for rendering
|
||||
|
84
source/renderer/backend/PipelineState.cpp
Normal file
84
source/renderer/backend/PipelineState.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "PipelineState.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
||||
namespace Backend
|
||||
{
|
||||
|
||||
GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc()
|
||||
{
|
||||
GraphicsPipelineStateDesc desc{};
|
||||
desc.blendState.enabled = false;
|
||||
desc.blendState.srcColorBlendFactor = desc.blendState.srcAlphaBlendFactor =
|
||||
BlendFactor::ONE;
|
||||
desc.blendState.dstColorBlendFactor = desc.blendState.dstAlphaBlendFactor =
|
||||
BlendFactor::ZERO;
|
||||
desc.blendState.colorBlendOp = desc.blendState.alphaBlendOp = BlendOp::ADD;
|
||||
desc.blendState.constant = CColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
return desc;
|
||||
}
|
||||
|
||||
BlendFactor ParseBlendFactor(const CStr& str)
|
||||
{
|
||||
// TODO: it might make sense to use upper case in XML for consistency.
|
||||
#define CASE(NAME, VALUE) if (str == NAME) return BlendFactor::VALUE
|
||||
CASE("zero", ZERO);
|
||||
CASE("one", ONE);
|
||||
CASE("src_color", SRC_COLOR);
|
||||
CASE("one_minus_src_color", ONE_MINUS_SRC_COLOR);
|
||||
CASE("dst_color", DST_COLOR);
|
||||
CASE("one_minus_dst_color", ONE_MINUS_DST_COLOR);
|
||||
CASE("src_alpha", SRC_ALPHA);
|
||||
CASE("one_minus_src_alpha", ONE_MINUS_SRC_ALPHA);
|
||||
CASE("dst_alpha", DST_ALPHA);
|
||||
CASE("one_minus_dst_alpha", ONE_MINUS_DST_ALPHA);
|
||||
CASE("constant_color", CONSTANT_COLOR);
|
||||
CASE("one_minus_constant_color", ONE_MINUS_CONSTANT_COLOR);
|
||||
CASE("constant_alpha", CONSTANT_ALPHA);
|
||||
CASE("one_minus_constant_alpha", ONE_MINUS_CONSTANT_ALPHA);
|
||||
CASE("src_alpha_saturate", SRC_ALPHA_SATURATE);
|
||||
CASE("src1_color", SRC1_COLOR);
|
||||
CASE("one_minus_src1_color", ONE_MINUS_SRC1_COLOR);
|
||||
CASE("src1_alpha", SRC1_ALPHA);
|
||||
CASE("one_minus_src1_alpha", ONE_MINUS_SRC1_ALPHA);
|
||||
#undef CASE
|
||||
debug_warn("Invalid blend factor");
|
||||
return BlendFactor::ZERO;
|
||||
}
|
||||
|
||||
BlendOp ParseBlendOp(const CStr& str)
|
||||
{
|
||||
#define CASE(NAME) if (str == #NAME) return BlendOp::NAME
|
||||
CASE(ADD);
|
||||
CASE(SUBTRACT);
|
||||
CASE(REVERSE_SUBTRACT);
|
||||
CASE(MIN);
|
||||
CASE(MAX);
|
||||
#undef CASE
|
||||
debug_warn("Invalid blend op");
|
||||
return BlendOp::ADD;
|
||||
}
|
||||
|
||||
} // namespace Backend
|
||||
|
||||
} // namespace Renderer
|
94
source/renderer/backend/PipelineState.h
Normal file
94
source/renderer/backend/PipelineState.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_RENDERER_BACKEND_PIPELINESTATE
|
||||
#define INCLUDED_RENDERER_BACKEND_PIPELINESTATE
|
||||
|
||||
#include "graphics/Color.h"
|
||||
|
||||
class CStr;
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
||||
namespace Backend
|
||||
{
|
||||
|
||||
// TODO: add per constant description.
|
||||
|
||||
enum class BlendFactor
|
||||
{
|
||||
ZERO,
|
||||
ONE,
|
||||
SRC_COLOR,
|
||||
ONE_MINUS_SRC_COLOR,
|
||||
DST_COLOR,
|
||||
ONE_MINUS_DST_COLOR,
|
||||
SRC_ALPHA,
|
||||
ONE_MINUS_SRC_ALPHA,
|
||||
DST_ALPHA,
|
||||
ONE_MINUS_DST_ALPHA,
|
||||
CONSTANT_COLOR,
|
||||
ONE_MINUS_CONSTANT_COLOR,
|
||||
CONSTANT_ALPHA,
|
||||
ONE_MINUS_CONSTANT_ALPHA,
|
||||
SRC_ALPHA_SATURATE,
|
||||
SRC1_COLOR,
|
||||
ONE_MINUS_SRC1_COLOR,
|
||||
SRC1_ALPHA,
|
||||
ONE_MINUS_SRC1_ALPHA,
|
||||
};
|
||||
|
||||
enum class BlendOp
|
||||
{
|
||||
ADD,
|
||||
SUBTRACT,
|
||||
REVERSE_SUBTRACT,
|
||||
MIN,
|
||||
MAX
|
||||
};
|
||||
|
||||
struct BlendStateDesc
|
||||
{
|
||||
bool enabled;
|
||||
BlendFactor srcColorBlendFactor;
|
||||
BlendFactor dstColorBlendFactor;
|
||||
BlendOp colorBlendOp;
|
||||
BlendFactor srcAlphaBlendFactor;
|
||||
BlendFactor dstAlphaBlendFactor;
|
||||
BlendOp alphaBlendOp;
|
||||
CColor constant;
|
||||
};
|
||||
|
||||
// TODO: Add a shader program to the graphics pipeline state.
|
||||
struct GraphicsPipelineStateDesc
|
||||
{
|
||||
BlendStateDesc blendState;
|
||||
};
|
||||
|
||||
// We don't provide additional helpers intentionally because all custom states
|
||||
// should be described with a related shader and should be switched together.
|
||||
GraphicsPipelineStateDesc MakeDefaultGraphicsPipelineStateDesc();
|
||||
|
||||
BlendFactor ParseBlendFactor(const CStr& str);
|
||||
BlendOp ParseBlendOp(const CStr& str);
|
||||
|
||||
} // namespace Backend
|
||||
|
||||
} // namespace Renderer
|
||||
|
||||
#endif // INCLUDED_RENDERER_BACKEND_PIPELINESTATE
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "DeviceCommandContext.h"
|
||||
|
||||
#include "renderer/backend/gl/Mapping.h"
|
||||
#include "renderer/backend/gl/Texture.h"
|
||||
|
||||
namespace Renderer
|
||||
@ -34,7 +35,7 @@ namespace GL
|
||||
std::unique_ptr<CDeviceCommandContext> CDeviceCommandContext::Create()
|
||||
{
|
||||
std::unique_ptr<CDeviceCommandContext> deviceCommandContext(new CDeviceCommandContext());
|
||||
|
||||
deviceCommandContext->ResetStates();
|
||||
return deviceCommandContext;
|
||||
}
|
||||
|
||||
@ -42,6 +43,12 @@ CDeviceCommandContext::CDeviceCommandContext() = default;
|
||||
|
||||
CDeviceCommandContext::~CDeviceCommandContext() = default;
|
||||
|
||||
void CDeviceCommandContext::SetGraphicsPipelineState(
|
||||
const GraphicsPipelineStateDesc& pipelineStateDesc)
|
||||
{
|
||||
SetGraphicsPipelineStateImpl(pipelineStateDesc, false);
|
||||
}
|
||||
|
||||
void CDeviceCommandContext::UploadTexture(
|
||||
CTexture* texture, const Format format,
|
||||
const void* data, const size_t dataSize,
|
||||
@ -116,6 +123,80 @@ void CDeviceCommandContext::UploadTextureRegion(
|
||||
debug_warn("Unsupported type");
|
||||
}
|
||||
|
||||
void CDeviceCommandContext::Flush()
|
||||
{
|
||||
ResetStates();
|
||||
}
|
||||
|
||||
void CDeviceCommandContext::ResetStates()
|
||||
{
|
||||
SetGraphicsPipelineStateImpl(MakeDefaultGraphicsPipelineStateDesc(), true);
|
||||
}
|
||||
|
||||
void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
|
||||
const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force)
|
||||
{
|
||||
const BlendStateDesc& currentBlendStateDesc = m_GraphicsPipelineStateDesc.blendState;
|
||||
const BlendStateDesc& nextBlendStateDesc = pipelineStateDesc.blendState;
|
||||
if (force || currentBlendStateDesc.enabled != nextBlendStateDesc.enabled)
|
||||
{
|
||||
if (nextBlendStateDesc.enabled)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
if (force ||
|
||||
currentBlendStateDesc.srcColorBlendFactor != nextBlendStateDesc.srcColorBlendFactor ||
|
||||
currentBlendStateDesc.srcAlphaBlendFactor != nextBlendStateDesc.srcAlphaBlendFactor ||
|
||||
currentBlendStateDesc.dstColorBlendFactor != nextBlendStateDesc.dstColorBlendFactor ||
|
||||
currentBlendStateDesc.dstAlphaBlendFactor != nextBlendStateDesc.dstAlphaBlendFactor)
|
||||
{
|
||||
if (nextBlendStateDesc.srcColorBlendFactor == nextBlendStateDesc.srcAlphaBlendFactor &&
|
||||
nextBlendStateDesc.dstColorBlendFactor == nextBlendStateDesc.dstAlphaBlendFactor)
|
||||
{
|
||||
glBlendFunc(
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.srcColorBlendFactor),
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.dstColorBlendFactor));
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendFuncSeparate(
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.srcColorBlendFactor),
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.dstColorBlendFactor),
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.srcAlphaBlendFactor),
|
||||
Mapping::FromBlendFactor(nextBlendStateDesc.dstAlphaBlendFactor));
|
||||
}
|
||||
}
|
||||
|
||||
if (force ||
|
||||
currentBlendStateDesc.colorBlendOp != nextBlendStateDesc.colorBlendOp ||
|
||||
currentBlendStateDesc.alphaBlendOp != nextBlendStateDesc.alphaBlendOp)
|
||||
{
|
||||
if (nextBlendStateDesc.colorBlendOp == nextBlendStateDesc.alphaBlendOp)
|
||||
{
|
||||
glBlendEquation(Mapping::FromBlendOp(nextBlendStateDesc.colorBlendOp));
|
||||
}
|
||||
else
|
||||
{
|
||||
glBlendEquationSeparate(
|
||||
Mapping::FromBlendOp(nextBlendStateDesc.colorBlendOp),
|
||||
Mapping::FromBlendOp(nextBlendStateDesc.alphaBlendOp));
|
||||
}
|
||||
}
|
||||
|
||||
if (force ||
|
||||
currentBlendStateDesc.constant != nextBlendStateDesc.constant)
|
||||
{
|
||||
glBlendColor(
|
||||
nextBlendStateDesc.constant.r,
|
||||
nextBlendStateDesc.constant.g,
|
||||
nextBlendStateDesc.constant.b,
|
||||
nextBlendStateDesc.constant.a);
|
||||
}
|
||||
|
||||
m_GraphicsPipelineStateDesc = pipelineStateDesc;
|
||||
}
|
||||
|
||||
} // namespace GL
|
||||
|
||||
} // namespace Backend
|
||||
|
@ -19,8 +19,10 @@
|
||||
#define INCLUDED_RENDERER_GL_DEVICECOMMANDCONTEXT
|
||||
|
||||
#include "renderer/backend/Format.h"
|
||||
#include "renderer/backend/PipelineState.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
@ -40,6 +42,8 @@ public:
|
||||
|
||||
static std::unique_ptr<CDeviceCommandContext> Create();
|
||||
|
||||
void SetGraphicsPipelineState(const GraphicsPipelineStateDesc& pipelineStateDesc);
|
||||
|
||||
void UploadTexture(CTexture* texture, const Format dataFormat,
|
||||
const void* data, const size_t dataSize,
|
||||
const uint32_t level = 0, const uint32_t layer = 0);
|
||||
@ -49,8 +53,17 @@ public:
|
||||
const uint32_t width, const uint32_t height,
|
||||
const uint32_t level = 0, const uint32_t layer = 0);
|
||||
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
CDeviceCommandContext();
|
||||
|
||||
void ResetStates();
|
||||
|
||||
void SetGraphicsPipelineStateImpl(
|
||||
const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force);
|
||||
|
||||
GraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{};
|
||||
};
|
||||
|
||||
} // namespace GL
|
||||
|
97
source/renderer/backend/gl/Mapping.cpp
Normal file
97
source/renderer/backend/gl/Mapping.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "Mapping.h"
|
||||
|
||||
#include "lib/code_annotation.h"
|
||||
#include "lib/config2.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
||||
namespace Backend
|
||||
{
|
||||
|
||||
namespace GL
|
||||
{
|
||||
|
||||
namespace Mapping
|
||||
{
|
||||
|
||||
GLenum FromBlendFactor(BlendFactor blendFactor)
|
||||
{
|
||||
GLenum factor = GL_ZERO;
|
||||
switch (blendFactor)
|
||||
{
|
||||
#define CASE(NAME) case BlendFactor::NAME: factor = GL_##NAME; break
|
||||
CASE(ZERO);
|
||||
CASE(ONE);
|
||||
CASE(SRC_COLOR);
|
||||
CASE(ONE_MINUS_SRC_COLOR);
|
||||
CASE(DST_COLOR);
|
||||
CASE(ONE_MINUS_DST_COLOR);
|
||||
CASE(SRC_ALPHA);
|
||||
CASE(ONE_MINUS_SRC_ALPHA);
|
||||
CASE(DST_ALPHA);
|
||||
CASE(ONE_MINUS_DST_ALPHA);
|
||||
CASE(CONSTANT_COLOR);
|
||||
CASE(ONE_MINUS_CONSTANT_COLOR);
|
||||
CASE(CONSTANT_ALPHA);
|
||||
CASE(ONE_MINUS_CONSTANT_ALPHA);
|
||||
CASE(SRC_ALPHA_SATURATE);
|
||||
#undef CASE
|
||||
// Dual source blending presents only in GL_VERSION >= 3.3.
|
||||
case BlendFactor::SRC1_COLOR: FALLTHROUGH;
|
||||
case BlendFactor::ONE_MINUS_SRC1_COLOR: FALLTHROUGH;
|
||||
case BlendFactor::SRC1_ALPHA: FALLTHROUGH;
|
||||
case BlendFactor::ONE_MINUS_SRC1_ALPHA:
|
||||
debug_warn("Unsupported blend factor.");
|
||||
break;
|
||||
}
|
||||
return factor;
|
||||
}
|
||||
|
||||
GLenum FromBlendOp(BlendOp blendOp)
|
||||
{
|
||||
GLenum mode = GL_FUNC_ADD;
|
||||
switch (blendOp)
|
||||
{
|
||||
case BlendOp::ADD: mode = GL_FUNC_ADD; break;
|
||||
case BlendOp::SUBTRACT: mode = GL_FUNC_SUBTRACT; break;
|
||||
case BlendOp::REVERSE_SUBTRACT: mode = GL_FUNC_REVERSE_SUBTRACT; break;
|
||||
#if !CONFIG2_GLES
|
||||
case BlendOp::MIN: mode = GL_MIN; break;
|
||||
case BlendOp::MAX: mode = GL_MAX; break;
|
||||
#else
|
||||
case BlendOp::MIN: FALLTHROUGH;
|
||||
case BlendOp::MAX:
|
||||
debug_warn("Unsupported blend op.");
|
||||
break;
|
||||
#endif
|
||||
};
|
||||
return mode;
|
||||
}
|
||||
|
||||
} // namespace Mapping
|
||||
|
||||
} // namespace GL
|
||||
|
||||
} // namespace Backend
|
||||
|
||||
} // namespace Renderer
|
48
source/renderer/backend/gl/Mapping.h
Normal file
48
source/renderer/backend/gl/Mapping.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_RENDERER_BACKEND_GL_MAPPING
|
||||
#define INCLUDED_RENDERER_BACKEND_GL_MAPPING
|
||||
|
||||
#include "lib/ogl.h"
|
||||
#include "renderer/backend/PipelineState.h"
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
||||
namespace Backend
|
||||
{
|
||||
|
||||
namespace GL
|
||||
{
|
||||
|
||||
namespace Mapping
|
||||
{
|
||||
|
||||
GLenum FromBlendFactor(BlendFactor blendFactor);
|
||||
|
||||
GLenum FromBlendOp(BlendOp blendOp);
|
||||
|
||||
} // namespace Mapping
|
||||
|
||||
} // namespace GL
|
||||
|
||||
} // namespace Backend
|
||||
|
||||
} // namespace Renderer
|
||||
|
||||
#endif // INCLUDED_RENDERER_BACKEND_GL_MAPPING
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -28,6 +28,8 @@
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/system/SimContext.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
class BrushTerrainOverlay : public TerrainOverlay
|
||||
@ -51,7 +53,9 @@ public:
|
||||
--max_j_inclusive;
|
||||
}
|
||||
|
||||
void ProcessTile(ssize_t i, ssize_t j)
|
||||
void ProcessTile(
|
||||
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
|
||||
ssize_t i, ssize_t j)
|
||||
{
|
||||
ssize_t i0, j0;
|
||||
m_Brush->GetBottomLeft(i0, j0);
|
||||
@ -60,9 +64,9 @@ public:
|
||||
m_Brush->Get(i-i0, j-j0) + m_Brush->Get(i-i0+1, j-j0) +
|
||||
m_Brush->Get(i-i0, j-j0+1) + m_Brush->Get(i-i0+1, j-j0+1)
|
||||
) / 4.f;
|
||||
RenderTile(CColor(0, 1, 0, avg*0.8f), false);
|
||||
RenderTile(deviceCommandContext, CColor(0, 1, 0, avg*0.8f), false);
|
||||
if (avg > 0.1f)
|
||||
RenderTileOutline(CColor(1, 1, 1, std::min(0.4f, avg-0.1f)), 1, true);
|
||||
RenderTileOutline(deviceCommandContext, CColor(1, 1, 1, std::min(0.4f, avg-0.1f)), 1, true);
|
||||
}
|
||||
|
||||
const AtlasMessage::Brush* m_Brush;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2022 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -24,10 +24,12 @@
|
||||
|
||||
class TerrainOverlay;
|
||||
|
||||
namespace AtlasMessage {
|
||||
|
||||
struct Brush
|
||||
namespace AtlasMessage
|
||||
{
|
||||
|
||||
class Brush
|
||||
{
|
||||
public:
|
||||
Brush();
|
||||
~Brush();
|
||||
|
||||
@ -56,6 +58,6 @@ private:
|
||||
|
||||
extern Brush g_CurrentBrush;
|
||||
|
||||
}
|
||||
} // namespace AtlasMessage
|
||||
|
||||
#endif // INCLUDED_BRUSHES
|
||||
|
Loading…
Reference in New Issue
Block a user