1
0
forked from 0ad/0ad

Moves uniform and texture binding to CDeviceCommandContext.

Tested By: Langbart
Differential Revision: https://code.wildfiregames.com/D4631
This was SVN commit r26848.
This commit is contained in:
Vladislav Belov 2022-05-02 20:57:22 +00:00
parent a8caed8348
commit 04bd96cee0
65 changed files with 1590 additions and 969 deletions

View File

@ -5,7 +5,7 @@
<stream name="uv0"/>
</vertex>
<fragment file="arb/los_interp.fp">
<uniform name="delta" loc="0" type="vec3"/>
<uniform name="delta" loc="0" type="float"/>
<uniform name="losTex1" loc="0" type="sampler2D"/>
<uniform name="losTex2" loc="1" type="sampler2D"/>
</fragment>

View File

@ -3,11 +3,11 @@
<vertex file="arb/terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="textureTransform" loc="1" type="vec2"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
<uniform name="shadowScale" loc="7" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec3"/>
<uniform name="transform" loc="9" type="mat4"/>
<stream name="pos"/>
<stream name="normal"/>

View File

@ -5,11 +5,11 @@
<vertex file="arb/terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="textureTransform" loc="1" type="vec2"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
<uniform name="shadowScale" loc="7" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec3"/>
<uniform name="transform" loc="9" type="mat4"/>
<stream name="pos"/>
<stream name="normal"/>

View File

@ -12,6 +12,11 @@ PARAM transform[4] = { program.local[9..12] };
TEMP lighting;
TEMP terrainTextureTransform;
MOV terrainTextureTransform, textureTransform;
MOV terrainTextureTransform.z, -textureTransform.y;
MOV terrainTextureTransform.w, 0;
//// Compute position and normal:
ATTRIB position = vertex.position;
@ -40,8 +45,8 @@ MUL result.color, lighting, sunColor;
// Compute texcoords from position and terrain-texture-dependent transform.
// textureTransform is stored as [c, -s, s, 0],
// and we want texcoord = (x*c + z*-s, x*-s + z*-c, 0, 1)
DP3 result.texcoord[0].x, textureTransform.xyww, position.xzww;
DP3 result.texcoord[0].y, -textureTransform.zxww, position.xzww;
DP3 result.texcoord[0].x, terrainTextureTransform.xyww, position.xzww;
DP3 result.texcoord[0].y, -terrainTextureTransform.zxww, position.xzww;
MOV result.texcoord[0].z, 0;
MOV result.texcoord[0].w, 1;
#endif

View File

@ -5,11 +5,11 @@
<vertex file="arb/terrain_common.vp">
<uniform name="sunColor" loc="0" type="vec3"/>
<uniform name="textureTransform" loc="1" type="vec4"/>
<uniform name="textureTransform" loc="1" type="vec2"/>
<uniform name="losTransform" loc="2" type="vec2"/>
<uniform name="shadowTransform" loc="3" type="mat4"/>
<uniform name="shadowScale" loc="7" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec4"/>
<uniform name="sunDir" loc="8" type="vec3"/>
<uniform name="transform" loc="9" type="mat4"/>
<stream name="pos"/>
<stream name="normal"/>

View File

@ -4,7 +4,7 @@
<vertex file="arb/water_simple.vp">
<stream name="pos"/>
<uniform name="transform" loc="0" type="mat4"/>
<uniform name="losTransform" loc="4" type="vec4"/>
<uniform name="losTransform" loc="4" type="vec2"/>
<uniform name="time" loc="5" type="float"/>
</vertex>

View File

@ -4,7 +4,7 @@ varying vec2 v_tex;
uniform sampler2D losTex1, losTex2;
uniform vec3 delta;
uniform float delta;
void main(void)
@ -12,6 +12,6 @@ void main(void)
float los2 = texture2D(losTex1, v_tex).a;
float los1 = texture2D(losTex2, v_tex).a;
gl_FragColor.a = mix(los1, los2, clamp(delta.r, 0.0, 1.0));
gl_FragColor.a = mix(los1, los2, clamp(delta, 0.0, 1.0));
}

View File

@ -15,7 +15,7 @@ uniform vec3 sunColor;
uniform mat4 instancingTransform;
#if USE_WIND
uniform vec4 sim_time;
uniform float sim_time;
uniform vec4 windData;
#endif
@ -112,9 +112,9 @@ void main()
vec4 cosVec;
// these determine the speed of the wind's "cosine" waves.
cosVec.w = 0.0;
cosVec.x = sim_time.x * modelPos[0] + position.x;
cosVec.y = sim_time.x * modelPos[2] / 3.0 + instancingTransform[3][0];
cosVec.z = sim_time.x * abswind / 4.0 + position.z;
cosVec.x = sim_time * modelPos[0] + position.x;
cosVec.y = sim_time * modelPos[2] / 3.0 + instancingTransform[3][0];
cosVec.z = sim_time * abswind / 4.0 + position.z;
// calculate "cosines" in parallel, using a smoothed triangle wave
cosVec = fakeCos(cosVec);

View File

@ -37,14 +37,24 @@ namespace
// Array of 2D elements unrolled into 1D array.
using PlaneArray2D = std::array<float, 12>;
struct SBindingSlots
{
int32_t transform;
int32_t colorAdd;
int32_t colorMul;
int32_t grayscaleFactor;
int32_t tex;
};
inline void DrawTextureImpl(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CTexturePtr& texture,
const PlaneArray2D& vertices, PlaneArray2D uvs,
const CColor& multiply, const CColor& add, const float grayscaleFactor)
const CTexturePtr& texture, const PlaneArray2D& vertices, PlaneArray2D uvs,
const CColor& multiply, const CColor& add, const float grayscaleFactor,
const SBindingSlots& bindingSlots)
{
texture->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_tex, texture->GetBackendTexture());
deviceCommandContext->SetTexture(
bindingSlots.tex, texture->GetBackendTexture());
for (size_t idx = 0; idx < uvs.size(); idx += 2)
{
if (texture->GetWidth() > 0.0f)
@ -53,9 +63,9 @@ inline void DrawTextureImpl(
uvs[idx + 1] /= texture->GetHeight();
}
shader->Uniform(str_colorAdd, add);
shader->Uniform(str_colorMul, multiply);
shader->Uniform(str_grayscaleFactor, grayscaleFactor);
deviceCommandContext->SetUniform(bindingSlots.colorAdd, add.AsFloatArray());
deviceCommandContext->SetUniform(bindingSlots.colorMul, multiply.AsFloatArray());
deviceCommandContext->SetUniform(bindingSlots.grayscaleFactor, grayscaleFactor);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
@ -87,12 +97,22 @@ public:
CShaderDefines defines;
Tech = g_Renderer.GetShaderManager().LoadEffect(str_canvas2d, defines);
// The canvas technique must be loaded because we can't render UI without it.
ENSURE(Tech);
DeviceCommandContext->SetGraphicsPipelineState(
Tech->GetGraphicsPipelineStateDesc());
DeviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = Tech->GetShader();
shader->Uniform(str_transform, GetDefaultGuiMatrix());
Renderer::Backend::IShaderProgram* shader = Tech->GetShader();
BindingSlots.transform = shader->GetBindingSlot(str_transform);
BindingSlots.colorAdd = shader->GetBindingSlot(str_colorAdd);
BindingSlots.colorMul = shader->GetBindingSlot(str_colorMul);
BindingSlots.grayscaleFactor = shader->GetBindingSlot(str_grayscaleFactor);
BindingSlots.tex = shader->GetBindingSlot(str_tex);
const CMatrix3D transform = GetDefaultGuiMatrix();
DeviceCommandContext->SetUniform(
BindingSlots.transform, transform.AsFloatArray());
}
void UnbindTech()
@ -106,6 +126,10 @@ public:
Renderer::Backend::GL::CDeviceCommandContext* DeviceCommandContext;
CShaderTechniquePtr Tech;
// We assume that the shader can't be destroyed while it's bound. So these
// bindings remain valid while the shader is alive.
SBindingSlots BindingSlots;
};
CCanvas2D::CCanvas2D(
@ -251,11 +275,16 @@ void CCanvas2D::DrawLine(const std::vector<CVector2D>& points, const float width
m->BindTechIfNeeded();
Renderer::Backend::GL::CShaderProgram* shader = m->Tech->GetShader();
shader->BindTexture(str_tex, g_Renderer.GetTextureManager().GetAlphaGradientTexture()->GetBackendTexture());
shader->Uniform(str_colorAdd, CColor(0.0f, 0.0f, 0.0f, 0.0f));
shader->Uniform(str_colorMul, color);
shader->Uniform(str_grayscaleFactor, 0.0f);
m->DeviceCommandContext->SetTexture(
m->BindingSlots.tex,
g_Renderer.GetTextureManager().GetAlphaGradientTexture()->GetBackendTexture());
const CColor colorAdd(0.0f, 0.0f, 0.0f, 0.0f);
m->DeviceCommandContext->SetUniform(
m->BindingSlots.colorAdd, colorAdd.AsFloatArray());
m->DeviceCommandContext->SetUniform(
m->BindingSlots.colorMul, color.AsFloatArray());
m->DeviceCommandContext->SetUniform(
m->BindingSlots.grayscaleFactor, 0.0f);
m->DeviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
@ -290,9 +319,10 @@ void CCanvas2D::DrawRect(const CRect& rect, const CColor& color)
m->BindTechIfNeeded();
DrawTextureImpl(
m->DeviceCommandContext, m->Tech->GetShader(),
m->DeviceCommandContext,
g_Renderer.GetTextureManager().GetTransparentTexture(),
vertices, uvs, CColor(0.0f, 0.0f, 0.0f, 0.0f), color, 0.0f);
vertices, uvs, CColor(0.0f, 0.0f, 0.0f, 0.0f), color, 0.0f,
m->BindingSlots);
}
void CCanvas2D::DrawTexture(CTexturePtr texture, const CRect& destination)
@ -326,18 +356,19 @@ void CCanvas2D::DrawTexture(
};
m->BindTechIfNeeded();
DrawTextureImpl(m->DeviceCommandContext, m->Tech->GetShader(),
texture, vertices, uvs, multiply, add, grayscaleFactor);
DrawTextureImpl(
m->DeviceCommandContext, texture, vertices, uvs,
multiply, add, grayscaleFactor, m->BindingSlots);
}
void CCanvas2D::DrawText(CTextRenderer& textRenderer)
{
m->BindTechIfNeeded();
Renderer::Backend::GL::CShaderProgram* shader = m->Tech->GetShader();
shader->Uniform(str_grayscaleFactor, 0.0f);
m->DeviceCommandContext->SetUniform(
m->BindingSlots.grayscaleFactor, 0.0f);
textRenderer.Render(m->DeviceCommandContext, shader, GetDefaultGuiMatrix());
textRenderer.Render(m->DeviceCommandContext, m->Tech->GetShader(), GetDefaultGuiMatrix());
}
void CCanvas2D::Flush()

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/SColor.h"
#include "maths/Vector3D.h"
#include "maths/Vector4D.h"
#include "ps/containers/Span.h"
#include "ps/CStrForward.h"
// Simple defines for 3 and 4 component floating point colors - just map to
@ -66,7 +67,7 @@ struct CColor
}
// For passing to uniform as vec3/vec4.
const float* AsFloatArray() const
PS::span<const float> AsFloatArray() const
{
// Additional check to prevent a weird compiler has a different
// alignement for an array and a class members.
@ -77,7 +78,7 @@ struct CColor
offsetof(CColor, b) == sizeof(float) * 2u &&
offsetof(CColor, a) == sizeof(float) * 3u,
"CColor should be properly layouted to use AsFloatArray");
return &r;
return PS::span(&r, 4);
}
// For passing to CRenderer:

View File

@ -80,7 +80,7 @@ CLOSTexture::~CLOSTexture()
bool CLOSTexture::CreateShader()
{
m_SmoothTech = g_Renderer.GetShaderManager().LoadEffect(str_los_interp);
Renderer::Backend::GL::CShaderProgram* shader = m_SmoothTech->GetShader();
Renderer::Backend::IShaderProgram* shader = m_SmoothTech->GetShader();
m_ShaderInitialized = m_SmoothTech && shader;
@ -145,12 +145,16 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
m_SmoothTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = m_SmoothTech->GetShader();
Renderer::Backend::IShaderProgram* shader = m_SmoothTech->GetShader();
shader->BindTexture(str_losTex1, m_Texture.get());
shader->BindTexture(str_losTex2, m_SmoothTextures[m_WhichTexture].get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex1), m_Texture.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex2), m_SmoothTextures[m_WhichTexture].get());
shader->Uniform(str_delta, (float)g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f, 0.0f, 0.0f, 0.0f);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_delta),
static_cast<float>(g_Renderer.GetTimeManager().GetFrameDelta() * 4.0f));
const SViewPort oldVp = g_Renderer.GetViewport();
const SViewPort vp =

View File

@ -366,7 +366,7 @@ void CMiniMapTexture::RenderFinalTexture(
const float invTileMapSize = 1.0f / static_cast<float>(TERRAIN_TILE_SIZE * m_MapSize);
const float texCoordMax = m_TerrainTexture ? static_cast<float>(m_MapSize - 1) / m_TerrainTexture->GetWidth() : 1.0f;
Renderer::Backend::GL::CShaderProgram* shader;
Renderer::Backend::IShaderProgram* shader = nullptr;
CShaderTechniquePtr tech;
CShaderDefines baseDefines;
@ -380,7 +380,10 @@ void CMiniMapTexture::RenderFinalTexture(
shader = tech->GetShader();
if (m_TerrainTexture)
shader->BindTexture(str_baseTex, m_TerrainTexture.get());
{
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), m_TerrainTexture.get());
}
CMatrix3D baseTransform;
baseTransform.SetIdentity();
@ -390,8 +393,10 @@ void CMiniMapTexture::RenderFinalTexture(
CMatrix3D terrainTransform;
terrainTransform.SetIdentity();
terrainTransform.Scale(texCoordMax, texCoordMax, 1.0f);
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, terrainTransform);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), baseTransform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_textureTransform), terrainTransform.AsFloatArray());
if (m_TerrainTexture)
DrawTexture(deviceCommandContext);
@ -414,9 +419,13 @@ void CMiniMapTexture::RenderFinalTexture(
// Draw territory boundaries
CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture();
shader->BindTexture(str_baseTex, territoryTexture.GetTexture());
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, territoryTexture.GetMinimapTextureMatrix());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), territoryTexture.GetTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), baseTransform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_textureTransform),
territoryTexture.GetMinimapTextureMatrix().AsFloatArray());
DrawTexture(deviceCommandContext);
deviceCommandContext->EndPass();
@ -427,9 +436,13 @@ void CMiniMapTexture::RenderFinalTexture(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
shader->BindTexture(str_baseTex, losTexture.GetTexture());
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, losTexture.GetMinimapTextureMatrix());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), losTexture.GetTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), baseTransform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_textureTransform),
losTexture.GetMinimapTextureMatrix().AsFloatArray());
DrawTexture(deviceCommandContext);
@ -442,7 +455,8 @@ void CMiniMapTexture::RenderFinalTexture(
tech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
shader = tech->GetShader();
shader->Uniform(str_transform, baseTransform);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), baseTransform.AsFloatArray());
CMatrix3D unitMatrix;
unitMatrix.SetIdentity();
@ -451,7 +465,8 @@ void CMiniMapTexture::RenderFinalTexture(
unitMatrix.Scale(unitScale * 2.0f, unitScale * 2.0f, 1.0f);
// Offset the coordinates to [-1, 1].
unitMatrix.Translate(CVector3D(-1.0f, -1.0f, 0.0f));
shader->Uniform(str_transform, unitMatrix);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), unitMatrix.AsFloatArray());
if (doUpdate)
{

View File

@ -200,7 +200,7 @@ static void SkinPointsAndNormalsSSE(
const CMatrix3D& mtx = newPoseMatrices[blendIndices[j]];
// Loads matrix to xmm registers.
const float* data = mtx.AsFloatArray();
const float* data = mtx.AsFloatArray().data();
col0 = _mm_load_ps(data);
col1 = _mm_load_ps(data + 4);
col2 = _mm_load_ps(data + 8);

View File

@ -176,25 +176,32 @@ void CParticleEmitter::PrepareForRendering()
void CParticleEmitter::Bind(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader)
Renderer::Backend::IShaderProgram* shader)
{
m_Type->m_Texture->UploadBackendTextureIfNeeded(deviceCommandContext);
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
shader->BindTexture(str_losTex, los.GetTextureSmooth());
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex), los.GetTextureSmooth());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
const CLightEnv& lightEnv = g_Renderer.GetSceneRenderer().GetLightEnv();
shader->Uniform(str_sunColor, lightEnv.m_SunColor);
shader->Uniform(str_fogColor, lightEnv.m_FogColor);
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
shader->BindTexture(str_baseTex, m_Type->m_Texture->GetBackendTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_sunColor), lightEnv.m_SunColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogColor), lightEnv.m_FogColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogParams), lightEnv.m_FogFactor, lightEnv.m_FogMax);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), m_Type->m_Texture->GetBackendTexture());
}
void CParticleEmitter::RenderArray(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader))
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
if (m_Particles.empty())
return;

View File

@ -22,7 +22,7 @@
#include "graphics/ParticleEmitterType.h"
#include "maths/Quaternion.h"
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/VertexArray.h"
#include <map>
@ -124,14 +124,13 @@ public:
*/
void Bind(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader);
Renderer::Backend::IShaderProgram* shader);
/**
* Draw the vertex array.
*/
void RenderArray(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
/**
* Stop this emitter emitting new particles, and pass responsibility for rendering

View File

@ -225,13 +225,15 @@ CVector4D CShaderUniforms::GetVector(const char* name) const
return CVector4D();
}
void CShaderUniforms::BindUniforms(Renderer::Backend::GL::CShaderProgram* shader) const
void CShaderUniforms::BindUniforms(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) const
{
const std::vector<SItems::Item>& items = m_Items->items;
for (size_t i = 0; i < items.size(); ++i)
for (const SItems::Item& item : m_Items->items)
{
const CVector4D& v = items[i].second;
shader->Uniform(items[i].first, v.X, v.Y, v.Z, v.W);
const CVector4D& v = item.second;
deviceCommandContext->SetUniform(
shader->GetBindingSlot(item.first), v.AsFloatArray());
}
}

View File

@ -20,7 +20,8 @@
#include "ps/CStr.h"
#include "ps/CStrIntern.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/IShaderProgram.h"
#include <map>
#include <unordered_map>
@ -178,7 +179,9 @@ public:
/**
* Bind the collection of uniforms onto the given shader.
*/
void BindUniforms(Renderer::Backend::GL::CShaderProgram* shader) const;
void BindUniforms(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) const;
};
// Add here the types of queries we can make in the renderer

View File

