Optimizes FBO usages for LOSTexture and water shore foam.
Tested By: Stan Differential Revision: https://code.wildfiregames.com/D4418 This was SVN commit r26180.
This commit is contained in:
parent
dfafdcd792
commit
b061a7ead4
@ -60,8 +60,7 @@ static const size_t g_BlurSize = 7;
|
|||||||
static const size_t g_SubTextureAlignment = 4;
|
static const size_t g_SubTextureAlignment = 4;
|
||||||
|
|
||||||
CLOSTexture::CLOSTexture(CSimulation2& simulation)
|
CLOSTexture::CLOSTexture(CSimulation2& simulation)
|
||||||
: m_Simulation(simulation), m_Dirty(true), m_ShaderInitialized(false),
|
: m_Simulation(simulation)
|
||||||
m_SmoothFBO(0), m_MapSize(0), m_WhichTex(true)
|
|
||||||
{
|
{
|
||||||
if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS())
|
if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS())
|
||||||
CreateShader();
|
CreateShader();
|
||||||
@ -69,8 +68,10 @@ CLOSTexture::CLOSTexture(CSimulation2& simulation)
|
|||||||
|
|
||||||
CLOSTexture::~CLOSTexture()
|
CLOSTexture::~CLOSTexture()
|
||||||
{
|
{
|
||||||
if (m_SmoothFBO)
|
if (m_SmoothFBO1)
|
||||||
glDeleteFramebuffersEXT(1, &m_SmoothFBO);
|
glDeleteFramebuffersEXT(1, &m_SmoothFBO1);
|
||||||
|
if (m_SmoothFBO2)
|
||||||
|
glDeleteFramebuffersEXT(1, &m_SmoothFBO2);
|
||||||
|
|
||||||
if (m_Texture)
|
if (m_Texture)
|
||||||
DeleteTexture();
|
DeleteTexture();
|
||||||
@ -79,10 +80,10 @@ CLOSTexture::~CLOSTexture()
|
|||||||
// Create the LOS texture engine. Should be ran only once.
|
// Create the LOS texture engine. Should be ran only once.
|
||||||
bool CLOSTexture::CreateShader()
|
bool CLOSTexture::CreateShader()
|
||||||
{
|
{
|
||||||
m_smoothShader = g_Renderer.GetShaderManager().LoadEffect(str_los_interp);
|
m_SmoothTech = g_Renderer.GetShaderManager().LoadEffect(str_los_interp);
|
||||||
CShaderProgramPtr shader = m_smoothShader->GetShader();
|
CShaderProgramPtr shader = m_SmoothTech->GetShader();
|
||||||
|
|
||||||
m_ShaderInitialized = m_smoothShader && shader;
|
m_ShaderInitialized = m_SmoothTech && shader;
|
||||||
|
|
||||||
if (!m_ShaderInitialized)
|
if (!m_ShaderInitialized)
|
||||||
{
|
{
|
||||||
@ -91,7 +92,8 @@ bool CLOSTexture::CreateShader()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &m_SmoothFBO);
|
glGenFramebuffersEXT(1, &m_SmoothFBO1);
|
||||||
|
glGenFramebuffersEXT(1, &m_SmoothFBO2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,18 +141,10 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
|
|||||||
if (skipSmoothLOS)
|
if (skipSmoothLOS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_SmoothFBO);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (m_WhichTex ? m_SmoothFBO2 : m_SmoothFBO1));
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
|
|
||||||
(m_WhichTex ? m_TextureSmooth2 : m_TextureSmooth1)->GetHandle(), 0);
|
|
||||||
|
|
||||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
m_SmoothTech->BeginPass();
|
||||||
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
CShaderProgramPtr shader = m_SmoothTech->GetShader();
|
||||||
{
|
|
||||||
LOGWARNING("LOS framebuffer object incomplete: 0x%04X", status);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_smoothShader->BeginPass();
|
|
||||||
CShaderProgramPtr shader = m_smoothShader->GetShader();
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
@ -198,9 +192,7 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
|
|||||||
g_Renderer.SetViewport(oldVp);
|
g_Renderer.SetViewport(oldVp);
|
||||||
|
|
||||||
shader->Unbind();
|
shader->Unbind();
|
||||||
m_smoothShader->EndPass();
|
m_SmoothTech->EndPass();
|
||||||
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
@ -256,6 +248,20 @@ void CLOSTexture::ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext*
|
|||||||
m_TextureSmooth2 = Renderer::Backend::GL::CTexture::Create2D(
|
m_TextureSmooth2 = Renderer::Backend::GL::CTexture::Create2D(
|
||||||
Renderer::Backend::Format::A8, textureSize, textureSize, defaultSamplerDesc);
|
Renderer::Backend::Format::A8, textureSize, textureSize, defaultSamplerDesc);
|
||||||
|
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_SmoothFBO1);
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
|
||||||
|
m_TextureSmooth1->GetHandle(), 0);
|
||||||
|
GLenum status1 = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_SmoothFBO2);
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
|
||||||
|
m_TextureSmooth2->GetHandle(), 0);
|
||||||
|
GLenum status2 = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||||
|
if (status1 != GL_FRAMEBUFFER_COMPLETE_EXT || status2 != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||||
|
{
|
||||||
|
LOGWARNING("LOS framebuffer object incomplete: 0x%04X 0x%04X", status1, status2);
|
||||||
|
}
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
deviceCommandContext->UploadTexture(m_TextureSmooth1.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize);
|
deviceCommandContext->UploadTexture(m_TextureSmooth1.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize);
|
||||||
deviceCommandContext->UploadTexture(m_TextureSmooth2.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize);
|
deviceCommandContext->UploadTexture(m_TextureSmooth2.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize);
|
||||||
}
|
}
|
||||||
|
@ -84,19 +84,22 @@ private:
|
|||||||
|
|
||||||
CSimulation2& m_Simulation;
|
CSimulation2& m_Simulation;
|
||||||
|
|
||||||
bool m_Dirty;
|
bool m_Dirty = true;
|
||||||
|
|
||||||
bool m_ShaderInitialized;
|
bool m_ShaderInitialized = false;
|
||||||
|
|
||||||
std::unique_ptr<Renderer::Backend::GL::CTexture>
|
std::unique_ptr<Renderer::Backend::GL::CTexture>
|
||||||
m_Texture, m_TextureSmooth1, m_TextureSmooth2;
|
m_Texture, m_TextureSmooth1, m_TextureSmooth2;
|
||||||
|
|
||||||
bool m_WhichTex;
|
bool m_WhichTex = true;
|
||||||
|
|
||||||
GLuint m_SmoothFBO;
|
// We update textures once a frame, so we change a FBO once a frame. That
|
||||||
CShaderTechniquePtr m_smoothShader;
|
// allows us to use two ping-pong FBOs instead of checking completeness of
|
||||||
|
// FBO each frame.
|
||||||
|
GLuint m_SmoothFBO1 = 0, m_SmoothFBO2 = 0;
|
||||||
|
CShaderTechniquePtr m_SmoothTech;
|
||||||
|
|
||||||
size_t m_MapSize; // vertexes per side
|
size_t m_MapSize = 0; // vertexes per side
|
||||||
|
|
||||||
CMatrix3D m_TextureMatrix;
|
CMatrix3D m_TextureMatrix;
|
||||||
CMatrix3D m_MinimapTextureMatrix;
|
CMatrix3D m_MinimapTextureMatrix;
|
||||||
|
@ -880,11 +880,15 @@ void CSceneRenderer::RenderSubmissions(
|
|||||||
{
|
{
|
||||||
if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater())
|
if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater())
|
||||||
{
|
{
|
||||||
|
m->waterManager.UpdateQuality();
|
||||||
|
|
||||||
PROFILE3_GPU("water scissor");
|
PROFILE3_GPU("water scissor");
|
||||||
RenderReflections(context, waterScissor);
|
RenderReflections(context, waterScissor);
|
||||||
|
|
||||||
if (g_RenderingOptions.GetWaterRefraction())
|
if (g_RenderingOptions.GetWaterRefraction())
|
||||||
RenderRefractions(context, waterScissor);
|
RenderRefractions(context, waterScissor);
|
||||||
|
|
||||||
|
m->terrainRenderer.RenderWaterFoamOccluders(cullGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,8 @@
|
|||||||
* TerrainRenderer keeps track of which phase it is in, to detect
|
* TerrainRenderer keeps track of which phase it is in, to detect
|
||||||
* when Submit, PrepareForRendering etc. are called in the wrong order.
|
* when Submit, PrepareForRendering etc. are called in the wrong order.
|
||||||
*/
|
*/
|
||||||
enum Phase {
|
enum Phase
|
||||||
|
{
|
||||||
Phase_Submit,
|
Phase_Submit,
|
||||||
Phase_Render
|
Phase_Render
|
||||||
};
|
};
|
||||||
@ -400,38 +401,6 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
|
|||||||
const double time = waterManager.m_WaterTexTimer;
|
const double time = waterManager.m_WaterTexTimer;
|
||||||
const float repeatPeriod = waterManager.m_RepeatPeriod;
|
const float repeatPeriod = waterManager.m_RepeatPeriod;
|
||||||
|
|
||||||
// Render normals and foam to a framebuffer if we're in fancy effects
|
|
||||||
if (waterManager.m_WaterFancyEffects)
|
|
||||||
{
|
|
||||||
// Save the post-processing framebuffer.
|
|
||||||
GLint fbo;
|
|
||||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &fbo);
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO);
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
glDepthFunc(GL_LEQUAL);
|
|
||||||
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
// Overwrite waves that would be behind the ground.
|
|
||||||
CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
|
||||||
dummyTech->BeginPass();
|
|
||||||
CShaderProgramPtr dummyShader = dummyTech->GetShader();
|
|
||||||
|
|
||||||
dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
|
|
||||||
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
|
|
||||||
std::vector<CPatchRData*>& visiblePatches = m->visiblePatches[cullGroup];
|
|
||||||
for (size_t i = 0; i < visiblePatches.size(); ++i)
|
|
||||||
{
|
|
||||||
CPatchRData* data = visiblePatches[i];
|
|
||||||
data->RenderWater(dummyShader, true, true);
|
|
||||||
}
|
|
||||||
dummyTech->EndPass();
|
|
||||||
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
|
||||||
}
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
@ -580,9 +549,7 @@ void TerrainRenderer::RenderSimpleWater(int cullGroup)
|
|||||||
// Render water that is part of the terrain
|
// Render water that is part of the terrain
|
||||||
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
|
||||||
{
|
{
|
||||||
WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
|
const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
|
||||||
|
|
||||||
waterManager.UpdateQuality();
|
|
||||||
|
|
||||||
if (!waterManager.WillRenderFancyWater())
|
if (!waterManager.WillRenderFancyWater())
|
||||||
RenderSimpleWater(cullGroup);
|
RenderSimpleWater(cullGroup);
|
||||||
@ -590,6 +557,36 @@ void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup,
|
|||||||
RenderFancyWater(context, cullGroup, shadow);
|
RenderFancyWater(context, cullGroup, shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainRenderer::RenderWaterFoamOccluders(int cullGroup)
|
||||||
|
{
|
||||||
|
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
|
||||||
|
const WaterManager& waterManager = sceneRenderer.GetWaterManager();
|
||||||
|
if (!waterManager.WillRenderFancyWater())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Render normals and foam to a framebuffer if we're using fancy effects.
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, waterManager.m_FancyEffectsFBO);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
// Overwrite waves that would be behind the ground.
|
||||||
|
CShaderTechniquePtr dummyTech = g_Renderer.GetShaderManager().LoadEffect(str_solid);
|
||||||
|
dummyTech->BeginPass();
|
||||||
|
CShaderProgramPtr dummyShader = dummyTech->GetShader();
|
||||||
|
|
||||||
|
dummyShader->Uniform(str_transform, sceneRenderer.GetViewCamera().GetViewProjection());
|
||||||
|
dummyShader->Uniform(str_color, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
for (CPatchRData* data : m->visiblePatches[cullGroup])
|
||||||
|
data->RenderWater(dummyShader, true, true);
|
||||||
|
dummyTech->EndPass();
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void TerrainRenderer::RenderPriorities(int cullGroup)
|
void TerrainRenderer::RenderPriorities(int cullGroup)
|
||||||
{
|
{
|
||||||
PROFILE("priorities");
|
PROFILE("priorities");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2021 Wildfire Games.
|
/* Copyright (C) 2022 Wildfire Games.
|
||||||
* This file is part of 0 A.D.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
@ -130,6 +130,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
void RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders terrain to a framebuffer to occlude shore foams.
|
||||||
|
*/
|
||||||
|
void RenderWaterFoamOccluders(int cullGroup);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a scissor rectangle for the visible water patches.
|
* Calculate a scissor rectangle for the visible water patches.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user