diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 1f8678793..b2a28d6a2 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -57,182 +57,31 @@ void FGLRenderer::RenderScreenQuad() void FGLRenderer::PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D) { + hw_postprocess.fixedcm = fixedcm; + hw_postprocess.SceneWidth = mBuffers->GetSceneWidth(); + hw_postprocess.SceneHeight = mBuffers->GetSceneHeight(); + + hw_postprocess.DeclareShaders(); + hw_postprocess.UpdateTextures(); + hw_postprocess.UpdateSteps(); + mBuffers->BlitSceneToTexture(); - UpdateCameraExposure(); + + mBuffers->CompileEffectShaders(); + mBuffers->UpdateEffectTextures(); + + mBuffers->RenderEffect("UpdateCameraExposure"); mCustomPostProcessShaders->Run("beforebloom"); - BloomScene(fixedcm); + mBuffers->RenderEffect("BloomScene"); mBuffers->BindCurrentFB(); afterBloomDrawEndScene2D(); - TonemapScene(); - ColormapScene(fixedcm); - LensDistortScene(); - ApplyFXAA(); + mBuffers->RenderEffect("TonemapScene"); + mBuffers->RenderEffect("ColormapScene"); + mBuffers->RenderEffect("LensDistortScene"); + mBuffers->RenderEffect("ApplyFXAA"); mCustomPostProcessShaders->Run("scene"); } -void FGLRenderBuffers::RenderEffect(const FString &name) -{ - // Create/update textures (To do: move out of RunEffect) - { - TMap::Iterator it(hw_postprocess.Textures); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - auto &gltexture = GLTextures[pair->Key]; - auto &glframebuffer = GLTextureFBs[pair->Key]; - - int glformat; - switch (pair->Value.Format) - { - default: - case PixelFormat::Rgba8: glformat = GL_RGBA8; break; - case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break; - case PixelFormat::R32f: glformat = GL_R32F; break; - } - - if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height)) - { - glDeleteTextures(1, &gltexture.handle); - glDeleteFramebuffers(1, &glframebuffer.handle); - gltexture.handle = 0; - glframebuffer.handle = 0; - } - - if (!gltexture) - { - if (pair->Value.Data) - gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height, pair->Value.Data.get()); - else - gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height); - gltexture.Width = pair->Value.Width; - gltexture.Height = pair->Value.Height; - glframebuffer = CreateFrameBuffer(pair->Key.GetChars(), gltexture); - } - } - } - - // Compile shaders (To do: move out of RunEffect) - { - TMap::Iterator it(hw_postprocess.Shaders); - TMap::Pair *pair; - while (it.NextPair(pair)) - { - const auto &desc = pair->Value; - auto &glshader = GLShaders[pair->Key]; - if (!glshader) - { - glshader = std::make_unique(); - - FString prolog; - if (!desc.Uniforms.empty()) - prolog = UniformBlockDecl::Create("Uniforms", desc.Uniforms, POSTPROCESS_BINDINGPOINT); - prolog += desc.Defines; - - glshader->Compile(IShaderProgram::Vertex, desc.VertexShader, "", desc.Version); - glshader->Compile(IShaderProgram::Fragment, desc.FragmentShader, prolog, desc.Version); - glshader->Link(pair->Key.GetChars()); - if (!desc.Uniforms.empty()) - glshader->SetUniformBufferLocation(POSTPROCESS_BINDINGPOINT, "Uniforms"); - } - } - } - - // Render the effect - - FGLDebug::PushGroup(name.GetChars()); - - FGLPostProcessState savedState; - savedState.SaveTextureBindings(3); - - for (const PPStep &step : hw_postprocess.Effects[name]) - { - // Bind input textures - for (unsigned int index = 0; index < step.Textures.Size(); index++) - { - const PPTextureInput &input = step.Textures[index]; - int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR; - - switch (input.Type) - { - default: - case PPTextureType::CurrentPipelineTexture: - BindCurrentTexture(index, filter); - break; - - case PPTextureType::NextPipelineTexture: - I_FatalError("PPTextureType::NextPipelineTexture not allowed as input\n"); - break; - - case PPTextureType::PPTexture: - GLTextures[input.Texture].Bind(index, filter); - break; - } - } - - // Set render target - switch (step.Output.Type) - { - default: - case PPTextureType::CurrentPipelineTexture: - BindCurrentFB(); - break; - - case PPTextureType::NextPipelineTexture: - BindNextFB(); - break; - - case PPTextureType::PPTexture: - GLTextureFBs[step.Output.Texture].Bind(); - break; - } - - // Set blend mode - if (step.BlendMode.BlendOp == STYLEOP_Add && step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_Zero && step.BlendMode.Flags == 0) - { - glDisable(GL_BLEND); - } - else - { - // To do: support all the modes - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - if (step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_One) - glBlendFunc(GL_ONE, GL_ONE); - else - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Setup viewport - glViewport(step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height); - - auto &shader = GLShaders[step.ShaderName]; - - // Set uniforms - if (step.Uniforms.Size > 0) - { - if (!shader->Uniforms) - shader->Uniforms.reset(screen->CreateUniformBuffer(step.Uniforms.Size)); - shader->Uniforms->SetData(step.Uniforms.Data); - shader->Uniforms->Bind(POSTPROCESS_BINDINGPOINT); - } - - // Set shader - shader->Bind(NOQUEUE); - - // Draw the screen quad - GLRenderer->RenderScreenQuad(); - - // Advance to next PP texture if our output was sent there - if (step.Output.Type == PPTextureType::NextPipelineTexture) - NextTexture(); - } - - glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height); - - FGLDebug::PopGroup(); -} - - //----------------------------------------------------------------------------- // // Adds ambient occlusion to the scene @@ -345,77 +194,25 @@ void FGLRenderer::AmbientOccludeScene(float m5) FGLDebug::PopGroup(); } -void FGLRenderer::UpdateCameraExposure() -{ - PPCameraExposure exposure; - exposure.DeclareShaders(); - exposure.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight()); - exposure.UpdateSteps(); - mBuffers->RenderEffect("UpdateCameraExposure"); -} - -void FGLRenderer::BloomScene(int fixedcm) -{ - if (mBuffers->GetSceneWidth() <= 0 || mBuffers->GetSceneHeight() <= 0) - return; - - PPBloom bloom; - bloom.DeclareShaders(); - bloom.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight()); - bloom.UpdateSteps(fixedcm); - mBuffers->RenderEffect("BloomScene"); -} - void FGLRenderer::BlurScene(float gameinfobluramount) { - if (mBuffers->GetSceneWidth() <= 0 || mBuffers->GetSceneHeight() <= 0) - return; + hw_postprocess.gameinfobluramount = gameinfobluramount; + + hw_postprocess.DeclareShaders(); + hw_postprocess.UpdateTextures(); + hw_postprocess.UpdateSteps(); + + mBuffers->CompileEffectShaders(); + mBuffers->UpdateEffectTextures(); - PPBloom blur; - blur.DeclareShaders(); - blur.UpdateTextures(mBuffers->GetSceneWidth(), mBuffers->GetSceneHeight()); - blur.UpdateBlurSteps(gameinfobluramount); mBuffers->RenderEffect("BlurScene"); } -void FGLRenderer::TonemapScene() -{ - PPTonemap tonemap; - tonemap.DeclareShaders(); - tonemap.UpdateTextures(); - tonemap.UpdateSteps(); - mBuffers->RenderEffect("TonemapScene"); -} - void FGLRenderer::ClearTonemapPalette() { hw_postprocess.Textures.Remove("Tonemap.Palette"); } -void FGLRenderer::ColormapScene(int fixedcm) -{ - PPColormap colormap; - colormap.DeclareShaders(); - colormap.UpdateSteps(fixedcm); - mBuffers->RenderEffect("ColormapScene"); -} - -void FGLRenderer::LensDistortScene() -{ - PPLensDistort lens; - lens.DeclareShaders(); - lens.UpdateSteps(); - mBuffers->RenderEffect("LensDistortScene"); -} - -void FGLRenderer::ApplyFXAA() -{ - PPFXAA fxaa; - fxaa.DeclareShaders(); - fxaa.UpdateSteps(); - mBuffers->RenderEffect("ApplyFXAA"); -} - //----------------------------------------------------------------------------- // // Copies the rendered screen to its final destination diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index 7ffacbb48..6fd5b4ddb 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -32,6 +32,8 @@ #include "gl/system/gl_debug.h" #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderbuffers.h" +#include "gl/renderer/gl_postprocessstate.h" +#include "gl/shaders/gl_shaderprogram.h" #include CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); @@ -586,13 +588,6 @@ void FGLRenderBuffers::BlitSceneToTexture() glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } -void FGLRenderBuffers::BlitLinear(PPFrameBuffer src, PPFrameBuffer dest, int sx0, int sy0, int sx1, int sy1, int dx0, int dy0, int dx1, int dy1) -{ - glBindFramebuffer(GL_READ_FRAMEBUFFER, src.handle); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dest.handle); - glBlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, GL_COLOR_BUFFER_BIT, GL_LINEAR); -} - //========================================================================== // // Eye textures and their frame buffers @@ -818,3 +813,183 @@ void FGLRenderBuffers::BindOutputFB() //========================================================================== bool FGLRenderBuffers::FailedCreate = false; + +//========================================================================== +// +// Creates or updates textures used by postprocess effects +// +//========================================================================== + +void FGLRenderBuffers::UpdateEffectTextures() +{ + TMap::Iterator it(hw_postprocess.Textures); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + auto &gltexture = GLTextures[pair->Key]; + auto &glframebuffer = GLTextureFBs[pair->Key]; + + int glformat; + switch (pair->Value.Format) + { + default: + case PixelFormat::Rgba8: glformat = GL_RGBA8; break; + case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break; + case PixelFormat::R32f: glformat = GL_R32F; break; + } + + if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height)) + { + glDeleteTextures(1, &gltexture.handle); + glDeleteFramebuffers(1, &glframebuffer.handle); + gltexture.handle = 0; + glframebuffer.handle = 0; + } + + if (!gltexture) + { + FGLPostProcessState savedState; + + if (pair->Value.Data) + gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height, pair->Value.Data.get()); + else + gltexture = Create2DTexture(pair->Key.GetChars(), glformat, pair->Value.Width, pair->Value.Height); + gltexture.Width = pair->Value.Width; + gltexture.Height = pair->Value.Height; + glframebuffer = CreateFrameBuffer(pair->Key.GetChars(), gltexture); + } + } +} + +//========================================================================== +// +// Compile the shaders declared by post process effects +// +//========================================================================== + +void FGLRenderBuffers::CompileEffectShaders() +{ + TMap::Iterator it(hw_postprocess.Shaders); + TMap::Pair *pair; + while (it.NextPair(pair)) + { + const auto &desc = pair->Value; + auto &glshader = GLShaders[pair->Key]; + if (!glshader) + { + glshader = std::make_unique(); + + FString prolog; + if (!desc.Uniforms.empty()) + prolog = UniformBlockDecl::Create("Uniforms", desc.Uniforms, POSTPROCESS_BINDINGPOINT); + prolog += desc.Defines; + + glshader->Compile(IShaderProgram::Vertex, desc.VertexShader, "", desc.Version); + glshader->Compile(IShaderProgram::Fragment, desc.FragmentShader, prolog, desc.Version); + glshader->Link(pair->Key.GetChars()); + if (!desc.Uniforms.empty()) + glshader->SetUniformBufferLocation(POSTPROCESS_BINDINGPOINT, "Uniforms"); + } + } +} + +//========================================================================== +// +// Renders one post process effect +// +//========================================================================== + +void FGLRenderBuffers::RenderEffect(const FString &name) +{ + FGLDebug::PushGroup(name.GetChars()); + + FGLPostProcessState savedState; + savedState.SaveTextureBindings(3); + + for (const PPStep &step : hw_postprocess.Effects[name]) + { + // Bind input textures + for (unsigned int index = 0; index < step.Textures.Size(); index++) + { + const PPTextureInput &input = step.Textures[index]; + int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR; + + switch (input.Type) + { + default: + case PPTextureType::CurrentPipelineTexture: + BindCurrentTexture(index, filter); + break; + + case PPTextureType::NextPipelineTexture: + I_FatalError("PPTextureType::NextPipelineTexture not allowed as input\n"); + break; + + case PPTextureType::PPTexture: + GLTextures[input.Texture].Bind(index, filter); + break; + } + } + + // Set render target + switch (step.Output.Type) + { + default: + case PPTextureType::CurrentPipelineTexture: + BindCurrentFB(); + break; + + case PPTextureType::NextPipelineTexture: + BindNextFB(); + break; + + case PPTextureType::PPTexture: + GLTextureFBs[step.Output.Texture].Bind(); + break; + } + + // Set blend mode + if (step.BlendMode.BlendOp == STYLEOP_Add && step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_Zero && step.BlendMode.Flags == 0) + { + glDisable(GL_BLEND); + } + else + { + // To do: support all the modes + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + if (step.BlendMode.SrcAlpha == STYLEALPHA_One && step.BlendMode.DestAlpha == STYLEALPHA_One) + glBlendFunc(GL_ONE, GL_ONE); + else + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Setup viewport + glViewport(step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height); + + auto &shader = GLShaders[step.ShaderName]; + + // Set uniforms + if (step.Uniforms.Size > 0) + { + if (!shader->Uniforms) + shader->Uniforms.reset(screen->CreateUniformBuffer(step.Uniforms.Size)); + shader->Uniforms->SetData(step.Uniforms.Data); + shader->Uniforms->Bind(POSTPROCESS_BINDINGPOINT); + } + + // Set shader + shader->Bind(NOQUEUE); + + // Draw the screen quad + GLRenderer->RenderScreenQuad(); + + // Advance to next PP texture if our output was sent there + if (step.Output.Type == PPTextureType::NextPipelineTexture) + NextTexture(); + } + + glViewport(screen->mScreenViewport.left, screen->mScreenViewport.top, screen->mScreenViewport.width, screen->mScreenViewport.height); + + FGLDebug::PopGroup(); +} diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 63967ac33..5463cde0d 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -64,6 +64,8 @@ public: bool Setup(int width, int height, int sceneWidth, int sceneHeight); + void UpdateEffectTextures(); + void CompileEffectShaders(); void RenderEffect(const FString &name); TMap GLTextures; @@ -77,8 +79,6 @@ public: void BindSceneDepthTexture(int index); void BlitSceneToTexture(); - void BlitLinear(PPFrameBuffer src, PPFrameBuffer dest, int sx0, int sy0, int sx1, int sy1, int dx0, int dy0, int dx1, int dy1); - void BindCurrentTexture(int index, int filter = GL_NEAREST, int wrap = GL_CLAMP_TO_EDGE); void BindCurrentFB(); void BindNextFB(); @@ -107,8 +107,6 @@ public: enum { NumAmbientRandomTextures = 3 }; PPTexture AmbientRandomTexture[NumAmbientRandomTextures]; - static bool IsEnabled(); - int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index af77ee86e..03c75c5d6 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -108,13 +108,7 @@ public: void RenderScreenQuad(); void PostProcessScene(int fixedcm, const std::function &afterBloomDrawEndScene2D); void AmbientOccludeScene(float m5); - void UpdateCameraExposure(); - void BloomScene(int fixedcm); - void TonemapScene(); - void ColormapScene(int fixedcm); void ClearTonemapPalette(); - void LensDistortScene(); - void ApplyFXAA(); void BlurScene(float gameinfobluramount); void CopyToBackbuffer(const IntRect *bounds, bool applyGamma); void DrawPresentTexture(const IntRect &box, bool applyGamma); diff --git a/src/hwrenderer/postprocessing/hw_postprocess.cpp b/src/hwrenderer/postprocessing/hw_postprocess.cpp index 896585d22..86328d836 100644 --- a/src/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/hwrenderer/postprocessing/hw_postprocess.cpp @@ -6,6 +6,24 @@ Postprocess hw_postprocess; +Postprocess::Postprocess() +{ + Managers.Push(new PPBloom()); + Managers.Push(new PPLensDistort()); + Managers.Push(new PPFXAA()); + Managers.Push(new PPCameraExposure()); + Managers.Push(new PPColormap()); + Managers.Push(new PPTonemap()); +} + +Postprocess::~Postprocess() +{ + for (unsigned int i = 0; i < Managers.Size(); i++) + delete Managers[i]; +} + +///////////////////////////////////////////////////////////////////////////// + void PPBloom::DeclareShaders() { hw_postprocess.Shaders["BloomCombine"] = { "shaders/glsl/bloomcombine.fp", "", {} }; @@ -14,8 +32,11 @@ void PPBloom::DeclareShaders() hw_postprocess.Shaders["BlurHorizontal"] = { "shaders/glsl/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() }; } -void PPBloom::UpdateTextures(int width, int height) +void PPBloom::UpdateTextures() { + int width = hw_postprocess.SceneWidth; + int height = hw_postprocess.SceneHeight; + // No scene, no bloom! if (width <= 0 || height <= 0) return; @@ -42,10 +63,12 @@ void PPBloom::UpdateTextures(int width, int height) } } -void PPBloom::UpdateSteps(int fixedcm) +void PPBloom::UpdateSteps() { + UpdateBlurSteps(); + // Only bloom things if enabled and no special fixed light mode is active - if (!gl_bloom || fixedcm != CM_DEFAULT || gl_ssao_debug) + if (!gl_bloom || hw_postprocess.fixedcm != CM_DEFAULT || gl_ssao_debug || hw_postprocess.SceneWidth <= 0 || hw_postprocess.SceneHeight <= 0) { hw_postprocess.Effects["BloomScene"] = {}; return; @@ -117,14 +140,14 @@ void PPBloom::UpdateSteps(int fixedcm) hw_postprocess.Effects["BloomScene"] = steps; } -void PPBloom::UpdateBlurSteps(float gameinfobluramount) +void PPBloom::UpdateBlurSteps() { // first, respect the CVar float blurAmount = gl_menu_blur; // if CVar is negative, use the gameinfo entry if (gl_menu_blur < 0) - blurAmount = gameinfobluramount; + blurAmount = hw_postprocess.gameinfobluramount; // if blurAmount == 0 or somehow still returns negative, exit to prevent a crash, clearly we don't want this if (blurAmount <= 0.0) @@ -377,8 +400,11 @@ void PPCameraExposure::DeclareShaders() hw_postprocess.Shaders["ExposureCombine"] = { "shaders/glsl/exposurecombine.fp", "", ExposureCombineUniforms::Desc() }; } -void PPCameraExposure::UpdateTextures(int width, int height) +void PPCameraExposure::UpdateTextures() { + int width = hw_postprocess.SceneWidth; + int height = hw_postprocess.SceneHeight; + if (ExposureLevels.Size() > 0 && ExposureLevels[0].Viewport.width == width && ExposureLevels[0].Viewport.height == height) { return; @@ -486,8 +512,10 @@ void PPColormap::DeclareShaders() hw_postprocess.Shaders["Colormap"] = { "shaders/glsl/colormap.fp", "", ColormapUniforms::Desc() }; } -void PPColormap::UpdateSteps(int fixedcm) +void PPColormap::UpdateSteps() { + int fixedcm = hw_postprocess.fixedcm; + if (fixedcm < CM_FIRSTSPECIALCOLORMAP || fixedcm >= CM_MAXCOLORMAP) { hw_postprocess.Effects["ColormapScene"] = {}; diff --git a/src/hwrenderer/postprocessing/hw_postprocess.h b/src/hwrenderer/postprocessing/hw_postprocess.h index 9f19289fb..1708a86b4 100644 --- a/src/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/hwrenderer/postprocessing/hw_postprocess.h @@ -201,12 +201,34 @@ public: int Version = 330; }; +class PPEffectManager +{ +public: + virtual void DeclareShaders() { } + virtual void UpdateTextures() { } + virtual void UpdateSteps() { } +}; + class Postprocess { public: + Postprocess(); + ~Postprocess(); + + void DeclareShaders() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->DeclareShaders(); } + void UpdateTextures() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->UpdateTextures(); } + void UpdateSteps() { for (unsigned int i = 0; i < Managers.Size(); i++) Managers[i]->UpdateSteps(); } + + int SceneWidth = 0; + int SceneHeight = 0; + int fixedcm; + float gameinfobluramount; + TMap> Effects; TMap Textures; TMap Shaders; + + TArray Managers; }; extern Postprocess hw_postprocess; @@ -258,15 +280,16 @@ public: PPTextureName HTexture; }; -class PPBloom +class PPBloom : public PPEffectManager { public: - void DeclareShaders(); - void UpdateTextures(int sceneWidth, int sceneHeight); - void UpdateSteps(int fixedcm); - void UpdateBlurSteps(float gameinfobluramount); + void DeclareShaders() override; + void UpdateTextures() override; + void UpdateSteps() override; private: + void UpdateBlurSteps(); + PPStep BlurStep(const BlurUniforms &blurUniforms, PPTextureName input, PPTextureName output, PPViewport viewport, bool vertical); static float ComputeBlurGaussian(float n, float theta); @@ -299,11 +322,11 @@ struct LensUniforms } }; -class PPLensDistort +class PPLensDistort : public PPEffectManager { public: - void DeclareShaders(); - void UpdateSteps(); + void DeclareShaders() override; + void UpdateSteps() override; }; ///////////////////////////////////////////////////////////////////////////// @@ -324,11 +347,11 @@ struct FXAAUniforms } }; -class PPFXAA +class PPFXAA : public PPEffectManager { public: - void DeclareShaders(); - void UpdateSteps(); + void DeclareShaders() override; + void UpdateSteps() override; private: int GetMaxVersion(); @@ -378,12 +401,12 @@ public: PPTextureName Texture; }; -class PPCameraExposure +class PPCameraExposure : public PPEffectManager { public: - void DeclareShaders(); - void UpdateTextures(int sceneWidth, int sceneHeight); - void UpdateSteps(); + void DeclareShaders() override; + void UpdateTextures() override; + void UpdateSteps() override; private: TArray ExposureLevels; @@ -407,21 +430,21 @@ struct ColormapUniforms } }; -class PPColormap +class PPColormap : public PPEffectManager { public: - void DeclareShaders(); - void UpdateSteps(int fixedcm); + void DeclareShaders() override; + void UpdateSteps() override; }; ///////////////////////////////////////////////////////////////////////////// -class PPTonemap +class PPTonemap : public PPEffectManager { public: - void DeclareShaders(); - void UpdateTextures(); - void UpdateSteps(); + void DeclareShaders() override; + void UpdateTextures() override; + void UpdateSteps() override; enum TonemapMode {