1
0
forked from 0ad/0ad

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:
Vladislav Belov 2022-01-06 22:44:54 +00:00
parent dfafdcd792
commit b061a7ead4
5 changed files with 80 additions and 65 deletions

View File

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

View File

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

View File

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

View File

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

View File

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