Adds material passes to choose different shaders

All shaders were selected by context (set of defines) which increases
the number of needed permutations. For example: we don't need to know
about shadows when rendering silhouettes.
This commit is contained in:
Vladislav Belov 2026-05-10 23:57:16 +02:00
parent 9aee507e28
commit aced56c336
No known key found for this signature in database
GPG key ID: 353545E45DB9CCB3
4 changed files with 74 additions and 12 deletions

View file

@ -24,9 +24,23 @@
<empty/>
</element>
</optional>
<element name="shader">
<attribute name="effect"/>
</element>
<oneOrMore>
<element name="shader">
<attribute name="effect"/>
<attribute name="pass">
<choice>
<value>main</value>
<value>shadow_caster</value>
<value>silhouette_occluder</value>
<value>silhouette_caster</value>
<value>wireframe</value>
<value>wireframe_solid</value>
<value>reflections</value>
<value>refractions</value>
</choice>
</attribute>
</element>
</oneOrMore>
<zeroOrMore>
<element name="define">
<attribute name="name"/>

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -28,9 +28,16 @@ CMaterial::CMaterial() :
{
}
void CMaterial::SetShaderEffect(const CStr& effect)
CStrIntern CMaterial::GetShaderEffect(const Pass pass) const
{
m_ShaderEffect = CStrIntern(effect);
ENSURE(pass < Pass::COUNT);
return m_ShaderEffects[static_cast<uint8_t>(pass)];
}
void CMaterial::SetShaderEffect(const Pass pass, CStrIntern effect)
{
ENSURE(pass < Pass::COUNT);
m_ShaderEffects[static_cast<uint8_t>(pass)] = effect;
}
void CMaterial::AddShaderDefine(CStrIntern key, CStrIntern value)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 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,7 @@
#include "ps/CStr.h"
#include "ps/CStrIntern.h"
#include <array>
#include <vector>
class CVector4D;
@ -30,6 +31,18 @@ class CVector4D;
class CMaterial
{
public:
enum class Pass : uint8_t
{
MAIN,
SHADOW_CASTER,
REFLECTIONS,
REFRACTIONS,
SILHOUETTE_OCCLUDER,
SILHOUETTE_CASTER,
WIREFRAME,
WIREFRAME_SOLID,
COUNT
};
struct TextureSampler
{
@ -52,8 +65,8 @@ public:
const CTexturePtr& GetDiffuseTexture() const { return m_DiffuseTexture; }
void SetShaderEffect(const CStr& effect);
CStrIntern GetShaderEffect() const { return m_ShaderEffect; }
void SetShaderEffect(const Pass pass, CStrIntern effect);
CStrIntern GetShaderEffect(const Pass pass) const;
// Must call RecomputeCombinedShaderDefines after this, before rendering with this material
void AddShaderDefine(CStrIntern key, CStrIntern value);
@ -81,7 +94,7 @@ private:
SamplersVector m_Samplers;
std::vector<CStrIntern> m_RequiredSamplers;
CStrIntern m_ShaderEffect;
std::array<CStrIntern, static_cast<size_t>(Pass::COUNT)> m_ShaderEffects;
CShaderDefines m_ShaderDefines;
CShaderUniforms m_StaticUniforms;
CShaderRenderQueries m_RenderQueries;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -39,6 +39,31 @@
#include <string>
#include <utility>
namespace
{
CMaterial::Pass GetMaterialPassFromStr(const std::string_view pass)
{
if (pass == "shadow_caster")
return CMaterial::Pass::SHADOW_CASTER;
else if (pass == "reflections")
return CMaterial::Pass::REFLECTIONS;
else if (pass == "refractions")
return CMaterial::Pass::REFRACTIONS;
else if (pass == "silhouette_occluder")
return CMaterial::Pass::SILHOUETTE_OCCLUDER;
else if (pass == "silhouette_caster")
return CMaterial::Pass::SILHOUETTE_CASTER;
else if (pass == "wireframe")
return CMaterial::Pass::WIREFRAME;
else if (pass == "wireframe_solid")
return CMaterial::Pass::WIREFRAME_SOLID;
else
return CMaterial::Pass::MAIN;
}
}
CMaterialManager::CMaterialManager() :
qualityLevel{Clamp(g_ConfigDB.Get("materialmgr.quality", 5.0f), 0.0f, 10.0f)}
{
@ -77,6 +102,7 @@ CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname)
AT(quality);
AT(material);
AT(name);
AT(pass);
AT(value);
#undef AT
#undef EL
@ -114,7 +140,9 @@ CMaterial CMaterialManager::LoadMaterial(const VfsPath& pathname)
}
else if (token == el_shader)
{
material.SetShaderEffect(attrs.GetNamedItem(at_effect));
const CStr pass{attrs.GetNamedItem(at_pass)};
const CStrIntern shaderEffect{attrs.GetNamedItem(at_effect)};
material.SetShaderEffect(GetMaterialPassFromStr(pass), shaderEffect);
}
else if (token == el_define)
{