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:
parent
a8caed8348
commit
04bd96cee0
@ -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>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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
|
||||
|
@ -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"/>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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 =
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
76
source/ps/containers/Span.h
Normal file
76
source/ps/containers/Span.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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[] =
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -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>;
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user