@ -35,7 +35,7 @@ CShaderProgramPtr CShaderProgram::Create(const CStr& name, const CShaderDefines&
void CShaderProgram::Reload()
{
std::unique_ptr<Renderer::Backend::GL::CShaderProgram> backendShaderProgram =
std::unique_ptr<Renderer::Backend::IShaderProgram> backendShaderProgram =
g_VideoMode.GetBackendDevice()->CreateShaderProgram(m_Name, m_Defines);
if (backendShaderProgram)
m_BackendShaderProgram = std::move(backendShaderProgram);

View File

@ -22,7 +22,6 @@
#include "graphics/ShaderProgramPtr.h"
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/IShaderProgram.h"
#include <vector>
@ -42,7 +41,7 @@ public:
std::vector<VfsPath> GetFileDependencies() const;
Renderer::Backend::GL::CShaderProgram* GetBackendShaderProgram() { return m_BackendShaderProgram.get(); }
Renderer::Backend::IShaderProgram* GetBackendShaderProgram() { return m_BackendShaderProgram.get(); }
// TODO: add reloadable handles.
@ -51,7 +50,7 @@ protected:
CStr m_Name;
CShaderDefines m_Defines;
std::unique_ptr<Renderer::Backend::GL::CShaderProgram> m_BackendShaderProgram;
std::unique_ptr<Renderer::Backend::IShaderProgram> m_BackendShaderProgram;
};
#endif // INCLUDED_SHADERPROGRAM

View File

@ -41,7 +41,7 @@ int CShaderTechnique::GetNumPasses() const
return m_Passes.size();
}
Renderer::Backend::GL::CShaderProgram* CShaderTechnique::GetShader(int pass) const
Renderer::Backend::IShaderProgram* CShaderTechnique::GetShader(int pass) const
{
ENSURE(0 <= pass && pass < (int)m_Passes.size());
return m_Passes[pass].GetShader();

View File

@ -33,7 +33,7 @@ class CShaderPass
public:
CShaderPass(const Renderer::Backend::GraphicsPipelineStateDesc& pipelineStateDesc, const CShaderProgramPtr& shader);
Renderer::Backend::GL::CShaderProgram* GetShader() const { return m_Shader->GetBackendShaderProgram(); }
Renderer::Backend::IShaderProgram* GetShader() const { return m_Shader->GetBackendShaderProgram(); }
const Renderer::Backend::GraphicsPipelineStateDesc&
GetPipelineStateDesc() const { return m_PipelineStateDesc; }
@ -56,7 +56,7 @@ public:
int GetNumPasses() const;
Renderer::Backend::GL::CShaderProgram* GetShader(int pass = 0) const;
Renderer::Backend::IShaderProgram* GetShader(int pass = 0) const;
const Renderer::Backend::GraphicsPipelineStateDesc&
GetGraphicsPipelineStateDesc(int pass = 0) const;

View File

@ -204,7 +204,7 @@ struct SBatchCompare
void CTextRenderer::Render(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CMatrix3D& transform)
Renderer::Backend::IShaderProgram* shader, const CMatrix3D& transform)
{
std::vector<u16> indexes;
std::vector<t2f_v2i> vertexes;
@ -225,6 +225,11 @@ void CTextRenderer::Render(
++it;
}
const int32_t texBindingSlot = shader->GetBindingSlot(str_tex);
const int32_t transformBindingSlot = shader->GetBindingSlot(str_transform);
const int32_t colorAddBindingSlot = shader->GetBindingSlot(str_colorAdd);
const int32_t colorMulBindingSlot = shader->GetBindingSlot(str_colorMul);
bool transformChanged = false;
CTexture* lastTexture = nullptr;
@ -238,25 +243,26 @@ void CTextRenderer::Render(
{
lastTexture = batch.font->GetTexture().get();
lastTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_tex, lastTexture->GetBackendTexture());
deviceCommandContext->SetTexture(texBindingSlot, lastTexture->GetBackendTexture());
}
if (batch.translate.X != 0.0f || batch.translate.Y != 0.0f)
{
CMatrix3D translation;
translation.SetTranslation(batch.translate.X, batch.translate.Y, 0.0f);
shader->Uniform(str_transform, transform * translation);
CMatrix3D localTransform;
localTransform.SetTranslation(batch.translate.X, batch.translate.Y, 0.0f);
localTransform = transform * localTransform;
deviceCommandContext->SetUniform(transformBindingSlot, localTransform.AsFloatArray());
transformChanged = true;
}
// ALPHA-only textures will have .rgb sampled as 0, so we need to
// replace it with white (but not affect RGBA textures)
if (batch.font->HasRGB())
shader->Uniform(str_colorAdd, CColor(0.0f, 0.0f, 0.0f, 0.0f));
deviceCommandContext->SetUniform(colorAddBindingSlot, 0.0f, 0.0f, 0.0f, 0.0f);
else
shader->Uniform(str_colorAdd, CColor(batch.color.r, batch.color.g, batch.color.b, 0.0f));
deviceCommandContext->SetUniform(colorAddBindingSlot, batch.color.r, batch.color.g, batch.color.b, 0.0f);
shader->Uniform(str_colorMul, batch.color);
deviceCommandContext->SetUniform(colorMulBindingSlot, batch.color.AsFloatArray());
vertexes.resize(std::min(MAX_CHAR_COUNT_PER_BATCH, batch.chars) * 4);
indexes.resize(std::min(MAX_CHAR_COUNT_PER_BATCH, batch.chars) * 6);
@ -339,5 +345,5 @@ void CTextRenderer::Render(
m_Batches.clear();
if (transformChanged)
shader->Uniform(str_transform, transform);
deviceCommandContext->SetUniform(transformBindingSlot, transform.AsFloatArray());
}

View File

@ -105,7 +105,7 @@ public:
*/
void Render(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CMatrix3D& transform);
Renderer::Backend::IShaderProgram* shader, const CMatrix3D& transform);
private:
friend struct SBatchCompare;

View File

@ -415,13 +415,10 @@ void CMiniMap::Draw(CCanvas2D& canvas)
CMiniMapTexture& miniMapTexture = g_Game->GetView()->GetMiniMapTexture();
if (miniMapTexture.GetTexture())
{
Renderer::Backend::GL::CShaderProgram* shader;
CShaderTechniquePtr tech;
CShaderDefines baseDefines;
baseDefines.Add(str_MINIMAP_BASE, str_1);
tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines);
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, baseDefines);
Renderer::Backend::GraphicsPipelineStateDesc pipelineStateDesc =
tech->GetGraphicsPipelineStateDesc();
pipelineStateDesc.blendState.enabled = true;
@ -435,14 +432,20 @@ void CMiniMap::Draw(CCanvas2D& canvas)
g_Renderer.GetDeviceCommandContext();
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
shader = tech->GetShader();
shader->BindTexture(str_baseTex, miniMapTexture.GetTexture());
Renderer::Backend::IShaderProgram* shader = tech->GetShader();
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), miniMapTexture.GetTexture());
const CMatrix3D baseTransform = GetDefaultGuiMatrix();
CMatrix3D baseTextureTransform;
baseTextureTransform.SetIdentity();
shader->Uniform(str_transform, baseTransform);
shader->Uniform(str_textureTransform, baseTextureTransform);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), baseTransform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_textureTransform), baseTextureTransform.AsFloatArray());
const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;

View File

@ -25,6 +25,7 @@
#include "maths/Vector3D.h"
#include "maths/Vector4D.h"
#include "ps/containers/Span.h"
class CQuaternion;
@ -323,7 +324,7 @@ public:
CVector3D RotateTransposed(const CVector3D& vector) const;
// Returns 16 element array of floats, e.g. for mat4 uniforms.
const float* AsFloatArray() const
PS::span<const float> AsFloatArray() const
{
// Additional check to prevent a weird compiler has a different
// alignement for an array and a class members.
@ -333,7 +334,7 @@ public:
offsetof(CMatrix3D, _11) == 0 &&
offsetof(CMatrix3D, _44) == sizeof(float) * 15u,
"CMatrix3D should be properly layouted to use AsFloatArray");
return _data;
return PS::span<const float>(_data, 16);
}
};

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,8 @@
#ifndef INCLUDED_VECTOR3D
#define INCLUDED_VECTOR3D
#include "ps/containers/Span.h"
class CFixedVector3D;
class CVector3D
@ -121,7 +123,7 @@ class CVector3D
CVector3D Normalized() const;
// Returns 3 element array of floats, e.g. for vec3 uniforms.
const float* AsFloatArray() const
PS::span<const float> AsFloatArray() const
{
// Additional check to prevent a weird compiler has a different
// alignement for an array and a class members.
@ -131,7 +133,7 @@ class CVector3D
offsetof(CVector3D, Y) == sizeof(float) &&
offsetof(CVector3D, Z) == sizeof(float) * 2u,
"Vector3D should be properly layouted to use AsFloatArray");
return &X;
return PS::span<const float>(&X, 3);
}
};

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2012 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,8 @@
#ifndef INCLUDED_VECTOR4D
#define INCLUDED_VECTOR4D
#include "ps/containers/Span.h"
#include <math.h>
class CVector4D
@ -124,8 +126,20 @@ public:
return X*a.X + Y*a.Y + Z*a.Z + W*a.W;
}
// Returns 4 element array of floats, e.g. for vec4 uniforms.
PS::span<const float> AsFloatArray() const
{
// Additional check to prevent a weird compiler has a different
// alignement for an array and a class members.
static_assert(
sizeof(CVector4D) == sizeof(float) * 4u &&
offsetof(CVector4D, X) == 0 &&
offsetof(CVector4D, W) == sizeof(float) * 3u,
"CVector4D should be properly layouted to use AsFloatArray");
return PS::span<const float>(&X, 4);
}
float X, Y, Z, W;
};
#endif
#endif // INCLUDED_VECTOR4D

View File

@ -0,0 +1,76 @@
/* 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_PS_SPAN
#define INCLUDED_PS_SPAN
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace PS
{
/**
* Simplifed version of std::span (C++20) as we don't support the original one
* yet. The naming intentionally follows the STL version to make the future
* replacement easier with less blame changing.
* It supports only very basic subset of std::span functionality.
* TODO: remove as soon as std::span become available.
*/
template<typename T>
class span
{
public:
using element_type = T;
using value_type = std::remove_cv_t<T>;
using size_type = std::size_t;
using pointer = T*;
using reference = T&;
using iterator = pointer;
constexpr span()
: m_Pointer(nullptr), m_Extent(0) {}
constexpr span(iterator first, size_type extent)
: m_Pointer(first), m_Extent(extent) {}
constexpr span(iterator first, iterator last)
: m_Pointer(first), m_Extent(static_cast<size_type>(last - first)) {}
constexpr span(const span& other) = default;
constexpr span& operator=(const span& other) = default;
~span() = default;
constexpr size_type size() const { return m_Extent; }
constexpr bool empty() const { return size() == 0; }
constexpr reference operator[](size_type index) const { return *(m_Pointer + index); }
constexpr pointer data() const { return m_Pointer; }
constexpr iterator begin() const { return m_Pointer; }
constexpr iterator end() const { return m_Pointer + m_Extent; }
private:
pointer m_Pointer;
size_type m_Extent;
};
} // namespace PS
#endif // INCLUDED_PS_SPAN

View File

@ -89,9 +89,12 @@ void CDebugRenderer::DrawLine(
const CCamera& viewCamera = g_Renderer.GetSceneRenderer().GetViewCamera();
Renderer::Backend::GL::CShaderProgram* debugLineShader = debugLineTech->GetShader();
debugLineShader->Uniform(str_transform, viewCamera.GetViewProjection());
debugLineShader->Uniform(str_color, color);
Renderer::Backend::IShaderProgram* debugLineShader = debugLineTech->GetShader();
const CMatrix3D transform = viewCamera.GetViewProjection();
deviceCommandContext->SetUniform(
debugLineShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
debugLineShader->GetBindingSlot(str_color), color.AsFloatArray());
const CVector3D cameraIn = viewCamera.GetOrientation().GetIn();
@ -144,9 +147,13 @@ void CDebugRenderer::DrawCircle(const CVector3D& origin, const float radius, con
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
Renderer::Backend::GL::CShaderProgram* debugCircleShader = debugCircleTech->GetShader();
debugCircleShader->Uniform(str_transform, camera.GetViewProjection());
debugCircleShader->Uniform(str_color, color);
Renderer::Backend::IShaderProgram* debugCircleShader = debugCircleTech->GetShader();
const CMatrix3D transform = camera.GetViewProjection();
deviceCommandContext->SetUniform(
debugCircleShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
debugCircleShader->GetBindingSlot(str_color), color.AsFloatArray());
const CVector3D cameraUp = camera.GetOrientation().GetUp();
const CVector3D cameraLeft = camera.GetOrientation().GetLeft();
@ -202,9 +209,13 @@ void CDebugRenderer::DrawCameraFrustum(const CCamera& camera, const CColor& colo
deviceCommandContext, overlayTech, color, true, wireframe);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* overlayShader = overlayTech->GetShader();
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
overlayShader->Uniform(str_color, color);
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader();
const CMatrix3D transform = g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_color), color.AsFloatArray());
std::vector<float> vertices;
#define ADD(position) \
@ -297,9 +308,12 @@ void CDebugRenderer::DrawBoundingBox(
deviceCommandContext, shaderTech, color, true, wireframe);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = shaderTech->GetShader();
shader->Uniform(str_color, color);
shader->Uniform(str_transform, transform);
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_color), color.AsFloatArray());
std::vector<float> data;
@ -341,9 +355,13 @@ void CDebugRenderer::DrawBrush(const CBrush& brush, const CColor& color, bool wi
deviceCommandContext, shaderTech, color, true, wireframe);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = shaderTech->GetShader();
shader->Uniform(str_color, color);
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
const CMatrix3D transform = g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_color), color.AsFloatArray());
std::vector<float> data;

View File

@ -176,11 +176,14 @@ void CDecalRData::RenderDecals(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(shader, shadow);
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(deviceCommandContext, shader, shadow);
CColor shadingColor(1.0f, 1.0f, 1.0f, 1.0f);
shader->Uniform(str_shadingColor, shadingColor);
const int32_t shadingColorBindingSlot =
shader->GetBindingSlot(str_shadingColor);
deviceCommandContext->SetUniform(
shadingColorBindingSlot, shadingColor.AsFloatArray());
CShaderUniforms currentStaticUniforms;
@ -195,12 +198,16 @@ void CDecalRData::RenderDecals(
for (const CMaterial::TextureSampler& sampler : samplers)
sampler.Sampler->UploadBackendTextureIfNeeded(deviceCommandContext);
for (const CMaterial::TextureSampler& sampler : samplers)
shader->BindTexture(sampler.Name, sampler.Sampler->GetBackendTexture());
{
deviceCommandContext->SetTexture(
shader->GetBindingSlot(sampler.Name),
sampler.Sampler->GetBackendTexture());
}
if (currentStaticUniforms != material.GetStaticUniforms())
{
currentStaticUniforms = material.GetStaticUniforms();
material.GetStaticUniforms().BindUniforms(shader);
material.GetStaticUniforms().BindUniforms(deviceCommandContext, shader);
}
// TODO: Need to handle floating decals correctly. In particular, we need
@ -215,7 +222,8 @@ void CDecalRData::RenderDecals(
if (shadingColor != decal->m_Decal->GetShadingColor())
{
shadingColor = decal->m_Decal->GetShadingColor();
shader->Uniform(str_shadingColor, shadingColor);
deviceCommandContext->SetUniform(
shadingColorBindingSlot, shadingColor.AsFloatArray());
}
if (lastVB != batch.vertices->m_Owner)

View File

@ -187,7 +187,7 @@ void ShaderModelVertexRenderer::EndPass(
// Prepare UV coordinates for this modeldef
void ShaderModelVertexRenderer::PrepareModelDef(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const CModelDef& def)
const CModelDef& def)
{
m->shadermodeldef = (ShaderModelDef*)def.GetRenderData(m);
@ -216,7 +216,7 @@ void ShaderModelVertexRenderer::PrepareModelDef(
// Render one model
void ShaderModelVertexRenderer::RenderModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader), CModel* model, CModelRData* data)
Renderer::Backend::IShaderProgram* UNUSED(shader), CModel* model, CModelRData* data)
{
const CModelDefPtr& mdldef = model->GetModelDef();
ShaderModel* shadermodel = static_cast<ShaderModel*>(data);

View File

@ -44,10 +44,10 @@ public:
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) override;
void PrepareModelDef(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def) override;
const CModelDef& def) override;
void RenderModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data) override;
Renderer::Backend::IShaderProgram* shader, CModel* model, CModelRData* data) override;
protected:
struct ShaderModelRendererInternals;

View File

@ -308,7 +308,7 @@ void InstancingModelRenderer::EndPass(
// Prepare UV coordinates for this modeldef
void InstancingModelRenderer::PrepareModelDef(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const CModelDef& def)
const CModelDef& def)
{
m->imodeldef = (IModelDef*)def.GetRenderData(m);
@ -369,7 +369,7 @@ void InstancingModelRenderer::PrepareModelDef(
// Render one model
void InstancingModelRenderer::RenderModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* UNUSED(data))
Renderer::Backend::IShaderProgram* shader, CModel* model, CModelRData* UNUSED(data))
{
const CModelDefPtr& mdldef = model->GetModelDef();
@ -377,7 +377,11 @@ void InstancingModelRenderer::RenderModel(
{
// Bind matrices for current animation state.
// Add 1 to NumBones because of the special 'root' bone.
shader->Uniform(str_skinBlendMatrices, mdldef->GetNumBones() + 1, model->GetAnimatedBoneMatrices());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_skinBlendMatrices),
PS::span<const float>(
model->GetAnimatedBoneMatrices()[0]._data,
model->GetAnimatedBoneMatrices()[0].AsFloatArray().size() * (mdldef->GetNumBones() + 1)));
}
// Render the lot.

View File

@ -39,17 +39,17 @@ public:
~InstancingModelRenderer();
// Implementations
CModelRData* CreateModelData(const void* key, CModel* model);
void UpdateModelData(CModel* model, CModelRData* data, int updateflags);
CModelRData* CreateModelData(const void* key, CModel* model) override;
void UpdateModelData(CModel* model, CModelRData* data, int updateflags) override;
void BeginPass();
void BeginPass() override;
void EndPass(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext) override;
void PrepareModelDef(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def);
const CModelDef& def) override;
void RenderModel(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data);
Renderer::Backend::IShaderProgram* shader, CModel* model, CModelRData* data) override;
protected:
InstancingModelRendererInternals* m;

View File

