mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-13 07:57:52 +00:00
- convert the SSAO pass to use hw_postprocess
This commit is contained in:
parent
ecb5d69ae3
commit
35c13763db
11 changed files with 464 additions and 553 deletions
|
@ -1075,7 +1075,6 @@ set (PCH_SOURCES
|
||||||
hwrenderer/postprocessing/hw_shadowmapshader.cpp
|
hwrenderer/postprocessing/hw_shadowmapshader.cpp
|
||||||
hwrenderer/postprocessing/hw_presentshader.cpp
|
hwrenderer/postprocessing/hw_presentshader.cpp
|
||||||
hwrenderer/postprocessing/hw_present3dRowshader.cpp
|
hwrenderer/postprocessing/hw_present3dRowshader.cpp
|
||||||
hwrenderer/postprocessing/hw_ambientshader.cpp
|
|
||||||
hwrenderer/textures/hw_material.cpp
|
hwrenderer/textures/hw_material.cpp
|
||||||
hwrenderer/textures/hw_precache.cpp
|
hwrenderer/textures/hw_precache.cpp
|
||||||
hwrenderer/utility/hw_clock.cpp
|
hwrenderer/utility/hw_clock.cpp
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#include "gl/renderer/gl_renderer.h"
|
#include "gl/renderer/gl_renderer.h"
|
||||||
#include "gl/renderer/gl_postprocessstate.h"
|
#include "gl/renderer/gl_postprocessstate.h"
|
||||||
#include "gl/data/gl_vertexbuffer.h"
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
#include "hwrenderer/postprocessing/hw_ambientshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||||
|
@ -65,8 +64,6 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &aft
|
||||||
hw_postprocess.UpdateTextures();
|
hw_postprocess.UpdateTextures();
|
||||||
hw_postprocess.UpdateSteps();
|
hw_postprocess.UpdateSteps();
|
||||||
|
|
||||||
mBuffers->BlitSceneToTexture();
|
|
||||||
|
|
||||||
mBuffers->CompileEffectShaders();
|
mBuffers->CompileEffectShaders();
|
||||||
mBuffers->UpdateEffectTextures();
|
mBuffers->UpdateEffectTextures();
|
||||||
|
|
||||||
|
@ -90,108 +87,18 @@ void FGLRenderer::PostProcessScene(int fixedcm, const std::function<void()> &aft
|
||||||
|
|
||||||
void FGLRenderer::AmbientOccludeScene(float m5)
|
void FGLRenderer::AmbientOccludeScene(float m5)
|
||||||
{
|
{
|
||||||
FGLDebug::PushGroup("AmbientOccludeScene");
|
hw_postprocess.SceneWidth = mBuffers->GetSceneWidth();
|
||||||
|
hw_postprocess.SceneHeight = mBuffers->GetSceneHeight();
|
||||||
|
hw_postprocess.m5 = m5;
|
||||||
|
|
||||||
FGLPostProcessState savedState;
|
hw_postprocess.DeclareShaders();
|
||||||
savedState.SaveTextureBindings(3);
|
hw_postprocess.UpdateTextures();
|
||||||
|
hw_postprocess.UpdateSteps();
|
||||||
|
|
||||||
float bias = gl_ssao_bias;
|
mBuffers->CompileEffectShaders();
|
||||||
float aoRadius = gl_ssao_radius;
|
mBuffers->UpdateEffectTextures();
|
||||||
const float blurAmount = gl_ssao_blur;
|
|
||||||
float aoStrength = gl_ssao_strength;
|
|
||||||
|
|
||||||
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
|
mBuffers->RenderEffect("AmbientOccludeScene");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderer::BlurScene(float gameinfobluramount)
|
void FGLRenderer::BlurScene(float gameinfobluramount)
|
||||||
|
|
|
@ -60,7 +60,6 @@ FGLRenderBuffers::~FGLRenderBuffers()
|
||||||
ClearScene();
|
ClearScene();
|
||||||
ClearPipeline();
|
ClearPipeline();
|
||||||
ClearEyeBuffers();
|
ClearEyeBuffers();
|
||||||
ClearAmbientOcclusion();
|
|
||||||
ClearShadowMap();
|
ClearShadowMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,18 +104,6 @@ void FGLRenderBuffers::ClearEyeBuffers()
|
||||||
mEyeFBs.Clear();
|
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)
|
void FGLRenderBuffers::DeleteTexture(PPTexture &tex)
|
||||||
{
|
{
|
||||||
if (tex.handle != 0)
|
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)
|
if (width <= 0 || height <= 0)
|
||||||
I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height);
|
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;
|
mHeight = height;
|
||||||
mSamples = samples;
|
mSamples = samples;
|
||||||
mSceneUsesTextures = needsSceneTextures;
|
mSceneUsesTextures = needsSceneTextures;
|
||||||
|
mSceneWidth = sceneWidth;
|
||||||
// Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts
|
mSceneHeight = sceneHeight;
|
||||||
if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight)
|
|
||||||
{
|
|
||||||
CreateAmbientOcclusion(sceneWidth, sceneHeight);
|
|
||||||
mSceneWidth = sceneWidth;
|
|
||||||
mSceneHeight = sceneHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, textureBinding);
|
glBindTexture(GL_TEXTURE_2D, textureBinding);
|
||||||
glActiveTexture(activeTex);
|
glActiveTexture(activeTex);
|
||||||
|
@ -195,8 +176,6 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
mSceneHeight = 0;
|
mSceneHeight = 0;
|
||||||
I_FatalError("Unable to create render buffers.");
|
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<double> 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
|
// 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::Rgba8: glformat = GL_RGBA8; break;
|
||||||
case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break;
|
case PixelFormat::Rgba16f: glformat = GL_RGBA16F; break;
|
||||||
case PixelFormat::R32f: glformat = GL_R32F; 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))
|
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];
|
const PPTextureInput &input = step.Textures[index];
|
||||||
int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR;
|
int filter = (input.Filter == PPFilterMode::Nearest) ? GL_NEAREST : GL_LINEAR;
|
||||||
|
int wrap = (input.Wrap == PPWrapMode::Clamp) ? GL_CLAMP : GL_REPEAT;
|
||||||
|
|
||||||
switch (input.Type)
|
switch (input.Type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case PPTextureType::CurrentPipelineTexture:
|
case PPTextureType::CurrentPipelineTexture:
|
||||||
BindCurrentTexture(index, filter);
|
BindCurrentTexture(index, filter, wrap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPTextureType::NextPipelineTexture:
|
case PPTextureType::NextPipelineTexture:
|
||||||
|
@ -926,7 +859,23 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PPTextureType::PPTexture:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -935,6 +884,9 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
||||||
switch (step.Output.Type)
|
switch (step.Output.Type)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
I_FatalError("Unsupported postprocess output type\n");
|
||||||
|
break;
|
||||||
|
|
||||||
case PPTextureType::CurrentPipelineTexture:
|
case PPTextureType::CurrentPipelineTexture:
|
||||||
BindCurrentFB();
|
BindCurrentFB();
|
||||||
break;
|
break;
|
||||||
|
@ -946,6 +898,10 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
||||||
case PPTextureType::PPTexture:
|
case PPTextureType::PPTexture:
|
||||||
GLTextureFBs[step.Output.Texture].Bind();
|
GLTextureFBs[step.Output.Texture].Bind();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PPTextureType::SceneNormal:
|
||||||
|
BindSceneFB(false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set blend mode
|
// Set blend mode
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
FGLRenderBuffers();
|
FGLRenderBuffers();
|
||||||
~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 UpdateEffectTextures();
|
||||||
void CompileEffectShaders();
|
void CompileEffectShaders();
|
||||||
|
@ -95,18 +95,6 @@ public:
|
||||||
void BindShadowMapFB();
|
void BindShadowMapFB();
|
||||||
void BindShadowMapTexture(int index);
|
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 GetWidth() const { return mWidth; }
|
||||||
int GetHeight() const { return mHeight; }
|
int GetHeight() const { return mHeight; }
|
||||||
|
|
||||||
|
@ -117,13 +105,11 @@ private:
|
||||||
void ClearScene();
|
void ClearScene();
|
||||||
void ClearPipeline();
|
void ClearPipeline();
|
||||||
void ClearEyeBuffers();
|
void ClearEyeBuffers();
|
||||||
void ClearAmbientOcclusion();
|
|
||||||
void ClearShadowMap();
|
void ClearShadowMap();
|
||||||
void CreateScene(int width, int height, int samples, bool needsSceneTextures);
|
void CreateScene(int width, int height, int samples, bool needsSceneTextures);
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateEyeBuffers(int eye);
|
void CreateEyeBuffers(int eye);
|
||||||
void CreateShadowMap();
|
void CreateShadowMap();
|
||||||
void CreateAmbientOcclusion(int width, int height);
|
|
||||||
|
|
||||||
PPTexture Create2DTexture(const char *name, GLuint format, int width, int height, const void *data = nullptr);
|
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);
|
PPTexture Create2DMultisampleTexture(const char *name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
|
||||||
|
|
|
@ -50,7 +50,6 @@
|
||||||
#include "gl/renderer/gl_renderbuffers.h"
|
#include "gl/renderer/gl_renderbuffers.h"
|
||||||
#include "gl/data/gl_vertexbuffer.h"
|
#include "gl/data/gl_vertexbuffer.h"
|
||||||
#include "gl/scene/gl_drawinfo.h"
|
#include "gl/scene/gl_drawinfo.h"
|
||||||
#include "hwrenderer/postprocessing/hw_ambientshader.h"
|
|
||||||
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
#include "hwrenderer/postprocessing/hw_presentshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
|
#include "hwrenderer/postprocessing/hw_present3dRowshader.h"
|
||||||
#include "hwrenderer/postprocessing/hw_shadowmapshader.h"
|
#include "hwrenderer/postprocessing/hw_shadowmapshader.h"
|
||||||
|
@ -92,10 +91,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
||||||
mPresent3dCheckerShader = nullptr;
|
mPresent3dCheckerShader = nullptr;
|
||||||
mPresent3dColumnShader = nullptr;
|
mPresent3dColumnShader = nullptr;
|
||||||
mPresent3dRowShader = nullptr;
|
mPresent3dRowShader = nullptr;
|
||||||
mLinearDepthShader = nullptr;
|
|
||||||
mDepthBlurShader = nullptr;
|
|
||||||
mSSAOShader = nullptr;
|
|
||||||
mSSAOCombineShader = nullptr;
|
|
||||||
mShadowMapShader = nullptr;
|
mShadowMapShader = nullptr;
|
||||||
mCustomPostProcessShaders = nullptr;
|
mCustomPostProcessShaders = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -105,10 +100,6 @@ void FGLRenderer::Initialize(int width, int height)
|
||||||
mScreenBuffers = new FGLRenderBuffers();
|
mScreenBuffers = new FGLRenderBuffers();
|
||||||
mSaveBuffers = new FGLRenderBuffers();
|
mSaveBuffers = new FGLRenderBuffers();
|
||||||
mBuffers = mScreenBuffers;
|
mBuffers = mScreenBuffers;
|
||||||
mLinearDepthShader = new FLinearDepthShader();
|
|
||||||
mDepthBlurShader = new FDepthBlurShader();
|
|
||||||
mSSAOShader = new FSSAOShader();
|
|
||||||
mSSAOCombineShader = new FSSAOCombineShader();
|
|
||||||
mPresentShader = new FPresentShader();
|
mPresentShader = new FPresentShader();
|
||||||
mPresent3dCheckerShader = new FPresent3DCheckerShader();
|
mPresent3dCheckerShader = new FPresent3DCheckerShader();
|
||||||
mPresent3dColumnShader = new FPresent3DColumnShader();
|
mPresent3dColumnShader = new FPresent3DColumnShader();
|
||||||
|
@ -156,10 +147,6 @@ FGLRenderer::~FGLRenderer()
|
||||||
if (swdrawer) delete swdrawer;
|
if (swdrawer) delete swdrawer;
|
||||||
if (mBuffers) delete mBuffers;
|
if (mBuffers) delete mBuffers;
|
||||||
if (mPresentShader) delete mPresentShader;
|
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 (mPresent3dCheckerShader) delete mPresent3dCheckerShader;
|
||||||
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
|
if (mPresent3dColumnShader) delete mPresent3dColumnShader;
|
||||||
if (mPresent3dRowShader) delete mPresent3dRowShader;
|
if (mPresent3dRowShader) delete mPresent3dRowShader;
|
||||||
|
@ -355,9 +342,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
|
||||||
|
|
||||||
void FGLRenderer::BeginFrame()
|
void FGLRenderer::BeginFrame()
|
||||||
{
|
{
|
||||||
buffersActive = mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height);
|
||||||
if (buffersActive)
|
mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
||||||
buffersActive = mSaveBuffers->Setup(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -415,10 +401,7 @@ CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE)
|
||||||
void FGLRenderer::Draw2D(F2DDrawer *drawer)
|
void FGLRenderer::Draw2D(F2DDrawer *drawer)
|
||||||
{
|
{
|
||||||
twoD.Clock();
|
twoD.Clock();
|
||||||
if (buffersActive)
|
mBuffers->BindCurrentFB();
|
||||||
{
|
|
||||||
mBuffers->BindCurrentFB();
|
|
||||||
}
|
|
||||||
const auto &mScreenViewport = screen->mScreenViewport;
|
const auto &mScreenViewport = screen->mScreenViewport;
|
||||||
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,6 @@ class FLightBuffer;
|
||||||
class FSamplerManager;
|
class FSamplerManager;
|
||||||
class DPSprite;
|
class DPSprite;
|
||||||
class FGLRenderBuffers;
|
class FGLRenderBuffers;
|
||||||
class FLinearDepthShader;
|
|
||||||
class FDepthBlurShader;
|
|
||||||
class FSSAOShader;
|
|
||||||
class FSSAOCombineShader;
|
|
||||||
class FPresentShader;
|
class FPresentShader;
|
||||||
class FPresent3DCheckerShader;
|
class FPresent3DCheckerShader;
|
||||||
class FPresent3DColumnShader;
|
class FPresent3DColumnShader;
|
||||||
|
@ -68,10 +64,6 @@ public:
|
||||||
FGLRenderBuffers *mBuffers;
|
FGLRenderBuffers *mBuffers;
|
||||||
FGLRenderBuffers *mScreenBuffers;
|
FGLRenderBuffers *mScreenBuffers;
|
||||||
FGLRenderBuffers *mSaveBuffers;
|
FGLRenderBuffers *mSaveBuffers;
|
||||||
FLinearDepthShader *mLinearDepthShader;
|
|
||||||
FSSAOShader *mSSAOShader;
|
|
||||||
FDepthBlurShader *mDepthBlurShader;
|
|
||||||
FSSAOCombineShader *mSSAOCombineShader;
|
|
||||||
FPresentShader *mPresentShader;
|
FPresentShader *mPresentShader;
|
||||||
FPresent3DCheckerShader *mPresent3dCheckerShader;
|
FPresent3DCheckerShader *mPresent3dCheckerShader;
|
||||||
FPresent3DColumnShader *mPresent3dColumnShader;
|
FPresent3DColumnShader *mPresent3dColumnShader;
|
||||||
|
@ -90,8 +82,6 @@ public:
|
||||||
|
|
||||||
FPortalSceneState mPortalState;
|
FPortalSceneState mPortalState;
|
||||||
|
|
||||||
bool buffersActive = false;
|
|
||||||
|
|
||||||
float mSceneClearColor[3];
|
float mSceneClearColor[3];
|
||||||
|
|
||||||
FGLRenderer(OpenGLFrameBuffer *fb);
|
FGLRenderer(OpenGLFrameBuffer *fb);
|
||||||
|
@ -119,7 +109,7 @@ public:
|
||||||
sector_t *RenderView(player_t *player);
|
sector_t *RenderView(player_t *player);
|
||||||
void BeginFrame();
|
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);
|
sector_t *RenderViewpoint (FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "gl/dynlights/gl_lightbuffer.h"
|
#include "gl/dynlights/gl_lightbuffer.h"
|
||||||
#include "gl_load/gl_interface.h"
|
#include "gl_load/gl_interface.h"
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
|
#include "gl/system/gl_debug.h"
|
||||||
#include "hwrenderer/utility/hw_cvars.h"
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
#include "gl/renderer/gl_lightdata.h"
|
#include "gl/renderer/gl_lightdata.h"
|
||||||
#include "gl/renderer/gl_renderstate.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.
|
// Always clear all buffers with scissor test disabled.
|
||||||
// This is faster on newer hardware because it allows the GPU to skip
|
// This is faster on newer hardware because it allows the GPU to skip
|
||||||
// reading from slower memory where the full buffers are stored.
|
// 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];
|
const auto &eye = vrmode->mEyes[eye_ix];
|
||||||
screen->SetViewportRects(bounds);
|
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);
|
FDrawInfo *di = FDrawInfo::StartDrawInfo(mainvp, nullptr);
|
||||||
auto &vp = di->Viewpoint;
|
auto &vp = di->Viewpoint;
|
||||||
|
@ -484,12 +488,22 @@ sector_t * FGLRenderer::RenderViewpoint (FRenderViewpoint &mainvp, AActor * came
|
||||||
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees);
|
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees);
|
||||||
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
di->SetupView(vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
||||||
|
|
||||||
|
|
||||||
di->ProcessScene(toscreen);
|
di->ProcessScene(toscreen);
|
||||||
|
|
||||||
if (mainview)
|
if (mainview)
|
||||||
{
|
{
|
||||||
if (toscreen) di->EndDrawScene(mainvp.sector); // do not call this for camera textures.
|
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); });
|
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector); });
|
||||||
}
|
}
|
||||||
di->EndDrawInfo();
|
di->EndDrawInfo();
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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<UniformFieldDesc> 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<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> 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<UniformFieldDesc> 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<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum Quality
|
|
||||||
{
|
|
||||||
Off,
|
|
||||||
LowQuality,
|
|
||||||
MediumQuality,
|
|
||||||
HighQuality,
|
|
||||||
NumQualityModes
|
|
||||||
};
|
|
||||||
|
|
||||||
FString GetDefines(int mode, bool multisample);
|
|
||||||
|
|
||||||
std::unique_ptr<IShaderProgram> 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<UniformFieldDesc> Desc()
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{ "BlurSharpness", UniformType::Float, offsetof(UniformBlock, BlurSharpness) },
|
|
||||||
{ "PowExponent", UniformType::Float, offsetof(UniformBlock, PowExponent) },
|
|
||||||
{ "InvFullResolution", UniformType::Vec2, offsetof(UniformBlock, InvFullResolution) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ShaderUniforms<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms[2];
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
class FSSAOCombineShader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Bind(IRenderQueue *q);
|
|
||||||
|
|
||||||
struct UniformBlock
|
|
||||||
{
|
|
||||||
int SampleCount;
|
|
||||||
int Padding0, Padding1, Padding2;
|
|
||||||
FVector2 Scale;
|
|
||||||
FVector2 Offset;
|
|
||||||
|
|
||||||
static std::vector<UniformFieldDesc> 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<UniformBlock, POSTPROCESS_BINDINGPOINT> Uniforms;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<IShaderProgram> mShader;
|
|
||||||
bool mMultisample = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "hw_postprocess.h"
|
#include "hw_postprocess.h"
|
||||||
#include "hwrenderer/utility/hw_cvars.h"
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
#include "hwrenderer/postprocessing/hw_postprocess_cvars.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
Postprocess hw_postprocess;
|
Postprocess hw_postprocess;
|
||||||
|
|
||||||
|
@ -558,8 +559,7 @@ void PPTonemap::UpdateTextures()
|
||||||
{
|
{
|
||||||
if (gl_tonemap == Palette)
|
if (gl_tonemap == Palette)
|
||||||
{
|
{
|
||||||
auto &texture = hw_postprocess.Textures["Tonemap.Palette"];
|
if (!hw_postprocess.Textures.CheckKey("Tonemap.Palette"))
|
||||||
if (!texture.Data)
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<void> data(new uint32_t[512 * 512], [](void *p) { delete[](uint32_t*)p; });
|
std::shared_ptr<void> 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);
|
steps.Push(step);
|
||||||
hw_postprocess.Effects["TonemapScene"] = steps;
|
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<double> distribution(0.0, 1.0);
|
||||||
|
for (int quality = 0; quality < NumAmbientRandomTextures; quality++)
|
||||||
|
{
|
||||||
|
std::shared_ptr<void> 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<PPStep> 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;
|
||||||
|
}
|
||||||
|
|
|
@ -10,12 +10,14 @@ typedef FRenderStyle PPBlendMode;
|
||||||
typedef IntRect PPViewport;
|
typedef IntRect PPViewport;
|
||||||
|
|
||||||
enum class PPFilterMode { Nearest, Linear };
|
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
|
class PPTextureInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PPFilterMode Filter;
|
PPFilterMode Filter;
|
||||||
|
PPWrapMode Wrap;
|
||||||
PPTextureType Type;
|
PPTextureType Type;
|
||||||
PPTextureName Texture;
|
PPTextureName Texture;
|
||||||
};
|
};
|
||||||
|
@ -99,23 +101,50 @@ public:
|
||||||
class PPStep
|
class PPStep
|
||||||
{
|
{
|
||||||
public:
|
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)
|
if ((int)Textures.Size() < index + 1)
|
||||||
Textures.Resize(index + 1);
|
Textures.Resize(index + 1);
|
||||||
auto &tex = Textures[index];
|
auto &tex = Textures[index];
|
||||||
tex.Filter = filter;
|
tex.Filter = filter;
|
||||||
|
tex.Wrap = wrap;
|
||||||
tex.Type = PPTextureType::PPTexture;
|
tex.Type = PPTextureType::PPTexture;
|
||||||
tex.Texture = texture;
|
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)
|
if ((int)Textures.Size() < index + 1)
|
||||||
Textures.Resize(index + 1);
|
Textures.Resize(index + 1);
|
||||||
auto &tex = Textures[index];
|
auto &tex = Textures[index];
|
||||||
tex.Filter = filter;
|
tex.Filter = filter;
|
||||||
tex.Type = PPTextureType::CurrentPipelineTexture;
|
tex.Wrap = wrap;
|
||||||
|
tex.Type = type;
|
||||||
tex.Texture = {};
|
tex.Texture = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,6 +166,12 @@ public:
|
||||||
Output.Texture = {};
|
Output.Texture = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetOutputSceneColor()
|
||||||
|
{
|
||||||
|
Output.Type = PPTextureType::SceneColor;
|
||||||
|
Output.Texture = {};
|
||||||
|
}
|
||||||
|
|
||||||
void SetNoBlend()
|
void SetNoBlend()
|
||||||
{
|
{
|
||||||
BlendMode.BlendOp = STYLEOP_Add;
|
BlendMode.BlendOp = STYLEOP_Add;
|
||||||
|
@ -173,7 +208,9 @@ enum class PixelFormat
|
||||||
{
|
{
|
||||||
Rgba8,
|
Rgba8,
|
||||||
Rgba16f,
|
Rgba16f,
|
||||||
R32f
|
R32f,
|
||||||
|
Rg16f,
|
||||||
|
Rgba16_snorm
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPTextureDesc
|
class PPTextureDesc
|
||||||
|
@ -221,8 +258,9 @@ public:
|
||||||
|
|
||||||
int SceneWidth = 0;
|
int SceneWidth = 0;
|
||||||
int SceneHeight = 0;
|
int SceneHeight = 0;
|
||||||
int fixedcm;
|
int fixedcm = 0;
|
||||||
float gameinfobluramount;
|
float gameinfobluramount = 0.0f;
|
||||||
|
float m5 = 0.0f;
|
||||||
|
|
||||||
TMap<FString, TArray<PPStep>> Effects;
|
TMap<FString, TArray<PPStep>> Effects;
|
||||||
TMap<FString, PPTextureDesc> Textures;
|
TMap<FString, PPTextureDesc> Textures;
|
||||||
|
@ -457,3 +495,132 @@ public:
|
||||||
NumTonemapModes
|
NumTonemapModes
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct LinearDepthUniforms
|
||||||
|
{
|
||||||
|
int SampleIndex;
|
||||||
|
float LinearizeDepthA;
|
||||||
|
float LinearizeDepthB;
|
||||||
|
float InverseDepthRangeA;
|
||||||
|
float InverseDepthRangeB;
|
||||||
|
float Padding0, Padding1, Padding2;
|
||||||
|
FVector2 Scale;
|
||||||
|
FVector2 Offset;
|
||||||
|
|
||||||
|
static std::vector<UniformFieldDesc> 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<UniformFieldDesc> 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<UniformFieldDesc> 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<UniformFieldDesc> 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];
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue