1
0
forked from 0ad/0ad

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:
Vladislav Belov 2022-01-19 17:28:47 +00:00
parent 0b7a717c8a
commit 5adbe4f1a3
56 changed files with 1241 additions and 405 deletions

View File

@ -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>

View 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>

View File

@ -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>

View 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_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>

View File

@ -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>

View 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" 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>

View File

@ -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()

View File

@ -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;

View File

@ -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);
}

View File

@ -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());

View File

@ -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);

View File

@ -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;

View File

@ -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)

View File

@ -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)
{

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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.

View File

@ -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");

View File

@ -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)

View File

@ -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);

View File

@ -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()

View File

@ -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; }

View File

@ -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();

View File

@ -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;

View File

@ -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
}

View File

@ -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;

View File

@ -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)

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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))
{
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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
};

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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.

View File

@ -40,7 +40,8 @@ public:
/**
* Render the sky.
*/
void RenderSky();
void RenderSky(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
/**
* Return the currently selected sky set name.

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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);
};

View File

@ -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);

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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;

View File

@ -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