@ -580,8 +580,8 @@ void ShaderModelRenderer::Render(
// texBindings holds the identifier bindings in the shader, which can no longer be defined
// statically in the ShaderRenderModifier class. texBindingNames uses interned strings to
// keep track of when bindings need to be reevaluated.
using BindingListAllocator = ProxyAllocator<Renderer::Backend::GL::CShaderProgram::Binding, Arena>;
std::vector<Renderer::Backend::GL::CShaderProgram::Binding, BindingListAllocator> texBindings((BindingListAllocator(arena)));
using BindingListAllocator = ProxyAllocator<int32_t, Arena>;
std::vector<int32_t, BindingListAllocator> texBindings((BindingListAllocator(arena)));
texBindings.reserve(64);
using BindingNamesListAllocator = ProxyAllocator<CStrIntern, Arena>;
@ -607,9 +607,9 @@ void ShaderModelRenderer::Render(
currentTech->GetGraphicsPipelineStateDesc(pass));
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = currentTech->GetShader(pass);
Renderer::Backend::IShaderProgram* shader = currentTech->GetShader(pass);
modifier->BeginPass(shader);
modifier->BeginPass(deviceCommandContext, shader);
// TODO: Use a more generic approach to handle bound queries.
bool boundTime = false;
@ -647,12 +647,12 @@ void ShaderModelRenderer::Render(
if (currentTexs.size() != samplersNum)
{
currentTexs.resize(samplersNum, NULL);
texBindings.resize(samplersNum, Renderer::Backend::GL::CShaderProgram::Binding());
texBindings.resize(samplersNum, -1);
texBindingNames.resize(samplersNum, CStrIntern());
// ensure they are definitely empty
std::fill(texBindings.begin(), texBindings.end(), Renderer::Backend::GL::CShaderProgram::Binding());
std::fill(currentTexs.begin(), currentTexs.end(), (CTexture*)NULL);
std::fill(texBindings.begin(), texBindings.end(), -1);
std::fill(currentTexs.begin(), currentTexs.end(), nullptr);
std::fill(texBindingNames.begin(), texBindingNames.end(), CStrIntern());
}
@ -663,18 +663,19 @@ void ShaderModelRenderer::Render(
// check that the handles are current
// and reevaluate them if necessary
if (texBindingNames[s] != samp.Name || !texBindings[s].Active())
if (texBindingNames[s] != samp.Name || texBindings[s] < 0)
{
texBindings[s] = shader->GetTextureBinding(samp.Name);
texBindings[s] = shader->GetBindingSlot(samp.Name);
texBindingNames[s] = samp.Name;
}
// same with the actual sampler bindings
CTexture* newTex = samp.Sampler.get();
if (texBindings[s].Active() && newTex != currentTexs[s])
if (texBindings[s] >= 0 && newTex != currentTexs[s])
{
newTex->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(texBindings[s], newTex->GetBackendTexture());
deviceCommandContext->SetTexture(
texBindings[s], newTex->GetBackendTexture());
currentTexs[s] = newTex;
}
}
@ -684,7 +685,7 @@ void ShaderModelRenderer::Render(
if (newModeldef != currentModeldef)
{
currentModeldef = newModeldef;
m->vertexRenderer->PrepareModelDef(deviceCommandContext, shader, *currentModeldef);
m->vertexRenderer->PrepareModelDef(deviceCommandContext, *currentModeldef);
}
// Bind all uniforms when any change
@ -692,7 +693,7 @@ void ShaderModelRenderer::Render(
if (newStaticUniforms != currentStaticUniforms)
{
currentStaticUniforms = newStaticUniforms;
currentStaticUniforms.BindUniforms(shader);
currentStaticUniforms.BindUniforms(deviceCommandContext, shader);
}
const CShaderRenderQueries& renderQueries = model->GetMaterial().GetRenderQueries();
@ -704,7 +705,8 @@ void ShaderModelRenderer::Render(
{
if (!boundTime)
{
shader->Uniform(rq.second, time, 0.0f, 0.0f, 0.0f);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(rq.second), time);
boundTime = true;
}
}
@ -718,10 +720,16 @@ void ShaderModelRenderer::Render(
{
const CTexturePtr& waterTexture = waterManager.m_NormalMap[waterManager.GetCurrentTextureIndex(period)];
waterTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_waterTex, waterTexture->GetBackendTexture());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_waterTex),
waterTexture->GetBackendTexture());
}
else
shader->BindTexture(str_waterTex, g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
{
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_waterTex),
g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
}
boundWaterTexture = true;
}
}
@ -729,13 +737,15 @@ void ShaderModelRenderer::Render(
{
if (!boundSkyCube)
{
shader->BindTexture(str_skyCube, g_Renderer.GetSceneRenderer().GetSkyManager().GetSkyCube());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_skyCube),
g_Renderer.GetSceneRenderer().GetSkyManager().GetSkyCube());
boundSkyCube = true;
}
}
}
modifier->PrepareModel(shader, model);
modifier->PrepareModel(deviceCommandContext, model);
CModelRData* rdata = static_cast<CModelRData*>(model->GetRenderData());
ENSURE(rdata->GetKey() == m->vertexRenderer.get());

View File

@ -26,7 +26,7 @@
#include "graphics/MeshManager.h"
#include "graphics/ShaderProgramPtr.h"
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/IShaderProgram.h"
class CModel;
class CModelRData;
@ -114,7 +114,7 @@ public:
/**
* PrepareModelDef: Setup OpenGL state for rendering of models that
* PrepareModelDef: Setup backend state for rendering of models that
* use the given CModelDef object as base.
*
* ModelRenderer implementations must call this function before
@ -126,7 +126,7 @@ public:
*/
virtual void PrepareModelDef(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const CModelDef& def) = 0;
const CModelDef& def) = 0;
/**
@ -147,7 +147,7 @@ public:
*/
virtual void RenderModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, CModel* model, CModelRData* data) = 0;
Renderer::Backend::IShaderProgram* shader, CModel* model, CModelRData* data) = 0;
};

View File

