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;
CLOSTexture::CLOSTexture(CSimulation2& simulation)
: m_Simulation(simulation), m_Dirty(true), m_ShaderInitialized(false),
m_SmoothFBO(0), m_MapSize(0), m_WhichTex(true)
: m_Simulation(simulation)
{
if (CRenderer::IsInitialised() && g_RenderingOptions.GetSmoothLOS())
CreateShader();
@ -69,8 +68,10 @@ CLOSTexture::CLOSTexture(CSimulation2& simulation)
CLOSTexture::~CLOSTexture()
{
if (m_SmoothFBO)
glDeleteFramebuffersEXT(1, &m_SmoothFBO);
if (m_SmoothFBO1)
glDeleteFramebuffersEXT(1, &m_SmoothFBO1);
if (m_SmoothFBO2)
glDeleteFramebuffersEXT(1, &m_SmoothFBO2);
if (m_Texture)
DeleteTexture();
@ -79,10 +80,10 @@ CLOSTexture::~CLOSTexture()
// Create the LOS texture engine. Should be ran only once.
bool CLOSTexture::CreateShader()
{
m_smoothShader = g_Renderer.GetShaderManager().LoadEffect(str_los_interp);
CShaderProgramPtr shader = m_smoothShader->GetShader();
m_SmoothTech = g_Renderer.GetShaderManager().LoadEffect(str_los_interp);
CShaderProgramPtr shader = m_SmoothTech->GetShader();
m_ShaderInitialized = m_smoothShader && shader;
m_ShaderInitialized = m_SmoothTech && shader;
if (!m_ShaderInitialized)
{
@ -91,7 +92,8 @@ bool CLOSTexture::CreateShader()
return false;
}
glGenFramebuffersEXT(1, &m_SmoothFBO);
glGenFramebuffersEXT(1, &m_SmoothFBO1);
glGenFramebuffersEXT(1, &m_SmoothFBO2);
return true;
}
@ -139,18 +141,10 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
if (skipSmoothLOS)
return;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_SmoothFBO);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
(m_WhichTex ? m_TextureSmooth2 : m_TextureSmooth1)->GetHandle(), 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (m_WhichTex ? m_SmoothFBO2 : m_SmoothFBO1));
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
{
LOGWARNING("LOS framebuffer object incomplete: 0x%04X", status);
}
m_smoothShader->BeginPass();
CShaderProgramPtr shader = m_smoothShader->GetShader();
m_SmoothTech->BeginPass();
CShaderProgramPtr shader = m_SmoothTech->GetShader();
glDisable(GL_BLEND);
@ -198,9 +192,7 @@ void CLOSTexture::InterpolateLOS(Renderer::Backend::GL::CDeviceCommandContext* d
g_Renderer.SetViewport(oldVp);
shader->Unbind();
m_smoothShader->EndPass();
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
m_SmoothTech->EndPass();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@ -256,6 +248,20 @@ void CLOSTexture::ConstructTexture(Renderer::Backend::GL::CDeviceCommandContext*
m_TextureSmooth2 = Renderer::Backend::GL::CTexture::Create2D(
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_TextureSmooth2.get(), Renderer::Backend::Format::A8, texData.get(), textureSize * textureSize);
}

View File

@ -84,19 +84,22 @@ private:
CSimulation2& m_Simulation;
bool m_Dirty;
bool m_Dirty = true;
bool m_ShaderInitialized;
bool m_ShaderInitialized = false;
std::unique_ptr<Renderer::Backend::GL::CTexture>
m_Texture, m_TextureSmooth1, m_TextureSmooth2;
bool m_WhichTex;
bool m_WhichTex = true;
GLuint m_SmoothFBO;
CShaderTechniquePtr m_smoothShader;
// We update textures once a frame, so we change a FBO once a frame. That
// 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_MinimapTextureMatrix;

View File

@ -880,11 +880,15 @@ void CSceneRenderer::RenderSubmissions(
{
if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater())
{
m->waterManager.UpdateQuality();
PROFILE3_GPU("water scissor");
RenderReflections(context, waterScissor);
if (g_RenderingOptions.GetWaterRefraction())
RenderRefractions(context, waterScissor);
m->terrainRenderer.RenderWaterFoamOccluders(cullGroup);
}
}

View File

@ -51,7 +51,8 @@
* TerrainRenderer keeps track of which phase it is in, to detect
* when Submit, PrepareForRendering etc. are called in the wrong order.
*/
enum Phase {
enum Phase
{
Phase_Submit,
Phase_Render
};
@ -400,38 +401,6 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, int cullGr
const double time = waterManager.m_WaterTexTimer;
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);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
@ -580,9 +549,7 @@ void TerrainRenderer::RenderSimpleWater(int cullGroup)
// Render water that is part of the terrain
void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup, ShadowMap* shadow)
{
WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
waterManager.UpdateQuality();
const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager();
if (!waterManager.WillRenderFancyWater())
RenderSimpleWater(cullGroup);
@ -590,6 +557,36 @@ void TerrainRenderer::RenderWater(const CShaderDefines& context, int cullGroup,
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)
{
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.
*
* 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);
/**
* Renders terrain to a framebuffer to occlude shore foams.
*/
void RenderWaterFoamOccluders(int cullGroup);
/**
* Calculate a scissor rectangle for the visible water patches.
*/