diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52ad9a1e6..b432731fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1075,7 +1075,6 @@ set (PCH_SOURCES hwrenderer/postprocessing/hw_shadowmapshader.cpp hwrenderer/postprocessing/hw_presentshader.cpp hwrenderer/postprocessing/hw_present3dRowshader.cpp - hwrenderer/postprocessing/hw_ambientshader.cpp hwrenderer/textures/hw_material.cpp hwrenderer/textures/hw_precache.cpp hwrenderer/utility/hw_clock.cpp diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index b2a28d6a2..bca08d8b7 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -39,7 +39,6 @@ #include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_postprocessstate.h" #include "gl/data/gl_vertexbuffer.h" -#include "hwrenderer/postprocessing/hw_ambientshader.h" #include "hwrenderer/postprocessing/hw_presentshader.h" #include "hwrenderer/postprocessing/hw_postprocess.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" @@ -65,8 +64,6 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function &aft hw_postprocess.UpdateTextures(); hw_postprocess.UpdateSteps(); - mBuffers->BlitSceneToTexture(); - mBuffers->CompileEffectShaders(); mBuffers->UpdateEffectTextures(); @@ -90,108 +87,18 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function &aft void FGLRenderer::AmbientOccludeScene(float m5) { - FGLDebug::PushGroup("AmbientOccludeScene"); + hw_postprocess.SceneWidth = mBuffers->GetSceneWidth(); + hw_postprocess.SceneHeight = mBuffers->GetSceneHeight(); + hw_postprocess.m5 = m5; - FGLPostProcessState savedState; - savedState.SaveTextureBindings(3); + hw_postprocess.DeclareShaders(); + hw_postprocess.UpdateTextures(); + hw_postprocess.UpdateSteps(); - float bias = gl_ssao_bias; - float aoRadius = gl_ssao_radius; - const float blurAmount = gl_ssao_blur; - float aoStrength = gl_ssao_strength; + mBuffers->CompileEffectShaders(); + mBuffers->UpdateEffectTextures(); - //float tanHalfFovy = tan(fovy * (M_PI / 360.0f)); - float tanHalfFovy = 1.0f / m5; - float invFocalLenX = tanHalfFovy * (mBuffers->GetSceneWidth() / (float)mBuffers->GetSceneHeight()); - float invFocalLenY = tanHalfFovy; - float nDotVBias = clamp(bias, 0.0f, 1.0f); - float r2 = aoRadius * aoRadius; - - float blurSharpness = 1.0f / blurAmount; - - auto sceneScale = screen->SceneScale(); - auto sceneOffset = screen->SceneOffset(); - - int randomTexture = clamp(gl_ssao - 1, 0, FGLRenderBuffers::NumAmbientRandomTextures - 1); - - // Calculate linear depth values - mBuffers->LinearDepthFB.Bind(); - glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight); - mBuffers->BindSceneDepthTexture(0); - mBuffers->BindSceneColorTexture(1); - mLinearDepthShader->Bind(NOQUEUE); - if (gl_multisample > 1) mLinearDepthShader->Uniforms->SampleIndex = 0; - mLinearDepthShader->Uniforms->LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear(); - mLinearDepthShader->Uniforms->LinearizeDepthB = MAX(1.0f / screen->GetZNear(), 1.e-8f); - mLinearDepthShader->Uniforms->InverseDepthRangeA = 1.0f; - mLinearDepthShader->Uniforms->InverseDepthRangeB = 0.0f; - mLinearDepthShader->Uniforms->Scale = sceneScale; - mLinearDepthShader->Uniforms->Offset = sceneOffset; - mLinearDepthShader->Uniforms.Set(); - RenderScreenQuad(); - - // Apply ambient occlusion - mBuffers->AmbientFB1.Bind(); - mBuffers->LinearDepthTexture.Bind(0); - mBuffers->AmbientRandomTexture[randomTexture].Bind(2, GL_NEAREST, GL_REPEAT); - mBuffers->BindSceneNormalTexture(1); - mSSAOShader->Bind(NOQUEUE); - if (gl_multisample > 1) mSSAOShader->Uniforms->SampleIndex = 0; - mSSAOShader->Uniforms->UVToViewA = { 2.0f * invFocalLenX, 2.0f * invFocalLenY }; - mSSAOShader->Uniforms->UVToViewB = { -invFocalLenX, -invFocalLenY }; - mSSAOShader->Uniforms->InvFullResolution = { 1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight }; - mSSAOShader->Uniforms->NDotVBias = nDotVBias; - mSSAOShader->Uniforms->NegInvR2 = -1.0f / r2; - mSSAOShader->Uniforms->RadiusToScreen = aoRadius * 0.5 / tanHalfFovy * mBuffers->AmbientHeight; - mSSAOShader->Uniforms->AOMultiplier = 1.0f / (1.0f - nDotVBias); - mSSAOShader->Uniforms->AOStrength = aoStrength; - mSSAOShader->Uniforms->Scale = sceneScale; - mSSAOShader->Uniforms->Offset = sceneOffset; - mSSAOShader->Uniforms.Set(); - RenderScreenQuad(); - - // Blur SSAO texture - if (gl_ssao_debug < 2) - { - mBuffers->AmbientFB0.Bind(); - mBuffers->AmbientTexture1.Bind(0); - mDepthBlurShader->Bind(NOQUEUE, false); - mDepthBlurShader->Uniforms[false]->BlurSharpness = blurSharpness; - mDepthBlurShader->Uniforms[false]->InvFullResolution = { 1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight }; - mDepthBlurShader->Uniforms[false].Set(); - RenderScreenQuad(); - - mBuffers->AmbientFB1.Bind(); - mBuffers->AmbientTexture0.Bind(0); - mDepthBlurShader->Bind(NOQUEUE, true); - mDepthBlurShader->Uniforms[true]->BlurSharpness = blurSharpness; - mDepthBlurShader->Uniforms[true]->InvFullResolution = { 1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight }; - mDepthBlurShader->Uniforms[true]->PowExponent = gl_ssao_exponent; - mDepthBlurShader->Uniforms[true].Set(); - RenderScreenQuad(); - } - - // Add SSAO back to scene texture: - mBuffers->BindSceneFB(false); - glViewport(screen->mSceneViewport.left, screen->mSceneViewport.top, screen->mSceneViewport.width, screen->mSceneViewport.height); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (gl_ssao_debug != 0) - { - glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - } - mBuffers->AmbientTexture1.Bind(0, GL_LINEAR); - mBuffers->BindSceneFogTexture(1); - mSSAOCombineShader->Bind(NOQUEUE); - if (gl_multisample > 1) mSSAOCombineShader->Uniforms->SampleCount = gl_multisample; - mSSAOCombineShader->Uniforms->Scale = screen->SceneScale(); - mSSAOCombineShader->Uniforms->Offset = screen->SceneOffset(); - mSSAOCombineShader->Uniforms.Set(); - RenderScreenQuad(); - - FGLDebug::PopGroup(); + mBuffers->RenderEffect("AmbientOccludeScene"); } void FGLRenderer::BlurScene(float gameinfobluramount) diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index 6fd5b4ddb..0119341a8 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -60,7 +60,6 @@ FGLRenderBuffers::~FGLRenderBuffers() ClearScene(); ClearPipeline(); ClearEyeBuffers(); - ClearAmbientOcclusion(); ClearShadowMap(); } @@ -105,18 +104,6 @@ void FGLRenderBuffers::ClearEyeBuffers() mEyeFBs.Clear(); } -void FGLRenderBuffers::ClearAmbientOcclusion() -{ - DeleteFrameBuffer(LinearDepthFB); - DeleteFrameBuffer(AmbientFB0); - DeleteFrameBuffer(AmbientFB1); - DeleteTexture(LinearDepthTexture); - DeleteTexture(AmbientTexture0); - DeleteTexture(AmbientTexture1); - for (int i = 0; i < NumAmbientRandomTextures; i++) - DeleteTexture(AmbientRandomTexture[i]); -} - void FGLRenderBuffers::DeleteTexture(PPTexture &tex) { if (tex.handle != 0) @@ -145,7 +132,7 @@ void FGLRenderBuffers::DeleteFrameBuffer(PPFrameBuffer &fb) // //========================================================================== -bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHeight) +void FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHeight) { if (width <= 0 || height <= 0) I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height); @@ -169,14 +156,8 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei mHeight = height; mSamples = samples; mSceneUsesTextures = needsSceneTextures; - - // Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts - if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight) - { - CreateAmbientOcclusion(sceneWidth, sceneHeight); - mSceneWidth = sceneWidth; - mSceneHeight = sceneHeight; - } + mSceneWidth = sceneWidth; + mSceneHeight = sceneHeight; glBindTexture(GL_TEXTURE_2D, textureBinding); glActiveTexture(activeTex); @@ -195,8 +176,6 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei mSceneHeight = 0; I_FatalError("Unable to create render buffers."); } - - return true; } //========================================================================== @@ -265,55 +244,6 @@ void FGLRenderBuffers::CreatePipeline(int width, int height) } } -//========================================================================== -// -// Creates ambient occlusion working buffers -// -//========================================================================== - -void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height) -{ - ClearAmbientOcclusion(); - - if (width <= 0 || height <= 0) - return; - - AmbientWidth = (width + 1) / 2; - AmbientHeight = (height + 1) / 2; - LinearDepthTexture = Create2DTexture("LinearDepthTexture", GL_R32F, AmbientWidth, AmbientHeight); - AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG16F, AmbientWidth, AmbientHeight); - AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG16F, AmbientWidth, AmbientHeight); - LinearDepthFB = CreateFrameBuffer("LinearDepthFB", LinearDepthTexture); - AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0); - AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1); - - // Must match quality enum in FSSAOShader::GetDefines - double numDirections[NumAmbientRandomTextures] = { 2.0, 4.0, 8.0 }; - - std::mt19937 generator(1337); - std::uniform_real_distribution distribution(0.0, 1.0); - for (int quality = 0; quality < NumAmbientRandomTextures; quality++) - { - int16_t randomValues[16 * 4]; - - for (int i = 0; i < 16; i++) - { - double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality]; - double x = cos(angle); - double y = sin(angle); - double z = distribution(generator); - double w = distribution(generator); - - randomValues[i * 4 + 0] = (int16_t)clamp(x * 32767.0, -32768.0, 32767.0); - randomValues[i * 4 + 1] = (int16_t)clamp(y * 32767.0, -32768.0, 32767.0); - randomValues[i * 4 + 2] = (int16_t)clamp(z * 32767.0, -32768.0, 32767.0); - randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0); - } - - AmbientRandomTexture[quality] = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues); - } -} - //========================================================================== // // Creates eye buffers if needed @@ -563,7 +493,7 @@ void FGLRenderBuffers::ClearFrameBuffer(bool stencil, bool depth) //========================================================================== // -// Resolves the multisample frame buffer by copying it to the scene texture +// Resolves the multisample frame buffer by copying it to the first pipeline texture // //========================================================================== @@ -836,6 +766,8 @@ void FGLRenderBuffers::UpdateEffectTextures() case PixelFormat::Rgba8: glformat = GL_RGBA8; break; case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break; case PixelFormat::R32f: glformat = GL_R32F; break; + case PixelFormat::Rg16f: glformat = GL_RG16F; break; + case PixelFormat::Rgba16_snorm: glformat = GL_RGBA16_SNORM; break; } if (gltexture && (gltexture.Width != pair->Value.Width || gltexture.Height != pair->Value.Height)) @@ -913,12 +845,13 @@ void FGLRenderBuffers::RenderEffect(const FString &name) { const PPTextureInput &input = step.Textures[index]; int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR; + int wrap = (input.Wrap == PPWrapMode::Clamp) ? GL_CLAMP : GL_REPEAT; switch (input.Type) { default: case PPTextureType::CurrentPipelineTexture: - BindCurrentTexture(index, filter); + BindCurrentTexture(index, filter, wrap); break; case PPTextureType::NextPipelineTexture: @@ -926,7 +859,23 @@ void FGLRenderBuffers::RenderEffect(const FString &name) break; case PPTextureType::PPTexture: - GLTextures[input.Texture].Bind(index, filter); + GLTextures[input.Texture].Bind(index, filter, wrap); + break; + + case PPTextureType::SceneColor: + BindSceneColorTexture(index); + break; + + case PPTextureType::SceneFog: + BindSceneFogTexture(index); + break; + + case PPTextureType::SceneNormal: + BindSceneNormalTexture(index); + break; + + case PPTextureType::SceneDepth: + BindSceneDepthTexture(index); break; } } @@ -935,6 +884,9 @@ void FGLRenderBuffers::RenderEffect(const FString &name) switch (step.Output.Type) { default: + I_FatalError("Unsupported postprocess output type\n"); + break; + case PPTextureType::CurrentPipelineTexture: BindCurrentFB(); break; @@ -946,6 +898,10 @@ void FGLRenderBuffers::RenderEffect(const FString &name) case PPTextureType::PPTexture: GLTextureFBs[step.Output.Texture].Bind(); break; + + case PPTextureType::SceneNormal: + BindSceneFB(false); + break; } // Set blend mode diff --git a/src/gl/renderer/gl_renderbuffers.h b/src/gl/renderer/gl_renderbuffers.h index 5463cde0d..70057e558 100644 --- a/src/gl/renderer/gl_renderbuffers.h +++ b/src/gl/renderer/gl_renderbuffers.h @@ -62,7 +62,7 @@ public: FGLRenderBuffers(); ~FGLRenderBuffers(); - bool Setup(int width, int height, int sceneWidth, int sceneHeight); + void Setup(int width, int height, int sceneWidth, int sceneHeight); void UpdateEffectTextures(); void CompileEffectShaders(); @@ -95,18 +95,6 @@ public: void BindShadowMapFB(); void BindShadowMapTexture(int index); - // Ambient occlusion buffers - PPTexture LinearDepthTexture; - PPFrameBuffer LinearDepthFB; - PPTexture AmbientTexture0; - PPTexture AmbientTexture1; - PPFrameBuffer AmbientFB0; - PPFrameBuffer AmbientFB1; - int AmbientWidth = 0; - int AmbientHeight = 0; - enum { NumAmbientRandomTextures = 3 }; - PPTexture AmbientRandomTexture[NumAmbientRandomTextures]; - int GetWidth() const { return mWidth; } int GetHeight() const { return mHeight; } @@ -117,13 +105,11 @@ private: void ClearScene(); void ClearPipeline(); void ClearEyeBuffers(); - void ClearAmbientOcclusion(); void ClearShadowMap(); void CreateScene(int width, int height, int samples, bool needsSceneTextures); void CreatePipeline(int width, int height); void CreateEyeBuffers(int eye); void CreateShadowMap(); - void CreateAmbientOcclusion(int width, int height); PPTexture Create2DTexture(const char *name, GLuint format, int width, int height, const void *data = nullptr); PPTexture Create2DMultisampleTexture(const char *name, GLuint format, int width, int height, int samples, bool fixedSampleLocations); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 7cb848906..c5d937052 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -50,7 +50,6 @@ #include "gl/renderer/gl_renderbuffers.h" #include "gl/data/gl_vertexbuffer.h" #include "gl/scene/gl_drawinfo.h" -#include "hwrenderer/postprocessing/hw_ambientshader.h" #include "hwrenderer/postprocessing/hw_presentshader.h" #include "hwrenderer/postprocessing/hw_present3dRowshader.h" #include "hwrenderer/postprocessing/hw_shadowmapshader.h" @@ -92,10 +91,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) mPresent3dCheckerShader = nullptr; mPresent3dColumnShader = nullptr; mPresent3dRowShader = nullptr; - mLinearDepthShader = nullptr; - mDepthBlurShader = nullptr; - mSSAOShader = nullptr; - mSSAOCombineShader = nullptr; mShadowMapShader = nullptr; mCustomPostProcessShaders = nullptr; } @@ -105,10 +100,6 @@ void FGLRenderer::Initialize(int width, int height) mScreenBuffers = new FGLRenderBuffers(); mSaveBuffers = new FGLRenderBuffers(); mBuffers = mScreenBuffers; - mLinearDepthShader = new FLinearDepthShader(); - mDepthBlurShader = new FDepthBlurShader(); - mSSAOShader = new FSSAOShader(); - mSSAOCombineShader = new FSSAOCombineShader(); mPresentShader = new FPresentShader(); mPresent3dCheckerShader = new FPresent3DCheckerShader(); mPresent3dColumnShader = new FPresent3DColumnShader(); @@ -156,10 +147,6 @@ FGLRenderer::~FGLRenderer() if (swdrawer) delete swdrawer; if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; - if (mLinearDepthShader) delete mLinearDepthShader; - if (mDepthBlurShader) delete mDepthBlurShader; - if (mSSAOShader) delete mSSAOShader; - if (mSSAOCombineShader) delete mSSAOCombineShader; if (mPresent3dCheckerShader) delete mPresent3dCheckerShader; if (mPresent3dColumnShader) delete mPresent3dColumnShader; if (mPresent3dRowShader) delete mPresent3dRowShader; @@ -355,9 +342,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i void FGLRenderer::BeginFrame() { - buffersActive = mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); - if (buffersActive) - buffersActive = mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); + mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); + mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); } //=========================================================================== @@ -415,10 +401,7 @@ CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE) void FGLRenderer::Draw2D(F2DDrawer *drawer) { twoD.Clock(); - if (buffersActive) - { - mBuffers->BindCurrentFB(); - } + mBuffers->BindCurrentFB(); const auto &mScreenViewport = screen->mScreenViewport; glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 03c75c5d6..6bbd5cc46 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -26,10 +26,6 @@ class FLightBuffer; class FSamplerManager; class DPSprite; class FGLRenderBuffers; -class FLinearDepthShader; -class FDepthBlurShader; -class FSSAOShader; -class FSSAOCombineShader; class FPresentShader; class FPresent3DCheckerShader; class FPresent3DColumnShader; @@ -68,10 +64,6 @@ public: FGLRenderBuffers *mBuffers; FGLRenderBuffers *mScreenBuffers; FGLRenderBuffers *mSaveBuffers; - FLinearDepthShader *mLinearDepthShader; - FSSAOShader *mSSAOShader; - FDepthBlurShader *mDepthBlurShader; - FSSAOCombineShader *mSSAOCombineShader; FPresentShader *mPresentShader; FPresent3DCheckerShader *mPresent3dCheckerShader; FPresent3DColumnShader *mPresent3dColumnShader; @@ -90,8 +82,6 @@ public: FPortalSceneState mPortalState; - bool buffersActive = false; - float mSceneClearColor[3]; FGLRenderer(OpenGLFrameBuffer *fb); @@ -119,7 +109,7 @@ public: sector_t *RenderView(player_t *player); void BeginFrame(); - void Set3DViewport(bool mainview); + void Set3DViewport(); sector_t *RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 942e646ae..4039a3449 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -44,6 +44,7 @@ #include "gl/dynlights/gl_lightbuffer.h" #include "gl_load/gl_interface.h" #include "gl/system/gl_framebuffer.h" +#include "gl/system/gl_debug.h" #include "hwrenderer/utility/hw_cvars.h" #include "gl/renderer/gl_lightdata.h" #include "gl/renderer/gl_renderstate.h" @@ -422,17 +423,8 @@ void FDrawInfo::ProcessScene(bool toscreen) // //----------------------------------------------------------------------------- -void FGLRenderer::Set3DViewport(bool mainview) +void FGLRenderer::Set3DViewport() { - if (mainview && buffersActive) - { - bool useSSAO = (gl_ssao != 0); - mBuffers->BindSceneFB(useSSAO); - gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); - gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); - gl_RenderState.Apply(); - } - // Always clear all buffers with scissor test disabled. // This is faster on newer hardware because it allows the GPU to skip // reading from slower memory where the full buffers are stored. @@ -470,7 +462,19 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came { const auto &eye = vrmode->mEyes[eye_ix]; screen->SetViewportRects(bounds); - Set3DViewport(mainview); + + if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao + { + FGLDebug::PushGroup("MainView"); + + bool useSSAO = (gl_ssao != 0); + mBuffers->BindSceneFB(useSSAO); + gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); + gl_RenderState.EnableDrawBuffers(gl_RenderState.GetPassDrawBufferCount()); + gl_RenderState.Apply(); + } + + Set3DViewport(); FDrawInfo *di = FDrawInfo::StartDrawInfo(mainvp, nullptr); auto &vp = di->Viewpoint; @@ -484,12 +488,22 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees); di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false); - di->ProcessScene(toscreen); if (mainview) { if (toscreen) di->EndDrawScene(mainvp.sector); // do not call this for camera textures. + + if (gl_RenderState.GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers + { + gl_RenderState.SetPassType(NORMAL_PASS); + gl_RenderState.EnableDrawBuffers(1); + } + + mBuffers->BlitSceneToTexture(); // Copy the resulting scene to the current post process texture + + FGLDebug::PopGroup(); // MainView + PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector); }); } di->EndDrawInfo(); diff --git a/src/hwrenderer/postprocessing/hw_ambientshader.cpp b/src/hwrenderer/postprocessing/hw_ambientshader.cpp deleted file mode 100644 index ccbb0f579..000000000 --- a/src/hwrenderer/postprocessing/hw_ambientshader.cpp +++ /dev/null @@ -1,138 +0,0 @@ -// -//--------------------------------------------------------------------------- -// -// Copyright(C) 2016 Magnus Norddahl -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// - -#include "v_video.h" -#include "hwrenderer/utility/hw_cvars.h" -#include "hw_ambientshader.h" - -void FLinearDepthShader::Bind(IRenderQueue *q) -{ - bool multisample = (gl_multisample > 1); - if (mMultisample != multisample) - mShader.reset(); - - if (!mShader) - { - FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc()); - if (multisample) prolog += "#define MULTISAMPLE\n"; - - mShader.reset(screen->CreateShaderProgram()); - mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", prolog, 330); - mShader->Link("shaders/glsl/lineardepth"); - mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms"); - Uniforms.Init(); - mMultisample = multisample; - } - mShader->Bind(q); -} - -void FSSAOShader::Bind(IRenderQueue *q) -{ - bool multisample = (gl_multisample > 1); - if (mCurrentQuality != gl_ssao || mMultisample != multisample) - mShader.reset(); - - if (!mShader) - { - FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc()); - prolog += GetDefines(gl_ssao, multisample); - - mShader.reset(screen->CreateShaderProgram()); - mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/ssao.fp", prolog, 330); - mShader->Link("shaders/glsl/ssao"); - mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms"); - Uniforms.Init(); - mMultisample = multisample; - } - mShader->Bind(q); -} - -FString FSSAOShader::GetDefines(int mode, bool multisample) -{ - // Must match quality values in FGLRenderBuffers::CreateAmbientOcclusion - int numDirections, numSteps; - switch (gl_ssao) - { - default: - case LowQuality: numDirections = 2; numSteps = 4; break; - case MediumQuality: numDirections = 4; numSteps = 4; break; - case HighQuality: numDirections = 8; numSteps = 4; break; - } - - FString defines; - defines.Format(R"( - #define USE_RANDOM_TEXTURE - #define RANDOM_TEXTURE_WIDTH 4.0 - #define NUM_DIRECTIONS %d.0 - #define NUM_STEPS %d.0 - )", numDirections, numSteps); - - if (multisample) - defines += "\n#define MULTISAMPLE\n"; - return defines; -} - -void FDepthBlurShader::Bind(IRenderQueue *q, bool vertical) -{ - auto &shader = mShader[vertical]; - if (!shader) - { - FString prolog = Uniforms[vertical].CreateDeclaration("Uniforms", UniformBlock::Desc()); - if (vertical) - prolog += "#define BLUR_VERTICAL\n"; - else - prolog += "#define BLUR_HORIZONTAL\n"; - - shader.reset(screen->CreateShaderProgram()); - shader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - shader->Compile(IShaderProgram::Fragment, "shaders/glsl/depthblur.fp", prolog, 330); - shader->Link("shaders/glsl/depthblur"); - shader->SetUniformBufferLocation(Uniforms[vertical].BindingPoint(), "Uniforms"); - Uniforms[vertical].Init(); - } - shader->Bind(q); -} - -void FSSAOCombineShader::Bind(IRenderQueue *q) -{ - bool multisample = (gl_multisample > 1); - if (mMultisample != multisample) - mShader.reset(); - - if (!mShader) - { - FString prolog = Uniforms.CreateDeclaration("Uniforms", UniformBlock::Desc()); - if (multisample) - prolog += "#define MULTISAMPLE\n"; - - mShader.reset(screen->CreateShaderProgram()); - mShader->Compile(IShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); - mShader->Compile(IShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", prolog, 330); - mShader->Link("shaders/glsl/ssaocombine"); - mShader->SetUniformBufferLocation(Uniforms.BindingPoint(), "Uniforms"); - Uniforms.Init(); - mMultisample = multisample; - } - mShader->Bind(q); -} diff --git a/src/hwrenderer/postprocessing/hw_ambientshader.h b/src/hwrenderer/postprocessing/hw_ambientshader.h deleted file mode 100644 index aa0ada361..000000000 --- a/src/hwrenderer/postprocessing/hw_ambientshader.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef __GL_AMBIENTSHADER_H -#define __GL_AMBIENTSHADER_H - -#include "hwrenderer/postprocessing/hw_shaderprogram.h" - -class FLinearDepthShader -{ -public: - void Bind(IRenderQueue *q); - - struct UniformBlock - { - int SampleIndex; - float LinearizeDepthA; - float LinearizeDepthB; - float InverseDepthRangeA; - float InverseDepthRangeB; - float Padding0, Padding1, Padding2; - FVector2 Scale; - FVector2 Offset; - - static std::vector Desc() - { - return - { - { "SampleIndex", UniformType::Int, offsetof(UniformBlock, SampleIndex) }, - { "LinearizeDepthA", UniformType::Float, offsetof(UniformBlock, LinearizeDepthA) }, - { "LinearizeDepthB", UniformType::Float, offsetof(UniformBlock, LinearizeDepthB) }, - { "InverseDepthRangeA", UniformType::Float, offsetof(UniformBlock, InverseDepthRangeA) }, - { "InverseDepthRangeB", UniformType::Float, offsetof(UniformBlock, InverseDepthRangeB) }, - { "Padding0", UniformType::Float, offsetof(UniformBlock, Padding0) }, - { "Padding1", UniformType::Float, offsetof(UniformBlock, Padding1) }, - { "Padding2", UniformType::Float, offsetof(UniformBlock, Padding2) }, - { "Scale", UniformType::Vec2, offsetof(UniformBlock, Scale) }, - { "Offset", UniformType::Vec2, offsetof(UniformBlock, Offset) } - }; - } - }; - - ShaderUniforms Uniforms; - -private: - std::unique_ptr mShader; - bool mMultisample = false; -}; - -class FSSAOShader -{ -public: - void Bind(IRenderQueue *q); - - struct UniformBlock - { - FVector2 UVToViewA; - FVector2 UVToViewB; - FVector2 InvFullResolution; - float NDotVBias; - float NegInvR2; - float RadiusToScreen; - float AOMultiplier; - float AOStrength; - int SampleIndex; - float Padding0, Padding1; - FVector2 Scale; - FVector2 Offset; - - static std::vector Desc() - { - return - { - { "UVToViewA", UniformType::Vec2, offsetof(UniformBlock, UVToViewA) }, - { "UVToViewB", UniformType::Vec2, offsetof(UniformBlock, UVToViewB) }, - { "InvFullResolution", UniformType::Vec2, offsetof(UniformBlock, InvFullResolution) }, - { "NDotVBias", UniformType::Float, offsetof(UniformBlock, NDotVBias) }, - { "NegInvR2", UniformType::Float, offsetof(UniformBlock, NegInvR2) }, - { "RadiusToScreen", UniformType::Float, offsetof(UniformBlock, RadiusToScreen) }, - { "AOMultiplier", UniformType::Float, offsetof(UniformBlock, AOMultiplier) }, - { "AOStrength", UniformType::Float, offsetof(UniformBlock, AOStrength) }, - { "SampleIndex", UniformType::Int, offsetof(UniformBlock, SampleIndex) }, - { "Padding0", UniformType::Float, offsetof(UniformBlock, Padding0) }, - { "Padding1", UniformType::Float, offsetof(UniformBlock, Padding1) }, - { "Scale", UniformType::Vec2, offsetof(UniformBlock, Scale) }, - { "Offset", UniformType::Vec2, offsetof(UniformBlock, Offset) }, - }; - } - }; - - ShaderUniforms Uniforms; - -private: - enum Quality - { - Off, - LowQuality, - MediumQuality, - HighQuality, - NumQualityModes - }; - - FString GetDefines(int mode, bool multisample); - - std::unique_ptr mShader; - Quality mCurrentQuality = Off; - bool mMultisample = false; -}; - -class FDepthBlurShader -{ -public: - void Bind(IRenderQueue *q, bool vertical); - - struct UniformBlock - { - float BlurSharpness; - float PowExponent; - FVector2 InvFullResolution; - - static std::vector Desc() - { - return - { - { "BlurSharpness", UniformType::Float, offsetof(UniformBlock, BlurSharpness) }, - { "PowExponent", UniformType::Float, offsetof(UniformBlock, PowExponent) }, - { "InvFullResolution", UniformType::Vec2, offsetof(UniformBlock, InvFullResolution) } - }; - } - }; - - ShaderUniforms Uniforms[2]; - -private: - std::unique_ptr mShader[2]; -}; - -class FSSAOCombineShader -{ -public: - void Bind(IRenderQueue *q); - - struct UniformBlock - { - int SampleCount; - int Padding0, Padding1, Padding2; - FVector2 Scale; - FVector2 Offset; - - static std::vector Desc() - { - return - { - { "SampleCount", UniformType::Int, offsetof(UniformBlock, SampleCount) }, - { "Padding0", UniformType::Int, offsetof(UniformBlock, Padding0) }, - { "Padding1", UniformType::Int, offsetof(UniformBlock, Padding1) }, - { "Padding2", UniformType::Int, offsetof(UniformBlock, Padding2) }, - { "Scale", UniformType::Vec2, offsetof(UniformBlock, Scale) }, - { "Offset", UniformType::Vec2, offsetof(UniformBlock, Offset) } - }; - } - }; - - ShaderUniforms Uniforms; - -private: - std::unique_ptr mShader; - bool mMultisample = false; -}; - -#endif diff --git a/src/hwrenderer/postprocessing/hw_postprocess.cpp b/src/hwrenderer/postprocessing/hw_postprocess.cpp index 86328d836..070251b2a 100644 --- a/src/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/hwrenderer/postprocessing/hw_postprocess.cpp @@ -3,6 +3,7 @@ #include "hw_postprocess.h" #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/postprocessing/hw_postprocess_cvars.h" +#include Postprocess hw_postprocess; @@ -558,8 +559,7 @@ void PPTonemap::UpdateTextures() { if (gl_tonemap == Palette) { - auto &texture = hw_postprocess.Textures["Tonemap.Palette"]; - if (!texture.Data) + if (!hw_postprocess.Textures.CheckKey("Tonemap.Palette")) { std::shared_ptr data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; }); @@ -581,7 +581,7 @@ void PPTonemap::UpdateTextures() } } - texture = { 512, 512, PixelFormat::Rgba8, data }; + hw_postprocess.Textures["Tonemap.Palette"] = { 512, 512, PixelFormat::Rgba8, data }; } } } @@ -618,3 +618,218 @@ void PPTonemap::UpdateSteps() steps.Push(step); hw_postprocess.Effects["TonemapScene"] = steps; } + + +///////////////////////////////////////////////////////////////////////////// + +void PPAmbientOcclusion::DeclareShaders() +{ + // Must match quality values in PPAmbientOcclusion::UpdateTextures + int numDirections, numSteps; + switch (gl_ssao) + { + default: + case LowQuality: numDirections = 2; numSteps = 4; break; + case MediumQuality: numDirections = 4; numSteps = 4; break; + case HighQuality: numDirections = 8; numSteps = 4; break; + } + + FString defines; + defines.Format(R"( + #define USE_RANDOM_TEXTURE + #define RANDOM_TEXTURE_WIDTH 4.0 + #define NUM_DIRECTIONS %d.0 + #define NUM_STEPS %d.0 + )", numDirections, numSteps); + + hw_postprocess.Shaders["SSAO.LinearDepth"] = { "shaders/glsl/lineardepth.fp", "", LinearDepthUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.LinearDepthMS"] = { "shaders/glsl/lineardepth.fp", "#define MULTISAMPLE\n", LinearDepthUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.AmbientOcclude"] = { "shaders/glsl/ssao.fp", defines, SSAOUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.AmbientOccludeMS"] = { "shaders/glsl/ssao.fp", defines + "\n#define MULTISAMPLE\n", SSAOUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.BlurVertical"] = { "shaders/glsl/depthblur.fp", "#define BLUR_VERTICAL\n", DepthBlurUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.BlurHorizontal"] = { "shaders/glsl/depthblur.fp", "#define BLUR_HORIZONTAL\n", DepthBlurUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.Combine"] = { "shaders/glsl/ssaocombine.fp", "", AmbientCombineUniforms::Desc() }; + hw_postprocess.Shaders["SSAO.CombineMS"] = { "shaders/glsl/ssaocombine.fp", "#define MULTISAMPLE\n", AmbientCombineUniforms::Desc() }; +} + +void PPAmbientOcclusion::UpdateTextures() +{ + int width = hw_postprocess.SceneWidth; + int height = hw_postprocess.SceneHeight; + + if (width <= 0 || height <= 0) + return; + + AmbientWidth = (width + 1) / 2; + AmbientHeight = (height + 1) / 2; + + hw_postprocess.Textures["SSAO.LinearDepth"] = { AmbientWidth, AmbientHeight, PixelFormat::R32f }; + hw_postprocess.Textures["SSAO.Ambient0"] = { AmbientWidth, AmbientHeight, PixelFormat::Rg16f }; + hw_postprocess.Textures["SSAO.Ambient1"] = { AmbientWidth, AmbientHeight, PixelFormat::Rg16f }; + + // We only need to create the random texture once + if (!hw_postprocess.Textures.CheckKey("SSAO.Random0")) + { + // Must match quality enum in PPAmbientOcclusion::DeclareShaders + double numDirections[NumAmbientRandomTextures] = { 2.0, 4.0, 8.0 }; + + std::mt19937 generator(1337); + std::uniform_real_distribution distribution(0.0, 1.0); + for (int quality = 0; quality < NumAmbientRandomTextures; quality++) + { + std::shared_ptr data(new int16_t[16 * 4], [](void *p) { delete[](int16_t*)p; }); + int16_t *randomValues = (int16_t *)data.get(); + + for (int i = 0; i < 16; i++) + { + double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality]; + double x = cos(angle); + double y = sin(angle); + double z = distribution(generator); + double w = distribution(generator); + + randomValues[i * 4 + 0] = (int16_t)clamp(x * 32767.0, -32768.0, 32767.0); + randomValues[i * 4 + 1] = (int16_t)clamp(y * 32767.0, -32768.0, 32767.0); + randomValues[i * 4 + 2] = (int16_t)clamp(z * 32767.0, -32768.0, 32767.0); + randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0); + } + + FString name; + name.Format("SSAO.Random%d", quality); + + hw_postprocess.Textures[name] = { 4, 4, PixelFormat::Rgba16_snorm, data }; + AmbientRandomTexture[quality] = name; + } + } +} + +void PPAmbientOcclusion::UpdateSteps() +{ + if (gl_ssao == 0 || hw_postprocess.SceneWidth == 0 || hw_postprocess.SceneHeight == 0) + { + hw_postprocess.Effects["AmbientOccludeScene"] = {}; + return; + } + + float bias = gl_ssao_bias; + float aoRadius = gl_ssao_radius; + const float blurAmount = gl_ssao_blur; + float aoStrength = gl_ssao_strength; + + //float tanHalfFovy = tan(fovy * (M_PI / 360.0f)); + float tanHalfFovy = 1.0f / hw_postprocess.m5; + float invFocalLenX = tanHalfFovy * (hw_postprocess.SceneWidth / (float)hw_postprocess.SceneHeight); + float invFocalLenY = tanHalfFovy; + float nDotVBias = clamp(bias, 0.0f, 1.0f); + float r2 = aoRadius * aoRadius; + + float blurSharpness = 1.0f / blurAmount; + + auto sceneScale = screen->SceneScale(); + auto sceneOffset = screen->SceneOffset(); + + int randomTexture = clamp(gl_ssao - 1, 0, NumAmbientRandomTextures - 1); + + LinearDepthUniforms linearUniforms; + linearUniforms.SampleIndex = 0; + linearUniforms.LinearizeDepthA = 1.0f / screen->GetZFar() - 1.0f / screen->GetZNear(); + linearUniforms.LinearizeDepthB = MAX(1.0f / screen->GetZNear(), 1.e-8f); + linearUniforms.InverseDepthRangeA = 1.0f; + linearUniforms.InverseDepthRangeB = 0.0f; + linearUniforms.Scale = sceneScale; + linearUniforms.Offset = sceneOffset; + + SSAOUniforms ssaoUniforms; + ssaoUniforms.SampleIndex = 0; + ssaoUniforms.UVToViewA = { 2.0f * invFocalLenX, 2.0f * invFocalLenY }; + ssaoUniforms.UVToViewB = { -invFocalLenX, -invFocalLenY }; + ssaoUniforms.InvFullResolution = { 1.0f / AmbientWidth, 1.0f / AmbientHeight }; + ssaoUniforms.NDotVBias = nDotVBias; + ssaoUniforms.NegInvR2 = -1.0f / r2; + ssaoUniforms.RadiusToScreen = aoRadius * 0.5f / tanHalfFovy * AmbientHeight; + ssaoUniforms.AOMultiplier = 1.0f / (1.0f - nDotVBias); + ssaoUniforms.AOStrength = aoStrength; + ssaoUniforms.Scale = sceneScale; + ssaoUniforms.Offset = sceneOffset; + + DepthBlurUniforms blurUniforms; + blurUniforms.BlurSharpness = blurSharpness; + blurUniforms.InvFullResolution = { 1.0f / AmbientWidth, 1.0f / AmbientHeight }; + blurUniforms.PowExponent = gl_ssao_exponent; + + AmbientCombineUniforms combineUniforms; + combineUniforms.SampleCount = gl_multisample; + combineUniforms.Scale = screen->SceneScale(); + combineUniforms.Offset = screen->SceneOffset(); + + IntRect ambientViewport; + ambientViewport.left = 0; + ambientViewport.top = 0; + ambientViewport.width = AmbientWidth; + ambientViewport.height = AmbientHeight; + + TArray steps; + + // Calculate linear depth values + { + PPStep step; + step.ShaderName = gl_multisample ? "SSAO.LinearDepthMS" : "SSAO.LinearDepth"; + step.Uniforms.Set(linearUniforms); + step.Viewport = ambientViewport; + step.SetInputSceneDepth(0); + step.SetInputSceneColor(1); + step.SetOutputTexture("SSAO.LinearDepth"); + step.SetNoBlend(); + steps.Push(step); + } + + // Apply ambient occlusion + { + PPStep step; + step.ShaderName = gl_multisample ? "SSAO.AmbientOccludeMS" : "SSAO.AmbientOcclude"; + step.Uniforms.Set(ssaoUniforms); + step.Viewport = ambientViewport; + step.SetInputTexture(0, "SSAO.LinearDepth"); + step.SetInputSceneNormal(1); + step.SetInputTexture(2, AmbientRandomTexture[randomTexture], PPFilterMode::Nearest, PPWrapMode::Repeat); + step.SetOutputTexture("SSAO.Ambient0"); + step.SetNoBlend(); + steps.Push(step); + } + + // Blur SSAO texture + if (gl_ssao_debug < 2) + { + PPStep step; + step.ShaderName = "SSAO.BlurHorizontal"; + step.Uniforms.Set(blurUniforms); + step.Viewport = ambientViewport; + step.SetInputTexture(0, "SSAO.Ambient0"); + step.SetOutputTexture("SSAO.Ambient1"); + step.SetNoBlend(); + steps.Push(step); + + step.ShaderName = "SSAO.BlurVertical"; + step.SetInputTexture(0, "SSAO.Ambient1"); + step.SetOutputTexture("SSAO.Ambient0"); + steps.Push(step); + } + + // Add SSAO back to scene texture: + { + PPStep step; + step.ShaderName = gl_multisample ? "SSAO.CombineMS" : "SSAO.Combine"; + step.Uniforms.Set(combineUniforms); + step.Viewport = screen->mSceneViewport; + step.SetInputTexture(0, "SSAO.Ambient0", PPFilterMode::Linear); + step.SetInputSceneFog(1); + step.SetOutputSceneColor(); + if (gl_ssao_debug != 0) + step.SetNoBlend(); + else + step.SetAlphaBlend(); + steps.Push(step); + } + + hw_postprocess.Effects["AmbientOccludeScene"] = steps; +} diff --git a/src/hwrenderer/postprocessing/hw_postprocess.h b/src/hwrenderer/postprocessing/hw_postprocess.h index 1708a86b4..55e23150a 100644 --- a/src/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/hwrenderer/postprocessing/hw_postprocess.h @@ -10,12 +10,14 @@ typedef FRenderStyle PPBlendMode; typedef IntRect PPViewport; enum class PPFilterMode { Nearest, Linear }; -enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture }; +enum class PPWrapMode { Clamp, Repeat }; +enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth }; class PPTextureInput { public: PPFilterMode Filter; + PPWrapMode Wrap; PPTextureType Type; PPTextureName Texture; }; @@ -99,23 +101,50 @@ public: class PPStep { public: - void SetInputTexture(int index, PPTextureName texture, PPFilterMode filter = PPFilterMode::Nearest) + void SetInputTexture(int index, PPTextureName texture, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) { if ((int)Textures.Size() < index + 1) Textures.Resize(index + 1); auto &tex = Textures[index]; tex.Filter = filter; + tex.Wrap = wrap; tex.Type = PPTextureType::PPTexture; tex.Texture = texture; } - void SetInputCurrent(int index, PPFilterMode filter = PPFilterMode::Nearest) + void SetInputCurrent(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) + { + SetInputSpecialType(index, PPTextureType::CurrentPipelineTexture, filter, wrap); + } + + void SetInputSceneColor(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) + { + SetInputSpecialType(index, PPTextureType::SceneColor, filter, wrap); + } + + void SetInputSceneFog(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) + { + SetInputSpecialType(index, PPTextureType::SceneFog, filter, wrap); + } + + void SetInputSceneNormal(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) + { + SetInputSpecialType(index, PPTextureType::SceneNormal, filter, wrap); + } + + void SetInputSceneDepth(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) + { + SetInputSpecialType(index, PPTextureType::SceneDepth, filter, wrap); + } + + void SetInputSpecialType(int index, PPTextureType type, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp) { if ((int)Textures.Size() < index + 1) Textures.Resize(index + 1); auto &tex = Textures[index]; tex.Filter = filter; - tex.Type = PPTextureType::CurrentPipelineTexture; + tex.Wrap = wrap; + tex.Type = type; tex.Texture = {}; } @@ -137,6 +166,12 @@ public: Output.Texture = {}; } + void SetOutputSceneColor() + { + Output.Type = PPTextureType::SceneColor; + Output.Texture = {}; + } + void SetNoBlend() { BlendMode.BlendOp = STYLEOP_Add; @@ -173,7 +208,9 @@ enum class PixelFormat { Rgba8, Rgba16f, - R32f + R32f, + Rg16f, + Rgba16_snorm }; class PPTextureDesc @@ -221,8 +258,9 @@ public: int SceneWidth = 0; int SceneHeight = 0; - int fixedcm; - float gameinfobluramount; + int fixedcm = 0; + float gameinfobluramount = 0.0f; + float m5 = 0.0f; TMap> Effects; TMap Textures; @@ -457,3 +495,132 @@ public: NumTonemapModes }; }; + +///////////////////////////////////////////////////////////////////////////// + +struct LinearDepthUniforms +{ + int SampleIndex; + float LinearizeDepthA; + float LinearizeDepthB; + float InverseDepthRangeA; + float InverseDepthRangeB; + float Padding0, Padding1, Padding2; + FVector2 Scale; + FVector2 Offset; + + static std::vector Desc() + { + return + { + { "SampleIndex", UniformType::Int, offsetof(LinearDepthUniforms, SampleIndex) }, + { "LinearizeDepthA", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthA) }, + { "LinearizeDepthB", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthB) }, + { "InverseDepthRangeA", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeA) }, + { "InverseDepthRangeB", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeB) }, + { "Padding0", UniformType::Float, offsetof(LinearDepthUniforms, Padding0) }, + { "Padding1", UniformType::Float, offsetof(LinearDepthUniforms, Padding1) }, + { "Padding2", UniformType::Float, offsetof(LinearDepthUniforms, Padding2) }, + { "Scale", UniformType::Vec2, offsetof(LinearDepthUniforms, Scale) }, + { "Offset", UniformType::Vec2, offsetof(LinearDepthUniforms, Offset) } + }; + } +}; + +struct SSAOUniforms +{ + FVector2 UVToViewA; + FVector2 UVToViewB; + FVector2 InvFullResolution; + float NDotVBias; + float NegInvR2; + float RadiusToScreen; + float AOMultiplier; + float AOStrength; + int SampleIndex; + float Padding0, Padding1; + FVector2 Scale; + FVector2 Offset; + + static std::vector Desc() + { + return + { + { "UVToViewA", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewA) }, + { "UVToViewB", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewB) }, + { "InvFullResolution", UniformType::Vec2, offsetof(SSAOUniforms, InvFullResolution) }, + { "NDotVBias", UniformType::Float, offsetof(SSAOUniforms, NDotVBias) }, + { "NegInvR2", UniformType::Float, offsetof(SSAOUniforms, NegInvR2) }, + { "RadiusToScreen", UniformType::Float, offsetof(SSAOUniforms, RadiusToScreen) }, + { "AOMultiplier", UniformType::Float, offsetof(SSAOUniforms, AOMultiplier) }, + { "AOStrength", UniformType::Float, offsetof(SSAOUniforms, AOStrength) }, + { "SampleIndex", UniformType::Int, offsetof(SSAOUniforms, SampleIndex) }, + { "Padding0", UniformType::Float, offsetof(SSAOUniforms, Padding0) }, + { "Padding1", UniformType::Float, offsetof(SSAOUniforms, Padding1) }, + { "Scale", UniformType::Vec2, offsetof(SSAOUniforms, Scale) }, + { "Offset", UniformType::Vec2, offsetof(SSAOUniforms, Offset) }, + }; + } +}; + +struct DepthBlurUniforms +{ + float BlurSharpness; + float PowExponent; + FVector2 InvFullResolution; + + static std::vector Desc() + { + return + { + { "BlurSharpness", UniformType::Float, offsetof(DepthBlurUniforms, BlurSharpness) }, + { "PowExponent", UniformType::Float, offsetof(DepthBlurUniforms, PowExponent) }, + { "InvFullResolution", UniformType::Vec2, offsetof(DepthBlurUniforms, InvFullResolution) } + }; + } +}; + +struct AmbientCombineUniforms +{ + int SampleCount; + int Padding0, Padding1, Padding2; + FVector2 Scale; + FVector2 Offset; + + static std::vector Desc() + { + return + { + { "SampleCount", UniformType::Int, offsetof(AmbientCombineUniforms, SampleCount) }, + { "Padding0", UniformType::Int, offsetof(AmbientCombineUniforms, Padding0) }, + { "Padding1", UniformType::Int, offsetof(AmbientCombineUniforms, Padding1) }, + { "Padding2", UniformType::Int, offsetof(AmbientCombineUniforms, Padding2) }, + { "Scale", UniformType::Vec2, offsetof(AmbientCombineUniforms, Scale) }, + { "Offset", UniformType::Vec2, offsetof(AmbientCombineUniforms, Offset) } + }; + } +}; + +class PPAmbientOcclusion : public PPEffectManager +{ +public: + void DeclareShaders() override; + void UpdateTextures() override; + void UpdateSteps() override; + +private: + enum Quality + { + Off, + LowQuality, + MediumQuality, + HighQuality, + NumQualityModes + }; + + int AmbientWidth = 0; + int AmbientHeight = 0; + + enum { NumAmbientRandomTextures = 3 }; + PPTextureName AmbientRandomTexture[NumAmbientRandomTextures]; +};