@ -401,8 +401,6 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
// ----------------------------------------------------------------------------------------
CShaderTechniquePtr shaderTechTexLineNormal = GetOverlayLineShaderTechnique(m->defsOverlayLineNormal);
if (shaderTechTexLineNormal)
{
@ -421,12 +419,18 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shaderTexLineNormal = shaderTechTexLineNormal->GetShader();
Renderer::Backend::IShaderProgram* shaderTexLineNormal = shaderTechTexLineNormal->GetShader();
shaderTexLineNormal->BindTexture(str_losTex, los.GetTexture());
shaderTexLineNormal->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetTexture(
shaderTexLineNormal->GetBindingSlot(str_losTex), los.GetTexture());
shaderTexLineNormal->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shaderTexLineNormal->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shaderTexLineNormal->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
// batch render only the non-always-visible overlay lines using the normal shader
RenderTexturedOverlayLines(deviceCommandContext, shaderTexLineNormal, false);
@ -434,8 +438,6 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC
deviceCommandContext->EndPass();
}
// ----------------------------------------------------------------------------------------
CShaderTechniquePtr shaderTechTexLineAlwaysVisible = GetOverlayLineShaderTechnique(m->defsOverlayLineAlwaysVisible);
if (shaderTechTexLineAlwaysVisible)
{
@ -454,30 +456,30 @@ void OverlayRenderer::RenderTexturedOverlayLines(Renderer::Backend::GL::CDeviceC
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shaderTexLineAlwaysVisible = shaderTechTexLineAlwaysVisible->GetShader();
Renderer::Backend::IShaderProgram* shaderTexLineAlwaysVisible = shaderTechTexLineAlwaysVisible->GetShader();
// TODO: losTex and losTransform are unused in the always visible shader; see if these can be safely omitted
shaderTexLineAlwaysVisible->BindTexture(str_losTex, los.GetTexture());
shaderTexLineAlwaysVisible->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetTexture(
shaderTexLineAlwaysVisible->GetBindingSlot(str_losTex), los.GetTexture());
shaderTexLineAlwaysVisible->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shaderTexLineAlwaysVisible->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shaderTexLineAlwaysVisible->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
// batch render only the always-visible overlay lines using the LoS-ignored shader
RenderTexturedOverlayLines(deviceCommandContext, shaderTexLineAlwaysVisible, true);
deviceCommandContext->EndPass();
}
// ----------------------------------------------------------------------------------------
// TODO: the shaders should probably be responsible for unbinding their textures
deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, 0);
}
void OverlayRenderer::RenderTexturedOverlayLines(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, bool alwaysVisible)
Renderer::Backend::IShaderProgram* shader, bool alwaysVisible)
{
for (size_t i = 0; i < m->texlines.size(); ++i)
{
@ -518,14 +520,20 @@ void OverlayRenderer::RenderQuadOverlays(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = shaderTech->GetShader();
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
shader->BindTexture(str_losTex, los.GetTexture());
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex), los.GetTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
m->quadVertices.UploadIfNeeded(deviceCommandContext);
m->quadIndices.UploadIfNeeded(deviceCommandContext);
@ -533,6 +541,9 @@ void OverlayRenderer::RenderQuadOverlays(
const uint32_t vertexStride = m->quadVertices.GetStride();
const uint32_t firstVertexOffset = m->quadVertices.GetOffset() * vertexStride;
const int32_t baseTexBindingSlot = shader->GetBindingSlot(str_baseTex);
const int32_t maskTexBindingSlot = shader->GetBindingSlot(str_maskTex);
for (OverlayRendererInternals::QuadBatchMap::iterator it = m->quadBatchMap.begin(); it != m->quadBatchMap.end(); ++it)
{
QuadBatchData& batchRenderData = it->second;
@ -545,8 +556,11 @@ void OverlayRenderer::RenderQuadOverlays(
maskPair.m_Texture->UploadBackendTextureIfNeeded(deviceCommandContext);
maskPair.m_TextureMask->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_baseTex, maskPair.m_Texture->GetBackendTexture());
shader->BindTexture(str_maskTex, maskPair.m_TextureMask->GetBackendTexture());
deviceCommandContext->SetTexture(
baseTexBindingSlot, maskPair.m_Texture->GetBackendTexture());
deviceCommandContext->SetTexture(
maskTexBindingSlot, maskPair.m_TextureMask->GetBackendTexture());
// TODO: move setting format out of the loop, we might want move the offset
// to the index offset when it's supported.
@ -573,10 +587,6 @@ void OverlayRenderer::RenderQuadOverlays(
}
deviceCommandContext->EndPass();
// TODO: the shader should probably be responsible for unbinding its textures
deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, 0);
}
void OverlayRenderer::RenderForegroundOverlays(
@ -584,6 +594,7 @@ void OverlayRenderer::RenderForegroundOverlays(
const CCamera& viewCamera)
{
PROFILE3_GPU("overlays (fg)");
GPU_SCOPED_LABEL(deviceCommandContext, "Render foreground overlays");
const CVector3D right = -viewCamera.GetOrientation().GetLeft();
const CVector3D up = viewCamera.GetOrientation().GetUp();
@ -604,9 +615,12 @@ void OverlayRenderer::RenderForegroundOverlays(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = tech->GetShader();
Renderer::Backend::IShaderProgram* shader = tech->GetShader();
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
const CVector2D uvs[6] =
{
@ -627,16 +641,21 @@ void OverlayRenderer::RenderForegroundOverlays(
deviceCommandContext->SetVertexBufferData(1, &uvs[0]);
const int32_t baseTexBindingSlot = shader->GetBindingSlot(str_baseTex);
const int32_t colorMulBindingSlot = shader->GetBindingSlot(str_colorMul);
for (size_t i = 0; i < m->sprites.size(); ++i)
{
SOverlaySprite* sprite = m->sprites[i];
if (!i || sprite->m_Texture != m->sprites[i - 1]->m_Texture)
{
sprite->m_Texture->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_baseTex, sprite->m_Texture->GetBackendTexture());
deviceCommandContext->SetTexture(
baseTexBindingSlot, sprite->m_Texture->GetBackendTexture());
}
shader->Uniform(str_colorMul, sprite->m_Color);
deviceCommandContext->SetUniform(
colorMulBindingSlot, sprite->m_Color.AsFloatArray());
const CVector3D position[6] =
{
@ -728,7 +747,7 @@ void OverlayRenderer::RenderSphereOverlays(
if (m->spheres.empty())
return;
Renderer::Backend::GL::CShaderProgram* shader;
Renderer::Backend::IShaderProgram* shader = nullptr;
CShaderTechniquePtr tech;
tech = g_Renderer.GetShaderManager().LoadEffect(str_overlay_solid);
@ -747,7 +766,10 @@ void OverlayRenderer::RenderSphereOverlays(
shader = tech->GetShader();
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
m->GenerateSphere();
@ -762,14 +784,18 @@ void OverlayRenderer::RenderSphereOverlays(
{
SOverlaySphere* sphere = m->spheres[i];
CMatrix3D transform;
transform.SetIdentity();
transform.Scale(sphere->m_Radius, sphere->m_Radius, sphere->m_Radius);
transform.Translate(sphere->m_Center);
CMatrix3D instancingTransform;
instancingTransform.SetIdentity();
instancingTransform.Scale(
sphere->m_Radius, sphere->m_Radius, sphere->m_Radius);
instancingTransform.Translate(sphere->m_Center);
shader->Uniform(str_instancingTransform, transform);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_instancingTransform),
instancingTransform.AsFloatArray());
shader->Uniform(str_color, sphere->m_Color);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_color), sphere->m_Color.AsFloatArray());
deviceCommandContext->DrawIndexed(0, m->sphereIndexes.size(), 0);

View File

@ -140,7 +140,7 @@ private:
*/
void RenderTexturedOverlayLines(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, bool alwaysVisible);
Renderer::Backend::IShaderProgram* shader, bool alwaysVisible);
/**
* Helper method; batch-renders all registered quad overlays, batched by their texture for effiency.

View File

@ -157,12 +157,18 @@ void ParticleRenderer::RenderParticles(
deviceCommandContext->SetGraphicsPipelineState(lastTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = lastTech->GetShader();
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
shader->Uniform(str_modelViewMatrix, g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse());
Renderer::Backend::IShaderProgram* shader = lastTech->GetShader();
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
const CMatrix3D modelViewMatrix =
g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetInverse();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_modelViewMatrix), modelViewMatrix.AsFloatArray());
}
emitter->Bind(deviceCommandContext, lastTech->GetShader());
emitter->RenderArray(deviceCommandContext, lastTech->GetShader());
emitter->RenderArray(deviceCommandContext);
}
if (lastTech)

View File

@ -774,29 +774,43 @@ void CPatchRData::RenderBases(
deviceCommandContext->SetGraphicsPipelineState(
techBase->GetGraphicsPipelineStateDesc(pass));
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(shader, shadow);
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(deviceCommandContext, shader, shadow);
const int32_t baseTexBindingSlot =
shader->GetBindingSlot(str_baseTex);
const int32_t textureTransformBindingSlot =
shader->GetBindingSlot(str_textureTransform);
TextureBatches& textureBatches = itTech->second;
for (TextureBatches::iterator itt = textureBatches.begin(); itt != textureBatches.end(); ++itt)
{
if (!itt->first->GetMaterial().GetSamplers().empty())
{
const CMaterial::SamplersVector& samplers = itt->first->GetMaterial().GetSamplers();
const CMaterial::SamplersVector& samplers =
itt->first->GetMaterial().GetSamplers();
for(const CMaterial::TextureSampler& samp : samplers)
samp.Sampler->UploadBackendTextureIfNeeded(deviceCommandContext);
for(const CMaterial::TextureSampler& samp : samplers)
shader->BindTexture(samp.Name, samp.Sampler->GetBackendTexture());
{
deviceCommandContext->SetTexture(
shader->GetBindingSlot(samp.Name),
samp.Sampler->GetBackendTexture());
}
itt->first->GetMaterial().GetStaticUniforms().BindUniforms(shader);
itt->first->GetMaterial().GetStaticUniforms().BindUniforms(
deviceCommandContext, shader);
float c = itt->first->GetTextureMatrix()[0];
float ms = itt->first->GetTextureMatrix()[8];
shader->Uniform(str_textureTransform, c, ms, -ms, 0.f);
deviceCommandContext->SetUniform(
textureTransformBindingSlot, c, ms);
}
else
{
shader->BindTexture(str_baseTex, g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
deviceCommandContext->SetTexture(
baseTexBindingSlot,
g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
}
for (VertexBufferBatches::iterator itv = itt->second.begin(); itv != itt->second.end(); ++itv)
@ -970,7 +984,7 @@ void CPatchRData::RenderBlends(
PROFILE_END("compute batches");
CVertexBuffer* lastVB = nullptr;
Renderer::Backend::GL::CShaderProgram* previousShader = nullptr;
Renderer::Backend::IShaderProgram* previousShader = nullptr;
for (BatchesStack::iterator itTechBegin = batches.begin(), itTechEnd = batches.begin(); itTechBegin != batches.end(); itTechBegin = itTechEnd)
{
while (itTechEnd != batches.end() && itTechEnd->m_ShaderTech == itTechBegin->m_ShaderTech)
@ -992,11 +1006,18 @@ void CPatchRData::RenderBlends(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(shader, shadow);
Renderer::Backend::IShaderProgram* shader = techBase->GetShader(pass);
TerrainRenderer::PrepareShader(deviceCommandContext, shader, shadow);
Renderer::Backend::GL::CTexture* lastBlendTex = nullptr;
const int32_t baseTexBindingSlot =
shader->GetBindingSlot(str_baseTex);
const int32_t blendTexBindingSlot =
shader->GetBindingSlot(str_blendTex);
const int32_t textureTransformBindingSlot =
shader->GetBindingSlot(str_textureTransform);
for (BatchesStack::iterator itt = itTechBegin; itt != itTechEnd; ++itt)
{
if (itt->m_Texture->GetMaterial().GetSamplers().empty())
@ -1008,24 +1029,31 @@ void CPatchRData::RenderBlends(
for (const CMaterial::TextureSampler& samp : samplers)
samp.Sampler->UploadBackendTextureIfNeeded(deviceCommandContext);
for (const CMaterial::TextureSampler& samp : samplers)
shader->BindTexture(samp.Name, samp.Sampler->GetBackendTexture());
{
deviceCommandContext->SetTexture(
shader->GetBindingSlot(samp.Name),
samp.Sampler->GetBackendTexture());
}
Renderer::Backend::GL::CTexture* currentBlendTex = itt->m_Texture->m_TerrainAlpha->second.m_CompositeAlphaMap.get();
if (currentBlendTex != lastBlendTex)
{
shader->BindTexture(str_blendTex, currentBlendTex);
deviceCommandContext->SetTexture(
blendTexBindingSlot, currentBlendTex);
lastBlendTex = currentBlendTex;
}
itt->m_Texture->GetMaterial().GetStaticUniforms().BindUniforms(shader);
itt->m_Texture->GetMaterial().GetStaticUniforms().BindUniforms(deviceCommandContext, shader);
float c = itt->m_Texture->GetTextureMatrix()[0];
float ms = itt->m_Texture->GetTextureMatrix()[8];
shader->Uniform(str_textureTransform, c, ms, -ms, 0.f);
deviceCommandContext->SetUniform(
textureTransformBindingSlot, c, ms);
}
else
{
shader->BindTexture(str_baseTex, g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
deviceCommandContext->SetTexture(
baseTexBindingSlot, g_Renderer.GetTextureManager().GetErrorTexture()->GetBackendTexture());
}
for (VertexBufferBatches::iterator itv = itt->m_Batches.begin(); itv != itt->m_Batches.end(); ++itv)
@ -1083,8 +1111,7 @@ void CPatchRData::RenderBlends(
void CPatchRData::RenderStreams(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, Renderer::Backend::GL::CShaderProgram* UNUSED(shader),
const bool bindPositionAsTexCoord)
const std::vector<CPatchRData*>& patches, const bool bindPositionAsTexCoord)
{
PROFILE3("render terrain streams");
@ -1184,7 +1211,7 @@ void CPatchRData::RenderOutline()
void CPatchRData::RenderSides(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, Renderer::Backend::GL::CShaderProgram* UNUSED(shader))
const std::vector<CPatchRData*>& patches)
{
PROFILE3("render terrain sides");
GPU_SCOPED_LABEL(deviceCommandContext, "Render terrain sides");
@ -1449,7 +1476,7 @@ void CPatchRData::BuildWater()
void CPatchRData::RenderWaterSurface(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader), const bool bindWaterData)
const bool bindWaterData)
{
ASSERT(m_UpdateFlags == 0);
@ -1484,8 +1511,7 @@ void CPatchRData::RenderWaterSurface(
}
void CPatchRData::RenderWaterShore(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* UNUSED(shader))
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
ASSERT(m_UpdateFlags == 0);

View File

@ -23,7 +23,7 @@
#include "maths/Vector2D.h"
#include "maths/Vector3D.h"
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/IShaderProgram.h"
#include "renderer/VertexBufferManager.h"
#include <vector>
@ -50,10 +50,9 @@ public:
void RenderWaterSurface(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader, const bool bindWaterData);
const bool bindWaterData);
void RenderWaterShore(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::GL::CShaderProgram* shader);
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
CPatch* GetPatch() { return m_Patch; }
@ -67,13 +66,12 @@ public:
const std::vector<CPatchRData*>& patches, const CShaderDefines& context, ShadowMap* shadow);
static void RenderStreams(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, Renderer::Backend::GL::CShaderProgram* shader,
const bool bindPositionAsTexCoord);
const std::vector<CPatchRData*>& patches, const bool bindPositionAsTexCoord);
static void RenderSides(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const std::vector<CPatchRData*>& patches, Renderer::Backend::GL::CShaderProgram* shader);
const std::vector<CPatchRData*>& patches);
static void PrepareShader(Renderer::Backend::GL::CShaderProgram* shader, ShadowMap* shadow);
static void PrepareShader(ShadowMap* shadow);
private:
friend struct SBlendStackItem;

View File

@ -201,9 +201,10 @@ void CPostprocManager::ApplyBlurDownscale2x(
deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = tech->GetShader();
Renderer::Backend::IShaderProgram* shader = tech->GetShader();
shader->BindTexture(str_renderedTex, inTex);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_renderedTex), inTex);
const SViewPort oldVp = g_Renderer.GetViewport();
const SViewPort vp = { 0, 0, inWidth / 2, inHeight / 2 };
@ -266,9 +267,11 @@ void CPostprocManager::ApplyBlurGauss(
deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = tech->GetShader();
shader->BindTexture(str_renderedTex, inTex);
shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
Renderer::Backend::IShaderProgram* shader = tech->GetShader();
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_renderedTex), inTex);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_texSize), inWidth, inHeight);
const SViewPort oldVp = g_Renderer.GetViewport();
const SViewPort vp = { 0, 0, inWidth, inHeight };
@ -324,8 +327,10 @@ void CPostprocManager::ApplyBlurGauss(
shader = tech->GetShader();
// Our input texture to the shader is the output of the horizontal pass.
shader->BindTexture(str_renderedTex, tempTex);
shader->Uniform(str_texSize, inWidth, inHeight, 0.0f, 0.0f);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_renderedTex), tempTex);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_texSize), inWidth, inHeight);
g_Renderer.SetViewport(vp);
@ -408,33 +413,35 @@ void CPostprocManager::ApplyEffect(
deviceCommandContext->SetGraphicsPipelineState(
shaderTech->GetGraphicsPipelineStateDesc(pass));
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = shaderTech->GetShader(pass);
Renderer::Backend::IShaderProgram* shader = shaderTech->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
// this only happens once per frame the overhead is negligible.
if (m_WhichBuffer)
shader->BindTexture(str_renderedTex, m_ColorTex1.get());
else
shader->BindTexture(str_renderedTex, m_ColorTex2.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_renderedTex),
m_WhichBuffer ? m_ColorTex1.get() : m_ColorTex2.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_depthTex), m_DepthTex.get());
shader->BindTexture(str_depthTex, m_DepthTex.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_blurTex2), m_BlurScales[0].steps[0].texture.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_blurTex4), m_BlurScales[1].steps[0].texture.get());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_blurTex8), m_BlurScales[2].steps[0].texture.get());
shader->BindTexture(str_blurTex2, m_BlurScales[0].steps[0].texture.get());
shader->BindTexture(str_blurTex4, m_BlurScales[1].steps[0].texture.get());
shader->BindTexture(str_blurTex8, m_BlurScales[2].steps[0].texture.get());
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_width), m_Width);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_height), m_Height);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_zNear), m_NearPlane);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_zFar), m_FarPlane);
shader->Uniform(str_width, m_Width);
shader->Uniform(str_height, m_Height);
shader->Uniform(str_zNear, m_NearPlane);
shader->Uniform(str_zFar, m_FarPlane);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_sharpness), m_Sharpness);
shader->Uniform(str_sharpness, m_Sharpness);
shader->Uniform(str_brightness, g_LightEnv.m_Brightness);
shader->Uniform(str_hdr, g_LightEnv.m_Contrast);
shader->Uniform(str_saturation, g_LightEnv.m_Saturation);
shader->Uniform(str_bloom, g_LightEnv.m_Bloom);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_brightness), g_LightEnv.m_Brightness);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_hdr), g_LightEnv.m_Contrast);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_saturation), g_LightEnv.m_Saturation);
deviceCommandContext->SetUniform(shader->GetBindingSlot(str_bloom), g_LightEnv.m_Bloom);
float quadVerts[] =
{

View File

@ -68,67 +68,96 @@ ShaderRenderModifier::ShaderRenderModifier()
{
}
void ShaderRenderModifier::BeginPass(Renderer::Backend::GL::CShaderProgram* shader)
void ShaderRenderModifier::BeginPass(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader)
{
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
shader->Uniform(str_cameraPos, g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetTranslation());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_cameraPos),
g_Renderer.GetSceneRenderer().GetViewCamera().GetOrientation().GetTranslation().AsFloatArray());
if (GetShadowMap())
GetShadowMap()->BindTo(shader);
GetShadowMap()->BindTo(deviceCommandContext, shader);
if (GetLightEnv())
{
shader->Uniform(str_ambient, GetLightEnv()->m_AmbientColor);
shader->Uniform(str_sunDir, GetLightEnv()->GetSunDir());
shader->Uniform(str_sunColor, GetLightEnv()->m_SunColor);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_ambient),
GetLightEnv()->m_AmbientColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_sunDir),
GetLightEnv()->GetSunDir().AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_sunColor),
GetLightEnv()->m_SunColor.AsFloatArray());
shader->Uniform(str_fogColor, GetLightEnv()->m_FogColor);
shader->Uniform(str_fogParams, GetLightEnv()->m_FogFactor, GetLightEnv()->m_FogMax, 0.f, 0.f);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogColor),
GetLightEnv()->m_FogColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogParams),
GetLightEnv()->m_FogFactor, GetLightEnv()->m_FogMax);
}
if (shader->GetTextureBinding(str_losTex).Active())
if (shader->GetBindingSlot(str_losTex) >= 0)
{
CLOSTexture& los = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture();
shader->BindTexture(str_losTex, los.GetTextureSmooth());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex), los.GetTextureSmooth());
// Don't bother sending the whole matrix, we just need two floats (scale and translation)
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
}
m_BindingInstancingTransform = shader->GetUniformBinding(str_instancingTransform);
m_BindingShadingColor = shader->GetUniformBinding(str_shadingColor);
m_BindingPlayerColor = shader->GetUniformBinding(str_playerColor);
m_BindingInstancingTransform = shader->GetBindingSlot(str_instancingTransform);
m_BindingShadingColor = shader->GetBindingSlot(str_shadingColor);
m_BindingPlayerColor = shader->GetBindingSlot(str_playerColor);
if (m_BindingShadingColor.Active())
if (m_BindingShadingColor >= 0)
{
m_ShadingColor = CColor(1.0f, 1.0f, 1.0f, 1.0f);
shader->Uniform(m_BindingShadingColor, m_ShadingColor);
deviceCommandContext->SetUniform(
m_BindingShadingColor, m_ShadingColor.AsFloatArray());
}
if (m_BindingPlayerColor.Active())
if (m_BindingPlayerColor >= 0)
{
m_PlayerColor = g_Game->GetPlayerColor(0);
shader->Uniform(m_BindingPlayerColor, m_PlayerColor);
deviceCommandContext->SetUniform(
m_BindingPlayerColor, m_PlayerColor.AsFloatArray());
}
}
void ShaderRenderModifier::PrepareModel(Renderer::Backend::GL::CShaderProgram* shader, CModel* model)
void ShaderRenderModifier::PrepareModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
CModel* model)
{
if (m_BindingInstancingTransform.Active())
shader->Uniform(m_BindingInstancingTransform, model->GetTransform());
if (m_BindingShadingColor.Active() && m_ShadingColor != model->GetShadingColor())
if (m_BindingInstancingTransform >= 0)
{
m_ShadingColor = model->GetShadingColor();
shader->Uniform(m_BindingShadingColor, m_ShadingColor);
deviceCommandContext->SetUniform(
m_BindingInstancingTransform, model->GetTransform().AsFloatArray());
}
if (m_BindingPlayerColor.Active())
if (m_BindingShadingColor >= 0 && m_ShadingColor != model->GetShadingColor())
{
m_ShadingColor = model->GetShadingColor();
deviceCommandContext->SetUniform(
m_BindingShadingColor, m_ShadingColor.AsFloatArray());
}
if (m_BindingPlayerColor >= 0)
{
const CColor& playerColor = g_Game->GetPlayerColor(model->GetPlayerID());
if (m_PlayerColor != playerColor)
{
m_PlayerColor = playerColor;
shader->Uniform(m_BindingPlayerColor, m_PlayerColor);
deviceCommandContext->SetUniform(
m_BindingPlayerColor, m_PlayerColor.AsFloatArray());
}
}
}

View File

@ -55,23 +55,21 @@ public:
* BeginPass: Setup OpenGL for the given rendering pass.
*
* Must be implemented by derived classes.
*
* @param pass The current pass number (pass == 0 is the first pass)
*
* @return The streamflags that indicate which vertex components
* are required by the fragment stages (see STREAM_XYZ constants).
*/
virtual void BeginPass(Renderer::Backend::GL::CShaderProgram* shader) = 0;
virtual void BeginPass(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) = 0;
/**
* PrepareModel: Called before rendering the given model.
*
* Default behaviour does nothing.
*
* @param pass The current pass number (pass == 0 is the first pass)
* @param model The model that is about to be rendered.
*/
virtual void PrepareModel(Renderer::Backend::GL::CShaderProgram* shader, CModel* model) = 0;
virtual void PrepareModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
CModel* model) = 0;
};
@ -122,13 +120,17 @@ public:
ShaderRenderModifier();
// Implementation
void BeginPass(Renderer::Backend::GL::CShaderProgram* shader);
void PrepareModel(Renderer::Backend::GL::CShaderProgram* shader, CModel* model);
void BeginPass(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) override;
void PrepareModel(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
CModel* model) override;
private:
Renderer::Backend::GL::CShaderProgram::Binding m_BindingInstancingTransform;
Renderer::Backend::GL::CShaderProgram::Binding m_BindingShadingColor;
Renderer::Backend::GL::CShaderProgram::Binding m_BindingPlayerColor;
int32_t m_BindingInstancingTransform = -1;
int32_t m_BindingShadingColor = -1;
int32_t m_BindingPlayerColor = -1;
CColor m_ShadingColor, m_PlayerColor;
};

View File

@ -925,16 +925,13 @@ void CSceneRenderer::RenderSubmissions(
if (g_RenderingOptions.GetDisplayShadowsFrustum())
m->shadow.RenderDebugBounds();
m->silhouetteRenderer.RenderDebugBounds(deviceCommandContext);
if (g_RenderingOptions.GetDisplayShadowsFrustum())
m->shadow.RenderDebugTexture(deviceCommandContext);
m->silhouetteRenderer.RenderDebugBounds(deviceCommandContext);
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext);
// render overlays that should appear on top of all other objects
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
ogl_WarnIfError();
}
void CSceneRenderer::EndFrame()

View File

@ -519,7 +519,7 @@ void ShadowMapInternals::CreateTexture()
{
case 16: formatName = "Format::D16"; backendFormat = Renderer::Backend::Format::D16; break;
case 24: formatName = "Format::D24"; backendFormat = Renderer::Backend::Format::D24; break;
case 32: formatName = "Format::D32"; backendFormat = Renderer::Backend::Format::D32; break;
case 32: formatName = "Format::D32"; backendFormat = Renderer::Backend::Format::D32; break;
default: formatName = "Format::D24"; backendFormat = Renderer::Backend::Format::D24; break;
}
#endif
@ -631,20 +631,29 @@ void ShadowMap::EndRender()
g_Renderer.SetViewport(vp);
}
void ShadowMap::BindTo(Renderer::Backend::GL::CShaderProgram* shader) const
void ShadowMap::BindTo(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) const
{
if (!shader->GetTextureBinding(str_shadowTex).Active() || !m->Texture)
const int32_t shadowTexBindingSlot = shader->GetBindingSlot(str_shadowTex);
if (shadowTexBindingSlot < 0 || !m->Texture)
return;
shader->BindTexture(str_shadowTex, m->Texture.get());
shader->Uniform(str_shadowScale, m->Width, m->Height, 1.0f / m->Width, 1.0f / m->Height);
deviceCommandContext->SetTexture(shadowTexBindingSlot, m->Texture.get());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_shadowScale), m->Width, m->Height, 1.0f / m->Width, 1.0f / m->Height);
const CVector3D cameraForward = g_Renderer.GetSceneRenderer().GetCullCamera().GetOrientation().GetIn();
shader->Uniform(str_cameraForward, cameraForward.X, cameraForward.Y, cameraForward.Z,
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_cameraForward), cameraForward.X, cameraForward.Y, cameraForward.Z,
cameraForward.Dot(g_Renderer.GetSceneRenderer().GetCullCamera().GetOrientation().GetTranslation()));
if (GetCascadeCount() == 1)
{
shader->Uniform(str_shadowTransform, m->Cascades[0].TextureMatrix);
shader->Uniform(str_shadowDistance, m->Cascades[0].Distance);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_shadowTransform),
m->Cascades[0].TextureMatrix.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_shadowDistance), m->Cascades[0].Distance);
}
else
{
@ -655,8 +664,14 @@ void ShadowMap::BindTo(Renderer::Backend::GL::CShaderProgram* shader) const
shadowDistances.emplace_back(cascade.Distance);
shadowTransforms.emplace_back(cascade.TextureMatrix);
}
shader->Uniform(str_shadowTransforms, GetCascadeCount(), shadowTransforms.data());
shader->Uniform(str_shadowDistances, GetCascadeCount(), shadowDistances.data());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_shadowTransform),
PS::span<const float>(
shadowTransforms[0]._data,
shadowTransforms[0].AsFloatArray().size() * GetCascadeCount()));
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_shadowDistance),
PS::span<const float>(shadowDistances.data(), shadowDistances.size()));
}
}
@ -711,64 +726,6 @@ void ShadowMap::RenderDebugBounds()
ogl_WarnIfError();
}
void ShadowMap::RenderDebugTexture(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext)
{
if (!m->Texture)
return;
#if !CONFIG2_GLES
deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, m->Texture->GetHandle());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
#endif
CShaderTechniquePtr texTech = g_Renderer.GetShaderManager().LoadEffect(str_canvas2d);
deviceCommandContext->SetGraphicsPipelineState(
texTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* texShader = texTech->GetShader();
texShader->Uniform(str_transform, GetDefaultGuiMatrix());
texShader->BindTexture(str_tex, m->Texture.get());
texShader->Uniform(str_colorAdd, CColor(0.0f, 0.0f, 0.0f, 1.0f));
texShader->Uniform(str_colorMul, CColor(1.0f, 1.0f, 1.0f, 0.0f));
texShader->Uniform(str_grayscaleFactor, 0.0f);
float s = 256.f;
float boxVerts[] =
{
0,0, 0,s, s,0,
s,0, 0,s, s,s
};
float boxUV[] =
{
0,0, 0,1, 1,0,
1,0, 0,1, 1,1
};
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 0);
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::UV0,
Renderer::Backend::Format::R32G32_SFLOAT, 0, 0, 1);
deviceCommandContext->SetVertexBufferData(0, boxVerts);
deviceCommandContext->SetVertexBufferData(1, boxUV);
deviceCommandContext->Draw(0, 6);
deviceCommandContext->EndPass();
#if !CONFIG2_GLES
deviceCommandContext->BindTexture(0, GL_TEXTURE_2D, m->Texture->GetHandle());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
#endif
ogl_WarnIfError();
}
int ShadowMap::GetCascadeCount() const
{
#if CONFIG2_GLES

View File

@ -19,7 +19,7 @@
#define INCLUDED_SHADOWMAP
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/IShaderProgram.h"
class CBoundingBoxAligned;
class CCamera;
@ -126,7 +126,9 @@ public:
/**
* Binds all needed resources and uniforms to draw shadows using the shader.
*/
void BindTo(Renderer::Backend::GL::CShaderProgram* shader) const;
void BindTo(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader) const;
/**
* Visualize shadow mapping calculations to help in
@ -134,12 +136,6 @@ public:
*/
void RenderDebugBounds();
/**
* Visualize shadow map texture to help in debugging.
*/
void RenderDebugTexture(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext);
private:
ShadowMapInternals* m;
};

View File

@ -477,13 +477,15 @@ void SilhouetteRenderer::RenderDebugOverlays(
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
Renderer::Backend::GL::CShaderProgram* shader = shaderTech->GetShader();
shader->Uniform(str_transform, proj);
Renderer::Backend::IShaderProgram* shader = shaderTech->GetShader();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), proj.AsFloatArray());
for (size_t i = 0; i < m_DebugRects.size(); ++i)
const int32_t colorBindingSlot = shader->GetBindingSlot(str_color);
for (const DebugRect& r : m_DebugRects)
{
const DebugRect& r = m_DebugRects[i];
shader->Uniform(str_color, r.color);
deviceCommandContext->SetUniform(
colorBindingSlot, r.color.AsFloatArray());
u16 verts[] =
{
r.x0, r.y0,

View File

@ -224,8 +224,9 @@ void SkyManager::RenderSky(
deviceCommandContext->SetGraphicsPipelineState(
skytech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = skytech->GetShader();
shader->BindTexture(str_baseTex, m_SkyTextureCube->GetBackendTexture());
Renderer::Backend::IShaderProgram* shader = skytech->GetShader();
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), m_SkyTextureCube->GetBackendTexture());
// Translate so the sky center is at the camera space origin.
CMatrix3D translate;
@ -241,9 +242,9 @@ void SkyManager::RenderSky(
CMatrix3D rotate;
rotate.SetYRotation(M_PI + g_Renderer.GetSceneRenderer().GetLightEnv().GetRotation());
shader->Uniform(
str_transform,
camera.GetViewProjection() * translate * rotate * scale);
const CMatrix3D transform = camera.GetViewProjection() * translate * rotate * scale;
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
m_VertexArray.PrepareForRendering();
m_VertexArray.UploadIfNeeded(deviceCommandContext);

View File

@ -210,10 +210,14 @@ void TerrainOverlay::RenderTile(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* overlayShader = overlayTech->GetShader();
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader();
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
overlayShader->Uniform(str_color, color);
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_color), color.AsFloatArray());
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,
@ -271,10 +275,14 @@ void TerrainOverlay::RenderTileOutline(
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* overlayShader = overlayTech->GetShader();
Renderer::Backend::IShaderProgram* overlayShader = overlayTech->GetShader();
overlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
overlayShader->Uniform(str_color, color);
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
overlayShader->GetBindingSlot(str_color), color.AsFloatArray());
deviceCommandContext->SetVertexAttributeFormat(
Renderer::Backend::VertexAttributeStream::POSITION,

View File

@ -174,12 +174,17 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
deviceCommandContext->SetGraphicsPipelineState(
debugOverlayTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* debugOverlayShader = debugOverlayTech->GetShader();
Renderer::Backend::IShaderProgram* debugOverlayShader = debugOverlayTech->GetShader();
debugOverlayShader->BindTexture(str_baseTex, texture);
debugOverlayShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
debugOverlayShader->Uniform(str_textureTransform, textureMatrix);
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, debugOverlayShader, true);
deviceCommandContext->SetTexture(
debugOverlayShader->GetBindingSlot(str_baseTex), texture);
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
debugOverlayShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
debugOverlayShader->GetBindingSlot(str_textureTransform), textureMatrix.AsFloatArray());
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, true);
// To make the overlay visible over water, render an additional map-sized
// water-height patch.
@ -221,28 +226,47 @@ void TerrainRenderer::RenderTerrainOverlayTexture(
/**
* Set up all the uniforms for a shader pass.
*/
void TerrainRenderer::PrepareShader(Renderer::Backend::GL::CShaderProgram* shader, ShadowMap* shadow)
void TerrainRenderer::PrepareShader(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader, ShadowMap* shadow)
{
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
shader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
shader->Uniform(str_cameraPos, sceneRenderer.GetViewCamera().GetOrientation().GetTranslation());
const CMatrix3D transform = sceneRenderer.GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_cameraPos),
sceneRenderer.GetViewCamera().GetOrientation().GetTranslation().AsFloatArray());
const CLightEnv& lightEnv = sceneRenderer.GetLightEnv();
if (shadow)
shadow->BindTo(shader);
shadow->BindTo(deviceCommandContext, shader);
CLOSTexture& los = sceneRenderer.GetScene().GetLOSTexture();
shader->BindTexture(str_losTex, los.GetTextureSmooth());
shader->Uniform(str_losTransform, los.GetTextureMatrix()[0], los.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_losTex), los.GetTextureSmooth());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_losTransform),
los.GetTextureMatrix()[0], los.GetTextureMatrix()[12]);
shader->Uniform(str_ambient, lightEnv.m_AmbientColor);
shader->Uniform(str_sunColor, lightEnv.m_SunColor);
shader->Uniform(str_sunDir, lightEnv.GetSunDir());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_ambient),
lightEnv.m_AmbientColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_sunColor),
lightEnv.m_SunColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_sunDir),
lightEnv.GetSunDir().AsFloatArray());
shader->Uniform(str_fogColor, lightEnv.m_FogColor);
shader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogColor),
lightEnv.m_FogColor.AsFloatArray());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_fogParams),
lightEnv.m_FogFactor, lightEnv.m_FogMax);
}
void TerrainRenderer::RenderTerrainShader(
@ -264,11 +288,15 @@ void TerrainRenderer::RenderTerrainShader(
deviceCommandContext->SetGraphicsPipelineState(solidPipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shaderSolid = techSolid->GetShader();
shaderSolid->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);
Renderer::Backend::IShaderProgram* shaderSolid = techSolid->GetShader();
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shaderSolid->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
shaderSolid->GetBindingSlot(str_color), 0.0f, 0.0f, 0.0f, 1.0f);
CPatchRData::RenderSides(deviceCommandContext, visiblePatches, shaderSolid);
CPatchRData::RenderSides(deviceCommandContext, visiblePatches);
deviceCommandContext->EndPass();
@ -278,14 +306,8 @@ void TerrainRenderer::RenderTerrainShader(
CPatchRData::RenderBlends(deviceCommandContext, visiblePatches, context, shadow);
CDecalRData::RenderDecals(deviceCommandContext, visibleDecals, context, shadow);
// restore OpenGL state
deviceCommandContext->BindTexture(3, GL_TEXTURE_2D, 0);
deviceCommandContext->BindTexture(2, GL_TEXTURE_2D, 0);
deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
}
///////////////////////////////////////////////////////////////////
// Render un-textured patches as polygons
void TerrainRenderer::RenderPatches(
@ -305,11 +327,16 @@ void TerrainRenderer::RenderPatches(
solidTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* solidShader = solidTech->GetShader();
solidShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
solidShader->Uniform(str_color, color);
Renderer::Backend::IShaderProgram* solidShader = solidTech->GetShader();
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, solidShader, false);
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
solidShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
solidShader->GetBindingSlot(str_color), color.AsFloatArray());
CPatchRData::RenderStreams(deviceCommandContext, visiblePatches, false);
deviceCommandContext->EndPass();
}
@ -405,7 +432,7 @@ bool TerrainRenderer::RenderFancyWater(
deviceCommandContext->SetGraphicsPipelineState(
m->fancyWaterTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* fancyWaterShader = m->fancyWaterTech->GetShader();
Renderer::Backend::IShaderProgram* fancyWaterShader = m->fancyWaterTech->GetShader();
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -413,87 +440,157 @@ bool TerrainRenderer::RenderFancyWater(
// TODO: move uploading to a prepare function during loading.
const CTexturePtr& currentNormalTexture = waterManager.m_NormalMap[waterManager.GetCurrentTextureIndex(period)];
const CTexturePtr& nextNormalTexture = waterManager.m_NormalMap[waterManager.GetNextTextureIndex(period)];
currentNormalTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
nextNormalTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
fancyWaterShader->BindTexture(str_normalMap, currentNormalTexture->GetBackendTexture());
fancyWaterShader->BindTexture(str_normalMap2, nextNormalTexture->GetBackendTexture());
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_normalMap),
currentNormalTexture->GetBackendTexture());
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_normalMap2),
nextNormalTexture->GetBackendTexture());
if (waterManager.m_WaterFancyEffects)
{
fancyWaterShader->BindTexture(str_waterEffectsTex, waterManager.m_FancyTexture.get());
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_waterEffectsTex),
waterManager.m_FancyTexture.get());
}
if (waterManager.m_WaterRefraction && waterManager.m_WaterRealDepth)
{
fancyWaterShader->BindTexture(str_depthTex, waterManager.m_RefrFboDepthTexture.get());
fancyWaterShader->Uniform(str_projInvTransform, waterManager.m_RefractionProjInvMatrix);
fancyWaterShader->Uniform(str_viewInvTransform, waterManager.m_RefractionViewInvMatrix);
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_depthTex),
waterManager.m_RefrFboDepthTexture.get());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_projInvTransform),
waterManager.m_RefractionProjInvMatrix.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_viewInvTransform),
waterManager.m_RefractionViewInvMatrix.AsFloatArray());
}
if (waterManager.m_WaterRefraction)
fancyWaterShader->BindTexture(str_refractionMap, waterManager.m_RefractionTexture.get());
{
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_refractionMap),
waterManager.m_RefractionTexture.get());
}
if (waterManager.m_WaterReflection)
fancyWaterShader->BindTexture(str_reflectionMap, waterManager.m_ReflectionTexture.get());
fancyWaterShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
{
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_reflectionMap),
waterManager.m_ReflectionTexture.get());
}
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_losTex), losTexture.GetTextureSmooth());
const CLightEnv& lightEnv = sceneRenderer.GetLightEnv();
fancyWaterShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
const CMatrix3D transform = sceneRenderer.GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_transform), transform.AsFloatArray());
fancyWaterShader->BindTexture(str_skyCube, sceneRenderer.GetSkyManager().GetSkyCube());
deviceCommandContext->SetTexture(
fancyWaterShader->GetBindingSlot(str_skyCube),
sceneRenderer.GetSkyManager().GetSkyCube());
// TODO: check that this rotates in the right direction.
CMatrix3D skyBoxRotation;
skyBoxRotation.SetIdentity();
skyBoxRotation.RotateY(M_PI + lightEnv.GetRotation());
fancyWaterShader->Uniform(str_skyBoxRot, skyBoxRotation);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_skyBoxRot),
skyBoxRotation.AsFloatArray());
if (waterManager.m_WaterRefraction)
fancyWaterShader->Uniform(str_refractionMatrix, waterManager.m_RefractionMatrix);
{
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_refractionMatrix),
waterManager.m_RefractionMatrix.AsFloatArray());
}
if (waterManager.m_WaterReflection)
fancyWaterShader->Uniform(str_reflectionMatrix, waterManager.m_ReflectionMatrix);
{
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_reflectionMatrix),
waterManager.m_ReflectionMatrix.AsFloatArray());
}
fancyWaterShader->Uniform(str_ambient, lightEnv.m_AmbientColor);
fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir());
fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor);
fancyWaterShader->Uniform(str_color, waterManager.m_WaterColor);
fancyWaterShader->Uniform(str_tint, waterManager.m_WaterTint);
fancyWaterShader->Uniform(str_waviness, waterManager.m_Waviness);
fancyWaterShader->Uniform(str_murkiness, waterManager.m_Murkiness);
fancyWaterShader->Uniform(str_windAngle, waterManager.m_WindAngle);
fancyWaterShader->Uniform(str_repeatScale, 1.0f / repeatPeriod);
fancyWaterShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_ambient), lightEnv.m_AmbientColor.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_sunDir), lightEnv.GetSunDir().AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_sunColor), lightEnv.m_SunColor.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_color), waterManager.m_WaterColor.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_tint), waterManager.m_WaterTint.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waviness), waterManager.m_Waviness);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_murkiness), waterManager.m_Murkiness);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_windAngle), waterManager.m_WindAngle);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_repeatScale), 1.0f / repeatPeriod);
fancyWaterShader->Uniform(str_cameraPos, camera.GetOrientation().GetTranslation());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_losTransform),
losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12]);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_cameraPos),
camera.GetOrientation().GetTranslation().AsFloatArray());
fancyWaterShader->Uniform(str_fogColor, lightEnv.m_FogColor);
fancyWaterShader->Uniform(str_fogParams, lightEnv.m_FogFactor, lightEnv.m_FogMax, 0.f, 0.f);
fancyWaterShader->Uniform(str_time, (float)time);
fancyWaterShader->Uniform(str_screenSize, (float)g_Renderer.GetWidth(), (float)g_Renderer.GetHeight(), 0.0f, 0.0f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_fogColor),
lightEnv.m_FogColor.AsFloatArray());
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_fogParams),
lightEnv.m_FogFactor, lightEnv.m_FogMax);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_time), static_cast<float>(time));
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_screenSize),
static_cast<float>(g_Renderer.GetWidth()),
static_cast<float>(g_Renderer.GetHeight()));
if (waterManager.m_WaterType == L"clap")
{
fancyWaterShader->Uniform(str_waveParams1, 30.0f,1.5f,20.0f,0.03f);
fancyWaterShader->Uniform(str_waveParams2, 0.5f,0.0f,0.0f,0.0f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams1),
30.0f, 1.5f, 20.0f, 0.03f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams2),
0.5f, 0.0f, 0.0f, 0.0f);
}
else if (waterManager.m_WaterType == L"lake")
{
fancyWaterShader->Uniform(str_waveParams1, 8.5f,1.5f,15.0f,0.03f);
fancyWaterShader->Uniform(str_waveParams2, 0.2f,0.0f,0.0f,0.07f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams1),
8.5f, 1.5f, 15.0f, 0.03f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams2),
0.2f, 0.0f, 0.0f, 0.07f);
}
else
{
fancyWaterShader->Uniform(str_waveParams1, 15.0f,0.8f,10.0f,0.1f);
fancyWaterShader->Uniform(str_waveParams2, 0.3f,0.0f,0.1f,0.3f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams1),
15.0f, 0.8f, 10.0f, 0.1f);
deviceCommandContext->SetUniform(
fancyWaterShader->GetBindingSlot(str_waveParams2),
0.3f, 0.0f, 0.1f, 0.3f);
}
if (shadow)
shadow->BindTo(fancyWaterShader);
shadow->BindTo(deviceCommandContext, fancyWaterShader);
for (CPatchRData* data : m->visiblePatches[cullGroup])
{
data->RenderWaterSurface(deviceCommandContext, fancyWaterShader, true);
data->RenderWaterSurface(deviceCommandContext, true);
if (waterManager.m_WaterFancyEffects)
data->RenderWaterShore(deviceCommandContext, fancyWaterShader);
data->RenderWaterShore(deviceCommandContext);
}
deviceCommandContext->EndPass();
@ -521,26 +618,36 @@ void TerrainRenderer::RenderSimpleWater(
deviceCommandContext->SetGraphicsPipelineState(
waterSimpleTech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* waterSimpleShader = waterSimpleTech->GetShader();
Renderer::Backend::IShaderProgram* waterSimpleShader = waterSimpleTech->GetShader();
const CTexturePtr& waterTexture = waterManager.m_WaterTexture[waterManager.GetCurrentTextureIndex(1.6)];
waterTexture->UploadBackendTextureIfNeeded(deviceCommandContext);
waterSimpleShader->BindTexture(str_baseTex, waterTexture->GetBackendTexture());
waterSimpleShader->BindTexture(str_losTex, losTexture.GetTextureSmooth());
waterSimpleShader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
waterSimpleShader->Uniform(str_losTransform, losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12], 0.f, 0.f);
waterSimpleShader->Uniform(str_time, static_cast<float>(time));
waterSimpleShader->Uniform(str_color, waterManager.m_WaterColor);
deviceCommandContext->SetTexture(
waterSimpleShader->GetBindingSlot(str_baseTex), waterTexture->GetBackendTexture());
deviceCommandContext->SetTexture(
waterSimpleShader->GetBindingSlot(str_losTex), losTexture.GetTextureSmooth());
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
waterSimpleShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
waterSimpleShader->GetBindingSlot(str_losTransform),
losTexture.GetTextureMatrix()[0], losTexture.GetTextureMatrix()[12]);
deviceCommandContext->SetUniform(
waterSimpleShader->GetBindingSlot(str_time), static_cast<float>(time));
deviceCommandContext->SetUniform(
waterSimpleShader->GetBindingSlot(str_color), waterManager.m_WaterColor.AsFloatArray());
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
for (size_t i = 0; i < visiblePatches.size(); ++i)
{
CPatchRData* data = visiblePatches[i];
data->RenderWaterSurface(deviceCommandContext, waterSimpleShader, false);
data->RenderWaterSurface(deviceCommandContext, false);
}
deviceCommandContext->BindTexture(1, GL_TEXTURE_2D, 0);
deviceCommandContext->EndPass();
}
@ -580,12 +687,18 @@ void TerrainRenderer::RenderWaterFoamOccluders(
pipelineStateDesc.rasterizationState.cullMode = Renderer::Backend::CullMode::NONE;
deviceCommandContext->SetGraphicsPipelineState(pipelineStateDesc);
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* dummyShader = dummyTech->GetShader();
dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
Renderer::Backend::IShaderProgram* dummyShader = dummyTech->GetShader();
const CMatrix3D transform = sceneRenderer.GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
dummyShader->GetBindingSlot(str_transform), transform.AsFloatArray());
deviceCommandContext->SetUniform(
dummyShader->GetBindingSlot(str_color), 0.0f, 0.0f, 0.0f, 0.0f);
for (CPatchRData* data : m->visiblePatches[cullGroup])
data->RenderWaterShore(deviceCommandContext, dummyShader);
data->RenderWaterShore(deviceCommandContext);
deviceCommandContext->EndPass();
deviceCommandContext->SetFramebuffer(

View File

@ -26,8 +26,8 @@
#include "graphics/Color.h"
#include "maths/BoundingBoxAligned.h"
#include "renderer/backend/gl/DeviceCommandContext.h"
#include "renderer/backend/gl/ShaderProgram.h"
#include "renderer/backend/gl/Texture.h"
#include "renderer/backend/IShaderProgram.h"
class CCamera;
class CCanvas2D;
@ -187,7 +187,9 @@ private:
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
int cullGroup);
static void PrepareShader(Renderer::Backend::GL::CShaderProgram* shader, ShadowMap* shadow);
static void PrepareShader(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IShaderProgram* shader, ShadowMap* shadow);
};
#endif // INCLUDED_TERRAINRENDERER

View File

@ -37,7 +37,7 @@
void CTexturedLineRData::Render(
Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const SOverlayTexturedLine& line, Renderer::Backend::GL::CShaderProgram* shader)
const SOverlayTexturedLine& line, Renderer::Backend::IShaderProgram* shader)
{
if (!m_VB || !m_VBIndices)
return; // might have failed to allocate
@ -50,9 +50,12 @@ void CTexturedLineRData::Render(
m_VB->m_Owner->UploadIfNeeded(deviceCommandContext);
m_VBIndices->m_Owner->UploadIfNeeded(deviceCommandContext);
shader->BindTexture(str_baseTex, line.m_TextureBase->GetBackendTexture());
shader->BindTexture(str_maskTex, line.m_TextureMask->GetBackendTexture());
shader->Uniform(str_objectColor, line.m_Color);
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), line.m_TextureBase->GetBackendTexture());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_maskTex), line.m_TextureMask->GetBackendTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_objectColor), line.m_Color.AsFloatArray());
const uint32_t stride = sizeof(CTexturedLineRData::SVertex);

View File

@ -53,7 +53,7 @@ public:
void Update(const SOverlayTexturedLine& line);
void Render(Renderer::Backend::GL::CDeviceCommandContext* deviceCommandContext,
const SOverlayTexturedLine& line, Renderer::Backend::GL::CShaderProgram* shader);
const SOverlayTexturedLine& line, Renderer::Backend::IShaderProgram* shader);
bool IsVisibleInFrustum(const CFrustum& frustum) const;

View File

@ -80,10 +80,10 @@ public:
* Try to allocate a vertex buffer of the given size and type.
*
* @param vertexSize size of each vertex in the buffer
* @param numVertices number of vertices in the buffer
* @param usage GL_STATIC_DRAW, GL_DYNAMIC_DRAW, GL_STREAM_DRAW
* @param target typically GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER
* @param backingStore if usage is STATIC, this is NULL; else for DYNAMIC/STREAM,
* @param numberOfVertices number of vertices in the buffer
* @param type buffer type
* @param dynamic will be buffer updated frequently or not
* @param backingStore if not dynamic, this is nullptr; else for dynamic,
* this must be a copy of the vertex data that remains valid for the
* lifetime of the VBChunk
* @return chunk, or empty handle if no free chunks available

View File

@ -802,15 +802,22 @@ void WaterManager::RenderWaves(
deviceCommandContext->SetGraphicsPipelineState(
tech->GetGraphicsPipelineStateDesc());
deviceCommandContext->BeginPass();
Renderer::Backend::GL::CShaderProgram* shader = tech->GetShader();
Renderer::Backend::IShaderProgram* shader = tech->GetShader();
m_WaveTex->UploadBackendTextureIfNeeded(deviceCommandContext);
m_FoamTex->UploadBackendTextureIfNeeded(deviceCommandContext);
shader->BindTexture(str_waveTex, m_WaveTex->GetBackendTexture());
shader->BindTexture(str_foamTex, m_FoamTex->GetBackendTexture());
shader->Uniform(str_time, (float)m_WaterTexTimer);
shader->Uniform(str_transform, g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_waveTex), m_WaveTex->GetBackendTexture());
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_foamTex), m_FoamTex->GetBackendTexture());
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_time), static_cast<float>(m_WaterTexTimer));
const CMatrix3D transform =
g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection();
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_transform), transform.AsFloatArray());
for (size_t a = 0; a < m_ShoreWaves.size(); ++a)
{
@ -850,19 +857,19 @@ void WaterManager::RenderWaves(
Renderer::Backend::Format::R32G32B32_SFLOAT,
firstVertexOffset + offsetof(SWavesVertex, m_RetreatPosition), stride, 0);
shader->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff);
shader->Uniform(str_width, (int)m_ShoreWaves[a]->m_Width);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_translation), m_ShoreWaves[a]->m_TimeDiff);
deviceCommandContext->SetUniform(
shader->GetBindingSlot(str_width), static_cast<float>(m_ShoreWaves[a]->m_Width));
deviceCommandContext->SetVertexBuffer(0, VBchunk->m_Owner->GetBuffer());
deviceCommandContext->SetIndexBuffer(m_ShoreWavesVBIndices->m_Owner->GetBuffer());
deviceCommandContext->DrawIndexed(m_ShoreWavesVBIndices->m_Index, (m_ShoreWaves[a]->m_Width - 1) * (7 * 6), 0);
const uint32_t indexCount = (m_ShoreWaves[a]->m_Width - 1) * (7 * 6);
deviceCommandContext->DrawIndexed(m_ShoreWavesVBIndices->m_Index, indexCount, 0);
shader->Uniform(str_translation, m_ShoreWaves[a]->m_TimeDiff + 6.0f);
// TODO: figure out why this doesn't work.
//g_Renderer.m_Stats.m_DrawCalls++;
//g_Renderer.m_Stats.m_WaterTris += m_ShoreWaves_VBIndices->m_Count / 3;
g_Renderer.GetStats().m_DrawCalls++;
g_Renderer.GetStats().m_WaterTris += indexCount / 3;
}
deviceCommandContext->EndPass();
deviceCommandContext->SetFramebuffer(

View File

@ -18,6 +18,9 @@
#ifndef INCLUDED_RENDERER_BACKEND_ISHADERPROGRAM
#define INCLUDED_RENDERER_BACKEND_ISHADERPROGRAM
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStrIntern.h"
namespace Renderer
{
@ -46,6 +49,10 @@ class IShaderProgram
{
public:
virtual ~IShaderProgram() {}
virtual int32_t GetBindingSlot(const CStrIntern name) const = 0;
virtual std::vector<VfsPath> GetFileDependencies() const = 0;
};
} // namespace Backend

View File

@ -821,7 +821,7 @@ std::unique_ptr<CBuffer> CDevice::CreateBuffer(
return CBuffer::Create(this, name, type, size, dynamic);
}
std::unique_ptr<CShaderProgram> CDevice::CreateShaderProgram(
std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(
const CStr& name, const CShaderDefines& defines)
{
return CShaderProgram::Create(this, name, defines);

View File

@ -100,7 +100,7 @@ public:
std::unique_ptr<CBuffer> CreateBuffer(
const char* name, const CBuffer::Type type, const uint32_t size, const bool dynamic);
std::unique_ptr<CShaderProgram> CreateShaderProgram(
std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines);
void Present();

View File

@ -106,6 +106,15 @@ GLenum BufferTypeToGLTarget(const CBuffer::Type type)
return target;
}
#if !CONFIG2_GLES
bool IsDepthTexture(const Format format)
{
return
format == Format::D16 || format == Format::D24 ||
format == Format::D32 || format == Format::D24_S8;
}
#endif // !CONFIG2_GLES
void UploadBufferRegionImpl(
const GLenum target, const uint32_t dataOffset, const uint32_t dataSize,
const CDeviceCommandContext::UploadBufferFunction& uploadFunction)
@ -148,10 +157,10 @@ CDeviceCommandContext::CDeviceCommandContext(CDevice* device)
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
for (std::pair<GLenum, GLuint>& unit : m_BoundTextures)
for (BindUnit& unit : m_BoundTextures)
{
unit.first = GL_TEXTURE_2D;
unit.second = 0;
unit.target = GL_TEXTURE_2D;
unit.handle = 0;
}
for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index)
{
@ -372,7 +381,8 @@ void CDeviceCommandContext::EndScopedLabel()
glPopDebugGroup();
}
void CDeviceCommandContext::BindTexture(const uint32_t unit, const GLenum target, const GLuint handle)
void CDeviceCommandContext::BindTexture(
const uint32_t unit, const GLenum target, const GLuint handle)
{
ENSURE(unit < m_BoundTextures.size());
#if CONFIG2_GLES
@ -380,16 +390,16 @@ void CDeviceCommandContext::BindTexture(const uint32_t unit, const GLenum target
#else
ENSURE(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP || target == GL_TEXTURE_2D_MULTISAMPLE);
#endif
if (m_BoundTextures[unit].first == target && m_BoundTextures[unit].second == handle)
return;
if (m_ActiveTextureUnit != unit)
{
glActiveTexture(GL_TEXTURE0 + unit);
m_ActiveTextureUnit = unit;
}
if (m_BoundTextures[unit].first != target && m_BoundTextures[unit].first && m_BoundTextures[unit].second)
glBindTexture(m_BoundTextures[unit].first, 0);
if (m_BoundTextures[unit].second != handle)
if (m_BoundTextures[unit].target == target && m_BoundTextures[unit].handle == handle)
return;
if (m_BoundTextures[unit].target != target && m_BoundTextures[unit].target && m_BoundTextures[unit].handle)
glBindTexture(m_BoundTextures[unit].target, 0);
if (m_BoundTextures[unit].handle != handle)
glBindTexture(target, handle);
m_BoundTextures[unit] = {target, handle};
}
@ -421,22 +431,28 @@ void CDeviceCommandContext::OnTextureDestroy(CTexture* texture)
{
ENSURE(texture);
for (size_t index = 0; index < m_BoundTextures.size(); ++index)
if (m_BoundTextures[index].second == texture->GetHandle())
if (m_BoundTextures[index].handle == texture->GetHandle())
BindTexture(index, GL_TEXTURE_2D, 0);
}
void CDeviceCommandContext::Flush()
{
ENSURE(m_ScopedLabelDepth == 0);
GPU_SCOPED_LABEL(this, "CDeviceCommandContext::Flush");
ResetStates();
m_IndexBuffer = nullptr;
m_IndexBufferData = nullptr;
BindTexture(0, GL_TEXTURE_2D, 0);
for (size_t unit = 0; unit < m_BoundTextures.size(); ++unit)
{
if (m_BoundTextures[unit].handle)
BindTexture(unit, GL_TEXTURE_2D, 0);
}
BindBuffer(CBuffer::Type::INDEX, nullptr);
BindBuffer(CBuffer::Type::VERTEX, nullptr);
ENSURE(m_ScopedLabelDepth == 0);
}
void CDeviceCommandContext::ResetStates()
@ -476,6 +492,8 @@ void CDeviceCommandContext::SetGraphicsPipelineStateImpl(
nextShaderProgram->Bind(currentShaderProgram);
else if (currentShaderProgram)
currentShaderProgram->Unbind();
m_ShaderProgram = nextShaderProgram;
}
const DepthStencilStateDesc& currentDepthStencilStateDesc = m_GraphicsPipelineStateDesc.depthStencilState;
@ -822,17 +840,15 @@ void CDeviceCommandContext::SetVertexBuffer(
{
ENSURE(buffer);
ENSURE(buffer->GetType() == CBuffer::Type::VERTEX);
ENSURE(m_GraphicsPipelineStateDesc.shaderProgram);
ENSURE(m_ShaderProgram);
BindBuffer(buffer->GetType(), buffer);
CShaderProgram* shaderProgram =
static_cast<CShaderProgram*>(m_GraphicsPipelineStateDesc.shaderProgram);
for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index)
{
if (!m_VertexAttributeFormat[index].active || m_VertexAttributeFormat[index].bindingSlot != bindingSlot)
continue;
ENSURE(m_VertexAttributeFormat[index].initialized);
const VertexAttributeStream stream = static_cast<VertexAttributeStream>(index);
shaderProgram->VertexAttribPointer(stream,
m_ShaderProgram->VertexAttribPointer(stream,
m_VertexAttributeFormat[index].format,
m_VertexAttributeFormat[index].offset,
m_VertexAttributeFormat[index].stride,
@ -844,17 +860,15 @@ void CDeviceCommandContext::SetVertexBufferData(
const uint32_t bindingSlot, const void* data)
{
ENSURE(data);
ENSURE(m_GraphicsPipelineStateDesc.shaderProgram);
ENSURE(m_ShaderProgram);
BindBuffer(CBuffer::Type::VERTEX, nullptr);
CShaderProgram* shaderProgram =
static_cast<CShaderProgram*>(m_GraphicsPipelineStateDesc.shaderProgram);
for (size_t index = 0; index < m_VertexAttributeFormat.size(); ++index)
{
if (!m_VertexAttributeFormat[index].active || m_VertexAttributeFormat[index].bindingSlot != bindingSlot)
continue;
ENSURE(m_VertexAttributeFormat[index].initialized);
const VertexAttributeStream stream = static_cast<VertexAttributeStream>(index);
shaderProgram->VertexAttribPointer(stream,
m_ShaderProgram->VertexAttribPointer(stream,
m_VertexAttributeFormat[index].format,
m_VertexAttributeFormat[index].offset,
m_VertexAttributeFormat[index].stride,
@ -895,14 +909,13 @@ void CDeviceCommandContext::EndPass()
void CDeviceCommandContext::Draw(
const uint32_t firstVertex, const uint32_t vertexCount)
{
ENSURE(m_GraphicsPipelineStateDesc.shaderProgram);
ENSURE(m_ShaderProgram);
ENSURE(m_InsidePass);
// Some drivers apparently don't like count = 0 in glDrawArrays here, so skip
// all drawing in that case.
if (vertexCount == 0)
return;
static_cast<CShaderProgram*>(m_GraphicsPipelineStateDesc.shaderProgram)
->AssertPointersBound();
m_ShaderProgram->AssertPointersBound();
glDrawArrays(GL_TRIANGLES, firstVertex, vertexCount);
ogl_WarnIfError();
}
@ -910,7 +923,7 @@ void CDeviceCommandContext::Draw(
void CDeviceCommandContext::DrawIndexed(
const uint32_t firstIndex, const uint32_t indexCount, const int32_t vertexOffset)
{
ENSURE(m_GraphicsPipelineStateDesc.shaderProgram);
ENSURE(m_ShaderProgram);
ENSURE(m_InsidePass);
if (indexCount == 0)
return;
@ -920,8 +933,7 @@ void CDeviceCommandContext::DrawIndexed(
{
ENSURE(sizeof(uint16_t) * (firstIndex + indexCount) <= m_IndexBuffer->GetSize());
}
static_cast<CShaderProgram*>(m_GraphicsPipelineStateDesc.shaderProgram)
->AssertPointersBound();
m_ShaderProgram->AssertPointersBound();
// Don't use glMultiDrawElements here since it doesn't have a significant
// performance impact and it suffers from various driver bugs (e.g. it breaks
// in Mesa 7.10 swrast with index VBOs).
@ -934,15 +946,14 @@ void CDeviceCommandContext::DrawIndexedInRange(
const uint32_t firstIndex, const uint32_t indexCount,
const uint32_t start, const uint32_t end)
{
ENSURE(m_GraphicsPipelineStateDesc.shaderProgram);
ENSURE(m_ShaderProgram);
ENSURE(m_InsidePass);
if (indexCount == 0)
return;
ENSURE(m_IndexBuffer || m_IndexBufferData);
const void* indices =
static_cast<const void*>((static_cast<const uint8_t*>(m_IndexBufferData) + sizeof(uint16_t) * firstIndex));
static_cast<CShaderProgram*>(m_GraphicsPipelineStateDesc.shaderProgram)
->AssertPointersBound();
m_ShaderProgram->AssertPointersBound();
// Draw with DrawRangeElements where available, since it might be more
// efficient for slow hardware.
#if CONFIG2_GLES
@ -955,20 +966,102 @@ void CDeviceCommandContext::DrawIndexedInRange(
ogl_WarnIfError();
}
void CDeviceCommandContext::SetTexture(const int32_t bindingSlot, CTexture* texture)
{
ENSURE(m_ShaderProgram);
ENSURE(texture);
const CShaderProgram::TextureUnit textureUnit =
m_ShaderProgram->GetTextureUnit(bindingSlot);
if (!textureUnit.type)
return;
if (textureUnit.type != GL_SAMPLER_2D &&
#if !CONFIG2_GLES
textureUnit.type != GL_SAMPLER_2D_SHADOW &&
#endif
textureUnit.type != GL_SAMPLER_CUBE)
{
LOGERROR("CDeviceCommandContext::SetTexture: expected sampler at binding slot");
return;
}
#if !CONFIG2_GLES
if (textureUnit.type == GL_SAMPLER_2D_SHADOW)
{
if (!IsDepthTexture(texture->GetFormat()))
{
LOGERROR("CDeviceCommandContext::SetTexture: Invalid texture type (expected depth texture)");
return;
}
}
#endif
ENSURE(textureUnit.unit >= 0);
const uint32_t unit = textureUnit.unit;
if (unit >= m_BoundTextures.size())
{
LOGERROR("CDeviceCommandContext::SetTexture: Invalid texture unit (too big)");
return;
}
BindTexture(unit, textureUnit.target, texture->GetHandle());
}
void CDeviceCommandContext::SetUniform(
const int32_t bindingSlot,
const float value)
{
ENSURE(m_ShaderProgram);
m_ShaderProgram->SetUniform(bindingSlot, value);
}
void CDeviceCommandContext::SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY)
{
ENSURE(m_ShaderProgram);
m_ShaderProgram->SetUniform(bindingSlot, valueX, valueY);
}
void CDeviceCommandContext::SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ)
{
ENSURE(m_ShaderProgram);
m_ShaderProgram->SetUniform(bindingSlot, valueX, valueY, valueZ);
}
void CDeviceCommandContext::SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ, const float valueW)
{
ENSURE(m_ShaderProgram);
m_ShaderProgram->SetUniform(bindingSlot, valueX, valueY, valueZ, valueW);
}
void CDeviceCommandContext::SetUniform(
const int32_t bindingSlot, PS::span<const float> values)
{
ENSURE(m_ShaderProgram);
m_ShaderProgram->SetUniform(bindingSlot, values);
}
CDeviceCommandContext::ScopedBind::ScopedBind(
CDeviceCommandContext* deviceCommandContext,
const GLenum target, const GLuint handle)
: m_DeviceCommandContext(deviceCommandContext),
m_OldBindUnit(deviceCommandContext->m_BoundTextures[deviceCommandContext->m_ActiveTextureUnit])
m_OldBindUnit(deviceCommandContext->m_BoundTextures[deviceCommandContext->m_ActiveTextureUnit]),
m_ActiveTextureUnit(deviceCommandContext->m_ActiveTextureUnit)
{
m_DeviceCommandContext->BindTexture(
m_DeviceCommandContext->m_ActiveTextureUnit, target, handle);
const uint32_t unit = m_DeviceCommandContext->m_BoundTextures.size() - 1;
m_DeviceCommandContext->BindTexture(unit, target, handle);
}
CDeviceCommandContext::ScopedBind::~ScopedBind()
{
m_DeviceCommandContext->BindTexture(
m_DeviceCommandContext->m_ActiveTextureUnit, m_OldBindUnit.first, m_OldBindUnit.second);
m_ActiveTextureUnit, m_OldBindUnit.target, m_OldBindUnit.handle);
}
CDeviceCommandContext::ScopedBufferBind::ScopedBufferBind(

View File

@ -19,6 +19,7 @@
#define INCLUDED_RENDERER_GL_DEVICECOMMANDCONTEXT
#include "lib/ogl.h"
#include "ps/containers/Span.h"
#include "renderer/backend/Format.h"
#include "renderer/backend/gl/Buffer.h"
#include "renderer/backend/PipelineState.h"
@ -41,6 +42,7 @@ namespace GL
class CDevice;
class CFramebuffer;
class CShaderProgram;
class CTexture;
class CDeviceCommandContext
@ -111,12 +113,28 @@ public:
const uint32_t firstIndex, const uint32_t indexCount,
const uint32_t start, const uint32_t end);
void SetTexture(const int32_t bindingSlot, CTexture* texture);
void SetUniform(
const int32_t bindingSlot,
const float value);
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY);
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ);
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ, const float valueW);
void SetUniform(
const int32_t bindingSlot, PS::span<const float> values);
void BeginScopedLabel(const char* name);
void EndScopedLabel();
// TODO: remove direct binding after moving shaders.
void BindTexture(const uint32_t unit, const GLenum target, const GLuint handle);
// We need to know when to invalidate our texture bind cache.
void OnTextureDestroy(CTexture* texture);
@ -124,6 +142,7 @@ public:
private:
friend class CDevice;
friend class CTexture;
static std::unique_ptr<CDeviceCommandContext> Create(CDevice* device);
@ -134,12 +153,14 @@ private:
void SetGraphicsPipelineStateImpl(
const GraphicsPipelineStateDesc& pipelineStateDesc, const bool force);
void BindTexture(const uint32_t unit, const GLenum target, const GLuint handle);
void BindBuffer(const CBuffer::Type type, CBuffer* buffer);
CDevice* m_Device = nullptr;
GraphicsPipelineStateDesc m_GraphicsPipelineStateDesc{};
CFramebuffer* m_Framebuffer = nullptr;
CShaderProgram* m_ShaderProgram = nullptr;
uint32_t m_ScissorCount = 0;
// GL2.1 doesn't support more than 1 scissor.
std::array<Rect, 1> m_Scissors;
@ -153,7 +174,11 @@ private:
bool m_InsidePass = false;
uint32_t m_ActiveTextureUnit = 0;
using BindUnit = std::pair<GLenum, GLuint>;
struct BindUnit
{
GLenum target;
GLuint handle;
};
std::array<BindUnit, 16> m_BoundTextures;
class ScopedBind
{
@ -165,6 +190,7 @@ private:
private:
CDeviceCommandContext* m_DeviceCommandContext = nullptr;
BindUnit m_OldBindUnit;
uint32_t m_ActiveTextureUnit = 0;
};
using BoundBuffer = std::pair<GLenum, GLuint>;

View File

@ -23,8 +23,6 @@
#include "graphics/PreprocessorWrapper.h"
#include "graphics/ShaderManager.h"
#include "graphics/TextureManager.h"
#include "maths/Matrix3D.h"
#include "maths/Vector3D.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Profile.h"
@ -40,6 +38,8 @@
#endif
#include <algorithm>
#include <map>
#include <unordered_map>
namespace Renderer
{
@ -53,6 +53,22 @@ namespace GL
namespace
{
struct Binding
{
Binding(int a, int b) : first(a), second(b) { }
Binding() : first(-1), second(-1) { }
/**
* Returns whether this uniform attribute is active in the shader.
* If not then there's no point calling Uniform() to set its value.
*/
bool Active() const { return first != -1 || second != -1; }
int first;
int second;
};
int GetStreamMask(const VertexAttributeStream stream)
{
return 1 << static_cast<int>(stream);
@ -201,6 +217,51 @@ bool PreprocessShaderFile(
return true;
}
#if !CONFIG2_GLES
std::tuple<GLenum, GLenum, GLint> GetElementTypeAndCountFromString(const CStr& str)
{
#define CASE(MATCH_STRING, TYPE, ELEMENT_TYPE, ELEMENT_COUNT) \
if (str == MATCH_STRING) return {GL_ ## TYPE, GL_ ## ELEMENT_TYPE, ELEMENT_COUNT}
CASE("float", FLOAT, FLOAT, 1);
CASE("vec2", FLOAT_VEC2, FLOAT, 2);
CASE("vec3", FLOAT_VEC3, FLOAT, 3);
CASE("vec4", FLOAT_VEC4, FLOAT, 4);
CASE("mat2", FLOAT_MAT2, FLOAT, 4);
CASE("mat3", FLOAT_MAT3, FLOAT, 9);
CASE("mat4", FLOAT_MAT4, FLOAT, 16);
#if !CONFIG2_GLES // GL ES 2.0 doesn't support non-square matrices.
CASE("mat2x3", FLOAT_MAT2x3, FLOAT, 6);
CASE("mat2x4", FLOAT_MAT2x4, FLOAT, 8);
CASE("mat3x2", FLOAT_MAT3x2, FLOAT, 6);
CASE("mat3x4", FLOAT_MAT3x4, FLOAT, 12);
CASE("mat4x2", FLOAT_MAT4x2, FLOAT, 8);
CASE("mat4x3", FLOAT_MAT4x3, FLOAT, 12);
#endif
// A somewhat incomplete listing, missing "shadow" and "rect" versions
// which are interpreted as 2D (NB: our shadowmaps may change
// type based on user config).
#if CONFIG2_GLES
if (str == "sampler1D") debug_warn(L"sampler1D not implemented on GLES");
#else
CASE("sampler1D", SAMPLER_1D, TEXTURE_1D, 1);
#endif
CASE("sampler2D", SAMPLER_2D, TEXTURE_2D, 1);
#if CONFIG2_GLES
if (str == "sampler2DShadow") debug_warn(L"sampler2DShadow not implemented on GLES");
if (str == "sampler3D") debug_warn(L"sampler3D not implemented on GLES");
#else
CASE("sampler2DShadow", SAMPLER_2D_SHADOW, TEXTURE_2D, 1);
CASE("sampler3D", SAMPLER_3D, TEXTURE_3D, 1);
#endif
CASE("samplerCube", SAMPLER_CUBE, TEXTURE_CUBE_MAP, 1);
#undef CASE
return {0, 0, 0};
}
#endif // !CONFIG2_GLES
} // anonymous namespace
#if !CONFIG2_GLES
@ -212,11 +273,10 @@ public:
CDevice* device,
const VfsPath& vertexFilePath, const VfsPath& fragmentFilePath,
const CShaderDefines& defines,
const std::map<CStrIntern, int>& vertexIndexes, const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes,
int streamflags) :
CShaderProgram(streamflags),
m_Device(device),
m_VertexIndexes(vertexIndexes), m_FragmentIndexes(fragmentIndexes)
const std::map<CStrIntern, std::pair<CStr, int>>& vertexIndices,
const std::map<CStrIntern, std::pair<CStr, int>>& fragmentIndices,
int streamflags)
: CShaderProgram(streamflags), m_Device(device)
{
glGenProgramsARB(1, &m_VertexProgram);
glGenProgramsARB(1, &m_FragmentProgram);
@ -241,6 +301,30 @@ public:
if (!Compile(GL_FRAGMENT_PROGRAM_ARB, "fragment", m_FragmentProgram, fragmentFilePath, fragmentCode))
return;
for (const auto& index : vertexIndices)
{
BindingSlot& bindingSlot = GetOrCreateBindingSlot(index.first);
bindingSlot.vertexProgramLocation = index.second.second;
const auto [type, elementType, elementCount] = GetElementTypeAndCountFromString(index.second.first);
bindingSlot.type = type;
bindingSlot.elementType = elementType;
bindingSlot.elementCount = elementCount;
}
for (const auto& index : fragmentIndices)
{
BindingSlot& bindingSlot = GetOrCreateBindingSlot(index.first);
bindingSlot.fragmentProgramLocation = index.second.second;
const auto [type, elementType, elementCount] = GetElementTypeAndCountFromString(index.second.first);
if (bindingSlot.type && type != bindingSlot.type)
{
LOGERROR("CShaderProgramARB: vertex and fragment program uniforms with the same name should have the same type.");
}
bindingSlot.type = type;
bindingSlot.elementType = elementType;
bindingSlot.elementCount = elementCount;
}
}
~CShaderProgramARB() override
@ -302,98 +386,114 @@ public:
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
UnbindClientStates();
// TODO: should unbind textures, probably
}
int GetUniformVertexIndex(CStrIntern id)
int32_t GetBindingSlot(const CStrIntern name) const override
{
std::map<CStrIntern, int>::iterator it = m_VertexIndexes.find(id);
if (it == m_VertexIndexes.end())
return -1;
return it->second;
auto it = m_BindingSlotsMapping.find(name);
return it == m_BindingSlotsMapping.end() ? -1 : it->second;
}
frag_index_pair_t GetUniformFragmentIndex(CStrIntern id)
TextureUnit GetTextureUnit(const int32_t bindingSlot) override
{
std::map<CStrIntern, frag_index_pair_t>::iterator it = m_FragmentIndexes.find(id);
if (it == m_FragmentIndexes.end())
return std::make_pair(-1, 0);
return it->second;
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return { 0, 0, 0 };
TextureUnit textureUnit;
textureUnit.type = m_BindingSlots[bindingSlot].type;
textureUnit.target = m_BindingSlots[bindingSlot].elementType;
textureUnit.unit = m_BindingSlots[bindingSlot].fragmentProgramLocation;
return textureUnit;
}
Binding GetTextureBinding(texture_id_t id) override
void SetUniform(
const int32_t bindingSlot,
const float value) override
{
frag_index_pair_t fPair = GetUniformFragmentIndex(id);
int index = fPair.first;
if (index == -1)
return Binding();
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT)
{
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform type (expected float)");
return;
}
SetUniform(m_BindingSlots[bindingSlot], value, 0.0f, 0.0f, 0.0f);
}
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC2)
{
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform type (expected vec2)");
return;
}
SetUniform(m_BindingSlots[bindingSlot], valueX, valueY, 0.0f, 0.0f);
}
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY, const float valueZ) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC3)
{
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform type (expected vec3)");
return;
}
SetUniform(m_BindingSlots[bindingSlot], valueX, valueY, valueZ, 0.0f);
}
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ, const float valueW) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC4)
{
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform type (expected vec4)");
return;
}
SetUniform(m_BindingSlots[bindingSlot], valueX, valueY, valueZ, valueW);
}
void SetUniform(
const int32_t bindingSlot, PS::span<const float> values) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].elementType != GL_FLOAT)
{
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform element type (expected float)");
return;
}
if (m_BindingSlots[bindingSlot].elementCount > static_cast<GLint>(values.size()))
{
LOGERROR(
"CShaderProgramARB::SetUniform(): Invalid uniform element count (expected: %zu passed: %zu)",
m_BindingSlots[bindingSlot].elementCount, values.size());
return;
}
const GLenum type = m_BindingSlots[bindingSlot].type;
if (type == GL_FLOAT)
SetUniform(m_BindingSlots[bindingSlot], values[0], 0.0f, 0.0f, 0.0f);
else if (type == GL_FLOAT_VEC2)
SetUniform(m_BindingSlots[bindingSlot], values[0], values[1], 0.0f, 0.0f);
else if (type == GL_FLOAT_VEC3)
SetUniform(m_BindingSlots[bindingSlot], values[0], values[1], values[2], 0.0f);
else if (type == GL_FLOAT_VEC4)
SetUniform(m_BindingSlots[bindingSlot], values[0], values[1], values[2], values[3]);
else if (type == GL_FLOAT_MAT4)
SetUniformMatrix(m_BindingSlots[bindingSlot], values);
else
return Binding((int)fPair.second, index);
}
void BindTexture(texture_id_t id, GLuint tex) override
{
frag_index_pair_t fPair = GetUniformFragmentIndex(id);
int index = fPair.first;
if (index != -1)
{
m_Device->GetActiveCommandContext()->BindTexture(index, fPair.second, tex);
}
}
void BindTexture(Binding id, GLuint tex) override
{
int index = id.second;
if (index != -1)
{
m_Device->GetActiveCommandContext()->BindTexture(index, id.first, tex);
}
}
Binding GetUniformBinding(uniform_id_t id) override
{
return Binding(GetUniformVertexIndex(id), GetUniformFragmentIndex(id).first);
}
void Uniform(Binding id, float v0, float v1, float v2, float v3) override
{
if (id.first != -1)
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first, v0, v1, v2, v3);
if (id.second != -1)
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second, v0, v1, v2, v3);
}
void Uniform(Binding id, const CMatrix3D& v) override
{
if (id.first != -1)
{
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+0, v._11, v._12, v._13, v._14);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+1, v._21, v._22, v._23, v._24);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+2, v._31, v._32, v._33, v._34);
glProgramLocalParameter4fARB(GL_VERTEX_PROGRAM_ARB, (GLuint)id.first+3, v._41, v._42, v._43, v._44);
}
if (id.second != -1)
{
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+0, v._11, v._12, v._13, v._14);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+1, v._21, v._22, v._23, v._24);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+2, v._31, v._32, v._33, v._34);
glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, (GLuint)id.second+3, v._41, v._42, v._43, v._44);
}
}
void Uniform(Binding id, size_t count, const CMatrix3D* v) override
{
ENSURE(count == 1);
Uniform(id, v[0]);
}
void Uniform(Binding id, size_t count, const float* v) override
{
ENSURE(count == 4);
Uniform(id, v[0], v[1], v[2], v[3]);
LOGERROR("CShaderProgramARB::SetUniform(): Invalid uniform type (expected float, vec2, vec3, vec4, mat4)");
ogl_WarnIfError();
}
std::vector<VfsPath> GetFileDependencies() const override
@ -402,6 +502,79 @@ public:
}
private:
struct BindingSlot
{
CStrIntern name;
int vertexProgramLocation;
int fragmentProgramLocation;
GLenum type;
GLenum elementType;
GLint elementCount;
};
BindingSlot& GetOrCreateBindingSlot(const CStrIntern name)
{
auto it = m_BindingSlotsMapping.find(name);
if (it == m_BindingSlotsMapping.end())
{
m_BindingSlotsMapping[name] = m_BindingSlots.size();
BindingSlot bindingSlot{};
bindingSlot.name = name;
bindingSlot.vertexProgramLocation = -1;
bindingSlot.fragmentProgramLocation = -1;
bindingSlot.elementType = 0;
bindingSlot.elementCount = 0;
m_BindingSlots.emplace_back(std::move(bindingSlot));
return m_BindingSlots.back();
}
else
return m_BindingSlots[it->second];
}
void SetUniform(
const BindingSlot& bindingSlot,
const float v0, const float v1, const float v2, const float v3)
{
SetUniform(GL_VERTEX_PROGRAM_ARB, bindingSlot.vertexProgramLocation, v0, v1, v2, v3);
SetUniform(GL_FRAGMENT_PROGRAM_ARB, bindingSlot.fragmentProgramLocation, v0, v1, v2, v3);
}
void SetUniform(
const GLenum target, const int location,
const float v0, const float v1, const float v2, const float v3)
{
if (location >= 0)
{
glProgramLocalParameter4fARB(
target, static_cast<GLuint>(location), v0, v1, v2, v3);
}
}
void SetUniformMatrix(
const BindingSlot& bindingSlot, PS::span<const float> values)
{
const size_t mat4ElementCount = 16;
ENSURE(values.size() == mat4ElementCount);
SetUniformMatrix(GL_VERTEX_PROGRAM_ARB, bindingSlot.vertexProgramLocation, values);
SetUniformMatrix(GL_FRAGMENT_PROGRAM_ARB, bindingSlot.fragmentProgramLocation, values);
}
void SetUniformMatrix(
const GLenum target, const int location, PS::span<const float> values)
{
if (location >= 0)
{
glProgramLocalParameter4fARB(
target, static_cast<GLuint>(location + 0), values[0], values[4], values[8], values[12]);
glProgramLocalParameter4fARB(
target, static_cast<GLuint>(location + 1), values[1], values[5], values[9], values[13]);
glProgramLocalParameter4fARB(
target, static_cast<GLuint>(location + 2), values[2], values[6], values[10], values[14]);
glProgramLocalParameter4fARB(
target, static_cast<GLuint>(location + 3), values[3], values[7], values[11], values[15]);
}
}
CDevice* m_Device = nullptr;
std::vector<VfsPath> m_FileDependencies;
@ -409,10 +582,8 @@ private:
GLuint m_VertexProgram;
GLuint m_FragmentProgram;
std::map<CStrIntern, int> m_VertexIndexes;
// pair contains <index, gltype>
std::map<CStrIntern, frag_index_pair_t> m_FragmentIndexes;
std::vector<BindingSlot> m_BindingSlots;
std::unordered_map<CStrIntern, int32_t> m_BindingSlotsMapping;
};
#endif // !CONFIG2_GLES
@ -596,13 +767,24 @@ public:
if (!ok)
return false;
m_Uniforms.clear();
m_Samplers.clear();
Bind(nullptr);
ogl_WarnIfError();
// Reorder sampler units to decrease redundant texture unit changes when
// samplers bound in a different order.
const std::unordered_map<CStrIntern, int> requiredUnits =
{
{CStrIntern("baseTex"), 0},
{CStrIntern("normTex"), 1},
{CStrIntern("specTex"), 2},
{CStrIntern("aoTex"), 3},
{CStrIntern("shadowTex"), 4},
{CStrIntern("losTex"), 5},
};
std::vector<uint8_t> occupiedUnits;
GLint numUniforms = 0;
glGetProgramiv(m_Program, GL_ACTIVE_UNIFORMS, &numUniforms);
ogl_WarnIfError();
@ -629,10 +811,44 @@ public:
}
name[nameLength] = 0;
CStrIntern nameIntern(name);
m_Uniforms[nameIntern] = std::make_pair(location, type);
const CStrIntern nameIntern(name);
// Assign sampler uniforms to sequential texture units
m_BindingSlotsMapping[nameIntern] = m_BindingSlots.size();
BindingSlot bindingSlot{};
bindingSlot.name = nameIntern;
bindingSlot.location = location;
bindingSlot.size = size;
bindingSlot.type = type;
bindingSlot.isTexture = false;
#define CASE(TYPE, ELEMENT_TYPE, ELEMENT_COUNT) \
case GL_ ## TYPE: \
bindingSlot.elementType = GL_ ## ELEMENT_TYPE; \
bindingSlot.elementCount = ELEMENT_COUNT; \
break;
switch (type)
{
CASE(FLOAT, FLOAT, 1);
CASE(FLOAT_VEC2, FLOAT, 2);
CASE(FLOAT_VEC3, FLOAT, 3);
CASE(FLOAT_VEC4, FLOAT, 4);
CASE(INT, INT, 1);
CASE(FLOAT_MAT2, FLOAT, 4);
CASE(FLOAT_MAT3, FLOAT, 9);
CASE(FLOAT_MAT4, FLOAT, 16);
#if !CONFIG2_GLES // GL ES 2.0 doesn't support non-square matrices.
CASE(FLOAT_MAT2x3, FLOAT, 6);
CASE(FLOAT_MAT2x4, FLOAT, 8);
CASE(FLOAT_MAT3x2, FLOAT, 6);
CASE(FLOAT_MAT3x4, FLOAT, 12);
CASE(FLOAT_MAT4x2, FLOAT, 8);
CASE(FLOAT_MAT4x3, FLOAT, 12);
#endif
}
#undef CASE
// Assign sampler uniforms to sequential texture units.
if (type == GL_SAMPLER_2D
|| type == GL_SAMPLER_CUBE
#if !CONFIG2_GLES
@ -640,20 +856,51 @@ public:
#endif
)
{
const int unit = static_cast<int>(m_Samplers.size());
m_Samplers[nameIntern].first = (type == GL_SAMPLER_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D);
m_Samplers[nameIntern].second = unit;
glUniform1i(location, unit); // link uniform to unit
ogl_WarnIfError();
const auto it = requiredUnits.find(nameIntern);
const int unit = it == requiredUnits.end() ? -1 : it->second;
bindingSlot.elementType = (type == GL_SAMPLER_CUBE ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D);
bindingSlot.elementCount = unit;
bindingSlot.isTexture = true;
if (unit != -1)
{
if (unit >= static_cast<int>(occupiedUnits.size()))
occupiedUnits.resize(unit + 1);
occupiedUnits[unit] = true;
}
}
if (bindingSlot.elementType == 0)
{
LOGERROR("CShaderProgramGLSL::Link: unsupported uniform type: 0x%04x", static_cast<int>(type));
}
m_BindingSlots.emplace_back(std::move(bindingSlot));
}
for (BindingSlot& bindingSlot : m_BindingSlots)
{
if (!bindingSlot.isTexture)
continue;
if (bindingSlot.elementCount == -1)
{
// We need to find a minimal available unit.
int unit = 0;
while (unit < static_cast<int>(occupiedUnits.size()) && occupiedUnits[unit])
++unit;
if (unit >= static_cast<int>(occupiedUnits.size()))
occupiedUnits.resize(unit + 1);
occupiedUnits[unit] = true;
bindingSlot.elementCount = unit;
}
// Link uniform to unit.
glUniform1i(bindingSlot.location, bindingSlot.elementCount);
ogl_WarnIfError();
}
// TODO: verify that we're not using more samplers than is supported
Unbind();
ogl_WarnIfError();
return true;
}
@ -720,93 +967,128 @@ public:
for (const int index : m_ActiveVertexAttributes)
glDisableVertexAttribArray(index);
// TODO: should unbind textures, probably
}
Binding GetTextureBinding(texture_id_t id) override
int32_t GetBindingSlot(const CStrIntern name) const override
{
std::map<CStrIntern, std::pair<GLenum, int>>::iterator it = m_Samplers.find(CStrIntern(id));
if (it == m_Samplers.end())
return Binding();
else
return Binding((int)it->second.first, it->second.second);
auto it = m_BindingSlotsMapping.find(name);
return it == m_BindingSlotsMapping.end() ? -1 : it->second;
}
void BindTexture(texture_id_t id, GLuint tex) override
TextureUnit GetTextureUnit(const int32_t bindingSlot) override
{
std::map<CStrIntern, std::pair<GLenum, int>>::iterator it = m_Samplers.find(CStrIntern(id));
if (it == m_Samplers.end())
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return { 0, 0, 0 };
TextureUnit textureUnit;
textureUnit.type = m_BindingSlots[bindingSlot].type;
textureUnit.target = m_BindingSlots[bindingSlot].elementType;
textureUnit.unit = m_BindingSlots[bindingSlot].elementCount;
return textureUnit;
}
void SetUniform(
const int32_t bindingSlot,
const float value) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
m_Device->GetActiveCommandContext()->BindTexture(it->second.second, it->second.first, tex);
}
void BindTexture(Binding id, GLuint tex) override
{
if (id.second == -1)
if (m_BindingSlots[bindingSlot].type != GL_FLOAT ||
m_BindingSlots[bindingSlot].size != 1)
{
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform type (expected float) '%s'", m_BindingSlots[bindingSlot].name.c_str());
return;
m_Device->GetActiveCommandContext()->BindTexture(id.second, id.first, tex);
}
glUniform1f(m_BindingSlots[bindingSlot].location, value);
ogl_WarnIfError();
}
Binding GetUniformBinding(uniform_id_t id) override
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY) override
{
std::map<CStrIntern, std::pair<int, GLenum>>::iterator it = m_Uniforms.find(id);
if (it == m_Uniforms.end())
return Binding();
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC2 ||
m_BindingSlots[bindingSlot].size != 1)
{
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform type (expected vec2) '%s'", m_BindingSlots[bindingSlot].name.c_str());
return;
}
glUniform2f(m_BindingSlots[bindingSlot].location, valueX, valueY);
ogl_WarnIfError();
}
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY, const float valueZ) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC3 ||
m_BindingSlots[bindingSlot].size != 1)
{
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform type (expected vec3) '%s'", m_BindingSlots[bindingSlot].name.c_str());
return;
}
glUniform3f(m_BindingSlots[bindingSlot].location, valueX, valueY, valueZ);
ogl_WarnIfError();
}
void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ, const float valueW) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].type != GL_FLOAT_VEC4 ||
m_BindingSlots[bindingSlot].size != 1)
{
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform type (expected vec4) '%s'", m_BindingSlots[bindingSlot].name.c_str());
return;
}
glUniform4f(m_BindingSlots[bindingSlot].location, valueX, valueY, valueZ, valueW);
ogl_WarnIfError();
}
void SetUniform(
const int32_t bindingSlot, PS::span<const float> values) override
{
if (bindingSlot < 0 || bindingSlot >= static_cast<int32_t>(m_BindingSlots.size()))
return;
if (m_BindingSlots[bindingSlot].elementType != GL_FLOAT)
{
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform element type (expected float) '%s'", m_BindingSlots[bindingSlot].name.c_str());
return;
}
if (m_BindingSlots[bindingSlot].size == 1 && m_BindingSlots[bindingSlot].elementCount > static_cast<GLint>(values.size()))
{
LOGERROR(
"CShaderProgramGLSL::SetUniform(): Invalid uniform element count (expected: %zu passed: %zu) '%s'",
m_BindingSlots[bindingSlot].elementCount, values.size(), m_BindingSlots[bindingSlot].name.c_str());
return;
}
const GLint location = m_BindingSlots[bindingSlot].location;
const GLenum type = m_BindingSlots[bindingSlot].type;
if (type == GL_FLOAT)
glUniform1fv(location, 1, values.data());
else if (type == GL_FLOAT_VEC2)
glUniform2fv(location, 1, values.data());
else if (type == GL_FLOAT_VEC3)
glUniform3fv(location, 1, values.data());
else if (type == GL_FLOAT_VEC4)
glUniform4fv(location, 1, values.data());
else if (type == GL_FLOAT_MAT4)
{
// For case of array of matrices we might pass less number of matrices.
const GLint size = std::min(
m_BindingSlots[bindingSlot].size, static_cast<GLint>(values.size() / 16));
glUniformMatrix4fv(location, size, GL_FALSE, values.data());
}
else
return Binding(it->second.first, (int)it->second.second);
}
void Uniform(Binding id, float v0, float v1, float v2, float v3) override
{
if (id.first != -1)
{
if (id.second == GL_FLOAT)
glUniform1f(id.first, v0);
else if (id.second == GL_FLOAT_VEC2)
glUniform2f(id.first, v0, v1);
else if (id.second == GL_FLOAT_VEC3)
glUniform3f(id.first, v0, v1, v2);
else if (id.second == GL_FLOAT_VEC4)
glUniform4f(id.first, v0, v1, v2, v3);
else
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float, vec2, vec3, vec4)");
}
}
void Uniform(Binding id, const CMatrix3D& v) override
{
if (id.first != -1)
{
if (id.second == GL_FLOAT_MAT4)
glUniformMatrix4fv(id.first, 1, GL_FALSE, v.AsFloatArray());
else
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
}
}
void Uniform(Binding id, size_t count, const CMatrix3D* v) override
{
if (id.first != -1)
{
if (id.second == GL_FLOAT_MAT4)
glUniformMatrix4fv(id.first, count, GL_FALSE, &v->_11);
else
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected mat4)");
}
}
void Uniform(Binding id, size_t count, const float* v) override
{
if (id.first != -1)
{
if (id.second == GL_FLOAT)
glUniform1fv(id.first, count, v);
else
LOGERROR("CShaderProgramGLSL::Uniform(): Invalid uniform type (expected float)");
}
LOGERROR("CShaderProgramGLSL::SetUniform(): Invalid uniform type (expected float, vec2, vec3, vec4, mat4) '%s'", m_BindingSlots[bindingSlot].name.c_str());
ogl_WarnIfError();
}
void VertexAttribPointer(
@ -844,8 +1126,18 @@ private:
GLuint m_Program;
GLuint m_VertexShader, m_FragmentShader;
std::map<CStrIntern, std::pair<int, GLenum>> m_Uniforms;
std::map<CStrIntern, std::pair<GLenum, int>> m_Samplers; // texture target & unit chosen for each uniform sampler
struct BindingSlot
{
CStrIntern name;
GLint location;
GLint size;
GLenum type;
GLenum elementType;
GLint elementCount;
bool isTexture;
};
std::vector<BindingSlot> m_BindingSlots;
std::unordered_map<CStrIntern, int32_t> m_BindingSlotsMapping;
};
CShaderProgram::CShaderProgram(int streamflags)
@ -908,8 +1200,8 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
VfsPath vertexFile;
VfsPath fragmentFile;
CShaderDefines defines = baseDefines;
std::map<CStrIntern, int> vertexUniforms;
std::map<CStrIntern, CShaderProgram::frag_index_pair_t> fragmentUniforms;
std::map<CStrIntern, std::pair<CStr, int>> vertexUniforms;
std::map<CStrIntern, std::pair<CStr, int>> fragmentUniforms;
std::map<CStrIntern, int> vertexAttribs;
int streamFlags = 0;
@ -933,7 +1225,8 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
if (param.GetNodeName() == el_uniform)
{
vertexUniforms[CStrIntern(attributes.GetNamedItem(at_name))] = attributes.GetNamedItem(at_loc).ToInt();
vertexUniforms[CStrIntern(attributes.GetNamedItem(at_name))] =
std::make_pair(attributes.GetNamedItem(at_type), attributes.GetNamedItem(at_loc).ToInt());
}
else if (param.GetNodeName() == el_stream)
{
@ -992,158 +1285,32 @@ std::unique_ptr<CShaderProgram> CShaderProgram::Create(CDevice* device, const CS
if (param.GetNodeName() == el_uniform)
{
// A somewhat incomplete listing, missing "shadow" and "rect" versions
// which are interpreted as 2D (NB: our shadowmaps may change
// type based on user config).
GLenum type = GL_TEXTURE_2D;
const CStr t = attributes.GetNamedItem(at_type);
if (t == "sampler1D")
#if CONFIG2_GLES
debug_warn(L"sampler1D not implemented on GLES");
#else
type = GL_TEXTURE_1D;
#endif
else if (t == "sampler2D")
type = GL_TEXTURE_2D;
else if (t == "sampler3D")
#if CONFIG2_GLES
debug_warn(L"sampler3D not implemented on GLES");
#else
type = GL_TEXTURE_3D;
#endif
else if (t == "samplerCube")
type = GL_TEXTURE_CUBE_MAP;
fragmentUniforms[CStrIntern(attributes.GetNamedItem(at_name))] =
std::make_pair(attributes.GetNamedItem(at_loc).ToInt(), type);
std::make_pair(attributes.GetNamedItem(at_type), attributes.GetNamedItem(at_loc).ToInt());
}
}
}
}
if (isGLSL)
return CShaderProgram::ConstructGLSL(device, name, vertexFile, fragmentFile, defines, vertexAttribs, streamFlags);
{
return std::make_unique<CShaderProgramGLSL>(
device, name, vertexFile, fragmentFile, defines, vertexAttribs, streamFlags);
}
else
return CShaderProgram::ConstructARB(device, vertexFile, fragmentFile, defines, vertexUniforms, fragmentUniforms, streamFlags);
}
{
#if CONFIG2_GLES
// static
std::unique_ptr<CShaderProgram> CShaderProgram::ConstructARB(CDevice* UNUSED(device), const VfsPath& vertexFile, const VfsPath& fragmentFile,
const CShaderDefines& UNUSED(defines),
const std::map<CStrIntern, int>& UNUSED(vertexIndexes), const std::map<CStrIntern, frag_index_pair_t>& UNUSED(fragmentIndexes),
int UNUSED(streamflags))
{
LOGERROR("CShaderProgram::ConstructARB: '%s'+'%s': ARB shaders not supported on this device",
vertexFile.string8(), fragmentFile.string8());
return nullptr;
}
LOGERROR("CShaderProgram::Create: '%s'+'%s': ARB shaders not supported on this device",
vertexFile.string8(), fragmentFile.string8());
return nullptr;
#else
// static
std::unique_ptr<CShaderProgram> CShaderProgram::ConstructARB(
CDevice* device, const VfsPath& vertexFile, const VfsPath& fragmentFile,
const CShaderDefines& defines,
const std::map<CStrIntern, int>& vertexIndexes,
const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes,
int streamflags)
{
return std::make_unique<CShaderProgramARB>(
device, vertexFile, fragmentFile, defines, vertexIndexes, fragmentIndexes, streamflags);
}
return std::make_unique<CShaderProgramARB>(
device, vertexFile, fragmentFile, defines,
vertexUniforms, fragmentUniforms, streamFlags);
#endif
// static
std::unique_ptr<CShaderProgram> CShaderProgram::ConstructGLSL(
CDevice* device, const CStr& name,
const VfsPath& vertexFile, const VfsPath& fragmentFile,
const CShaderDefines& defines,
const std::map<CStrIntern, int>& vertexAttribs, int streamflags)
{
return std::make_unique<CShaderProgramGLSL>(
device, name, vertexFile, fragmentFile, defines, vertexAttribs, streamflags);
}
}
void CShaderProgram::BindTexture(texture_id_t id, const Renderer::Backend::GL::CTexture* tex)
{
BindTexture(id, tex->GetHandle());
}
void CShaderProgram::BindTexture(Binding id, const Renderer::Backend::GL::CTexture* tex)
{
BindTexture(id, tex->GetHandle());
}
void CShaderProgram::Uniform(Binding id, int v)
{
Uniform(id, (float)v, (float)v, (float)v, (float)v);
}
void CShaderProgram::Uniform(Binding id, float v)
{
Uniform(id, v, v, v, v);
}
void CShaderProgram::Uniform(Binding id, float v0, float v1)
{
Uniform(id, v0, v1, 0.0f, 0.0f);
}
void CShaderProgram::Uniform(Binding id, const CVector3D& v)
{
Uniform(id, v.X, v.Y, v.Z, 0.0f);
}
void CShaderProgram::Uniform(Binding id, const CColor& v)
{
Uniform(id, v.r, v.g, v.b, v.a);
}
void CShaderProgram::Uniform(uniform_id_t id, int v)
{
Uniform(GetUniformBinding(id), (float)v, (float)v, (float)v, (float)v);
}
void CShaderProgram::Uniform(uniform_id_t id, float v)
{
Uniform(GetUniformBinding(id), v, v, v, v);
}
void CShaderProgram::Uniform(uniform_id_t id, float v0, float v1)
{
Uniform(GetUniformBinding(id), v0, v1, 0.0f, 0.0f);
}
void CShaderProgram::Uniform(uniform_id_t id, const CVector3D& v)
{
Uniform(GetUniformBinding(id), v.X, v.Y, v.Z, 0.0f);
}
void CShaderProgram::Uniform(uniform_id_t id, const CColor& v)
{
Uniform(GetUniformBinding(id), v.r, v.g, v.b, v.a);
}
void CShaderProgram::Uniform(uniform_id_t id, float v0, float v1, float v2, float v3)
{
Uniform(GetUniformBinding(id), v0, v1, v2, v3);
}
void CShaderProgram::Uniform(uniform_id_t id, const CMatrix3D& v)
{
Uniform(GetUniformBinding(id), v);
}
void CShaderProgram::Uniform(uniform_id_t id, size_t count, const CMatrix3D* v)
{
Uniform(GetUniformBinding(id), count, v);
}
void CShaderProgram::Uniform(uniform_id_t id, size_t count, const float* v)
{
Uniform(GetUniformBinding(id), count, v);
}
// These should all be overridden by CShaderProgramGLSL, and not used
// if a non-GLSL shader was loaded instead:

View File

@ -53,7 +53,7 @@ class CDevice;
*
* Texture/uniform IDs are typically strings, corresponding to the names defined in
* the shader .xml file. Alternatively (and more efficiently, if used very frequently),
* call GetTextureBinding/GetUniformBinding and pass its return value as the ID.
* call GetBindingSlot and pass its return value as the ID.
* Setting uniforms that the shader .xml doesn't support is harmless.
*
* For a high-level overview of shaders and materials, see
@ -65,35 +65,9 @@ class CShaderProgram : public IShaderProgram
public:
typedef CStrIntern attrib_id_t;
typedef CStrIntern texture_id_t;
typedef CStrIntern uniform_id_t;
typedef std::pair<int, GLenum> frag_index_pair_t;
static std::unique_ptr<CShaderProgram> Create(CDevice* device, const CStr& name, const CShaderDefines& baseDefines);
/**
* Represents a uniform attribute or texture binding.
* For uniforms:
* - ARB shaders store vertex location in 'first', fragment location in 'second'.
* - GLSL shaders store uniform location in 'first', data type in 'second'.
* For textures, all store texture target (e.g. GL_TEXTURE_2D) in 'first', texture unit in 'second'.
* Non-existent bindings must store -1 in both.
*/
struct Binding
{
Binding(int a, int b) : first(a), second(b) { }
Binding() : first(-1), second(-1) { }
/**
* Returns whether this uniform attribute is active in the shader.
* If not then there's no point calling Uniform() to set its value.
*/
bool Active() const { return first != -1 || second != -1; }
int first;
int second;
};
static std::unique_ptr<CShaderProgram> Create(
CDevice* device, const CStr& name, const CShaderDefines& baseDefines);
~CShaderProgram() override;
@ -108,41 +82,32 @@ public:
*/
virtual void Unbind() = 0;
struct TextureUnit
{
GLenum type;
GLenum target;
GLint unit;
};
virtual TextureUnit GetTextureUnit(const int32_t bindingSlot) = 0;
virtual Binding GetTextureBinding(texture_id_t id) = 0;
// Variants of texture binding:
void BindTexture(texture_id_t id, const Renderer::Backend::GL::CTexture* tex);
void BindTexture(Binding id, const Renderer::Backend::GL::CTexture* tex);
virtual Binding GetUniformBinding(uniform_id_t id) = 0;
// Uniform-setting methods that subclasses must define:
virtual void Uniform(Binding id, float v0, float v1, float v2, float v3) = 0;
virtual void Uniform(Binding id, const CMatrix3D& v) = 0;
virtual void Uniform(Binding id, size_t count, const CMatrix3D* v) = 0;
virtual void Uniform(Binding id, size_t count, const float* v) = 0;
// Convenient uniform-setting wrappers:
void Uniform(Binding id, int v);
void Uniform(Binding id, float v);
void Uniform(Binding id, float v0, float v1);
void Uniform(Binding id, const CVector3D& v);
void Uniform(Binding id, const CColor& v);
void Uniform(uniform_id_t id, int v);
void Uniform(uniform_id_t id, float v);
void Uniform(uniform_id_t id, float v0, float v1);
void Uniform(uniform_id_t id, const CVector3D& v);
void Uniform(uniform_id_t id, const CColor& v);
void Uniform(uniform_id_t id, float v0, float v1, float v2, float v3);
void Uniform(uniform_id_t id, const CMatrix3D& v);
void Uniform(uniform_id_t id, size_t count, const CMatrix3D* v);
void Uniform(uniform_id_t id, size_t count, const float* v);
// Vertex attribute pointers (equivalent to glVertexPointer etc):
virtual void SetUniform(
const int32_t bindingSlot,
const float value) = 0;
virtual void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY) = 0;
virtual void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ) = 0;
virtual void SetUniform(
const int32_t bindingSlot,
const float valueX, const float valueY,
const float valueZ, const float valueW) = 0;
virtual void SetUniform(
const int32_t bindingSlot, PS::span<const float> values) = 0;
// Vertex attribute pointers (equivalent to glVertexPointer etc).
virtual void VertexAttribPointer(
const VertexAttributeStream stream, const Format format,
const uint32_t offset, const uint32_t stride, const void* data);
@ -155,39 +120,15 @@ public:
*/
void AssertPointersBound();
virtual std::vector<VfsPath> GetFileDependencies() const = 0;
protected:
CShaderProgram(int streamflags);
/**
* Construct based on ARB vertex/fragment program files.
*/
static std::unique_ptr<CShaderProgram> ConstructARB(
CDevice* device, const VfsPath& vertexFile, const VfsPath& fragmentFile,
const CShaderDefines& defines,
const std::map<CStrIntern, int>& vertexIndexes, const std::map<CStrIntern, frag_index_pair_t>& fragmentIndexes,
int streamflags);
/**
* Construct based on GLSL vertex/fragment shader files.
*/
static std::unique_ptr<CShaderProgram> ConstructGLSL(
CDevice* device, const CStr& name,
const VfsPath& vertexFile, const VfsPath& fragmentFile,
const CShaderDefines& defines,
const std::map<CStrIntern, int>& vertexAttribs,
int streamflags);
void VertexPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer);
void NormalPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer);
void ColorPointer(const Renderer::Backend::Format format, GLsizei stride, const void* pointer);
void TexCoordPointer(GLenum texture, const Renderer::Backend::Format format, GLsizei stride, const void* pointer);
void VertexAttribPointer(attrib_id_t id, const Renderer::Backend::Format format, GLboolean normalized, GLsizei stride, const void* pointer);
virtual void BindTexture(texture_id_t id, GLuint tex) = 0;
virtual void BindTexture(Binding id, GLuint tex) = 0;
int m_StreamFlags;
// Non-GLSL client state handling:

View File

@ -110,7 +110,8 @@ std::unique_ptr<CTexture> CTexture::Create(CDevice* device, const char* name,
const GLenum target = TypeToGLEnum(type);
texture->m_Device->GetActiveCommandContext()->BindTexture(0, target, texture->m_Handle);
CDeviceCommandContext::ScopedBind scopedBind(
texture->m_Device->GetActiveCommandContext(), target, texture->m_Handle);
// It's forbidden to set sampler state for multisample textures.
if (type != Type::TEXTURE_2D_MULTISAMPLE)
@ -151,7 +152,7 @@ std::unique_ptr<CTexture> CTexture::Create(CDevice* device, const char* name,
defaultSamplerDesc.addressModeV == Sampler::AddressMode::CLAMP_TO_BORDER ||
defaultSamplerDesc.addressModeW == Sampler::AddressMode::CLAMP_TO_BORDER)
{
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, defaultSamplerDesc.borderColor.AsFloatArray());
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, defaultSamplerDesc.borderColor.AsFloatArray().data());
}
ogl_WarnIfError();
@ -284,8 +285,6 @@ std::unique_ptr<CTexture> CTexture::Create(CDevice* device, const char* name,
glObjectLabel(GL_TEXTURE, texture->m_Handle, -1, name);
}
texture->m_Device->GetActiveCommandContext()->BindTexture(0, target, 0);
return texture;
}

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
@ -177,7 +177,7 @@ void CSoundBase::SetDirection(const CVector3D& direction)
if ( m_ALSource )
{
std::lock_guard<std::mutex> lock(m_ItemMutex);
alSourcefv(m_ALSource, AL_DIRECTION, direction.AsFloatArray());
alSourcefv(m_ALSource, AL_DIRECTION, direction.AsFloatArray().data());
AL_CHECK;
}
}
@ -212,7 +212,7 @@ void CSoundBase::SetLocation (const CVector3D& position)
if ( m_ALSource != 0 )
{
std::lock_guard<std::mutex> lock(m_ItemMutex);
alSourcefv(m_ALSource,AL_POSITION, position.AsFloatArray());
alSourcefv(m_ALSource,AL_POSITION, position.AsFloatArray().data());
AL_CHECK;
}
}