Add another gbuffer with normal data and make ssao pass use it

This commit is contained in:
Magnus Norddahl 2016-10-05 07:57:27 +02:00
parent 490dd612b3
commit 00e72028ef
13 changed files with 241 additions and 161 deletions

View file

@ -121,7 +121,7 @@ CUSTOM_CVAR(Int, gl_ssao_portals, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
} }
CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, gl_ssao_debug, false, 0) CVAR(Int, gl_ssao_debug, 0, 0)
CVAR(Float, gl_ssao_bias, 0.5f, 0) CVAR(Float, gl_ssao_bias, 0.5f, 0)
CVAR(Float, gl_ssao_radius, 100.0f, 0) CVAR(Float, gl_ssao_radius, 100.0f, 0)
CUSTOM_CVAR(Float, gl_ssao_blur_amount, 4.0f, 0) CUSTOM_CVAR(Float, gl_ssao_blur_amount, 4.0f, 0)
@ -162,13 +162,12 @@ void FGLRenderer::AmbientOccludeScene()
FGLDebug::PushGroup("AmbientOccludeScene"); FGLDebug::PushGroup("AmbientOccludeScene");
FGLPostProcessState savedState; FGLPostProcessState savedState;
savedState.SaveTextureBinding1(); savedState.SaveTextureBindings(3);
float bias = gl_ssao_bias; float bias = gl_ssao_bias;
float aoRadius = gl_ssao_radius; float aoRadius = gl_ssao_radius;
const float blurAmount = gl_ssao_blur_amount; const float blurAmount = gl_ssao_blur_amount;
float aoStrength = gl_ssao_strength; float aoStrength = gl_ssao_strength;
bool multisample = gl_multisample > 1;
//float tanHalfFovy = tan(fovy * (M_PI / 360.0f)); //float tanHalfFovy = tan(fovy * (M_PI / 360.0f));
float tanHalfFovy = 1.0f / gl_RenderState.mProjectionMatrix.get()[5]; float tanHalfFovy = 1.0f / gl_RenderState.mProjectionMatrix.get()[5];
@ -189,16 +188,16 @@ void FGLRenderer::AmbientOccludeScene()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
mLinearDepthShader->Bind(multisample); mLinearDepthShader->Bind();
mLinearDepthShader->DepthTexture[multisample].Set(0); mLinearDepthShader->DepthTexture.Set(0);
mLinearDepthShader->ColorTexture[multisample].Set(1); mLinearDepthShader->ColorTexture.Set(1);
if (multisample) mLinearDepthShader->SampleCount[multisample].Set(gl_multisample); if (gl_multisample > 1) mLinearDepthShader->SampleCount.Set(gl_multisample);
mLinearDepthShader->LinearizeDepthA[multisample].Set(1.0f / GetZFar() - 1.0f / GetZNear()); mLinearDepthShader->LinearizeDepthA.Set(1.0f / GetZFar() - 1.0f / GetZNear());
mLinearDepthShader->LinearizeDepthB[multisample].Set(MAX(1.0f / GetZNear(), 1.e-8f)); mLinearDepthShader->LinearizeDepthB.Set(MAX(1.0f / GetZNear(), 1.e-8f));
mLinearDepthShader->InverseDepthRangeA[multisample].Set(1.0f); mLinearDepthShader->InverseDepthRangeA.Set(1.0f);
mLinearDepthShader->InverseDepthRangeB[multisample].Set(0.0f); mLinearDepthShader->InverseDepthRangeB.Set(0.0f);
mLinearDepthShader->Scale[multisample].Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height); mLinearDepthShader->Scale.Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
mLinearDepthShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height); mLinearDepthShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
RenderScreenQuad(); RenderScreenQuad();
// Apply ambient occlusion // Apply ambient occlusion
@ -212,10 +211,14 @@ void FGLRenderer::AmbientOccludeScene()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
mBuffers->BindSceneNormalTexture(2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
mSSAOShader->Bind(); mSSAOShader->Bind();
mSSAOShader->DepthTexture.Set(0); mSSAOShader->DepthTexture.Set(0);
mSSAOShader->RandomTexture.Set(1); mSSAOShader->RandomTexture.Set(1);
mSSAOShader->NormalTexture.Set(2);
mSSAOShader->UVToViewA.Set(2.0f * invFocalLenX, -2.0f * invFocalLenY); mSSAOShader->UVToViewA.Set(2.0f * invFocalLenX, -2.0f * invFocalLenY);
mSSAOShader->UVToViewB.Set(-invFocalLenX, invFocalLenY); mSSAOShader->UVToViewB.Set(-invFocalLenX, invFocalLenY);
mSSAOShader->InvFullResolution.Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight); mSSAOShader->InvFullResolution.Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
@ -246,26 +249,29 @@ void FGLRenderer::AmbientOccludeScene()
// Add SSAO back to scene texture: // Add SSAO back to scene texture:
mBuffers->BindSceneFB(false); mBuffers->BindSceneFB(false);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, buffers);
glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height); glViewport(mSceneViewport.left, mSceneViewport.top, mSceneViewport.width, mSceneViewport.height);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD); glBlendEquation(GL_FUNC_ADD);
if (gl_ssao_debug) if (gl_ssao_debug > 1)
glBlendFunc(GL_ONE, GL_ZERO); glBlendFunc(GL_ONE, GL_ZERO);
else else
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (gl_ssao_debug == 1)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1); glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
mBuffers->BindSceneDataTexture(1); mBuffers->BindSceneFogTexture(1);
mSSAOCombineShader->Bind(multisample); mSSAOCombineShader->Bind();
mSSAOCombineShader->AODepthTexture[multisample].Set(0); mSSAOCombineShader->AODepthTexture.Set(0);
mSSAOCombineShader->SceneDataTexture[multisample].Set(1); mSSAOCombineShader->SceneFogTexture.Set(1);
if (multisample) mSSAOCombineShader->SampleCount[multisample].Set(gl_multisample); if (gl_multisample > 1) mSSAOCombineShader->SampleCount.Set(gl_multisample);
mSSAOCombineShader->Scale[multisample].Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height); mSSAOCombineShader->Scale.Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
mSSAOCombineShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height); mSSAOCombineShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
RenderScreenQuad(); RenderScreenQuad();
FGLDebug::PopGroup(); FGLDebug::PopGroup();
@ -285,7 +291,7 @@ void FGLRenderer::UpdateCameraExposure()
FGLDebug::PushGroup("UpdateCameraExposure"); FGLDebug::PushGroup("UpdateCameraExposure");
FGLPostProcessState savedState; FGLPostProcessState savedState;
savedState.SaveTextureBinding1(); savedState.SaveTextureBindings(2);
// Extract light level from scene texture: // Extract light level from scene texture:
const auto &level0 = mBuffers->ExposureLevels[0]; const auto &level0 = mBuffers->ExposureLevels[0];
@ -358,7 +364,7 @@ void FGLRenderer::BloomScene()
FGLDebug::PushGroup("BloomScene"); FGLDebug::PushGroup("BloomScene");
FGLPostProcessState savedState; FGLPostProcessState savedState;
savedState.SaveTextureBinding1(); savedState.SaveTextureBindings(2);
const float blurAmount = gl_bloom_amount; const float blurAmount = gl_bloom_amount;
int sampleCount = gl_bloom_kernel_size; int sampleCount = gl_bloom_kernel_size;
@ -461,7 +467,7 @@ void FGLRenderer::TonemapScene()
} }
else else
{ {
savedState.SaveTextureBinding1(); savedState.SaveTextureBindings(2);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureTexture); glBindTexture(GL_TEXTURE_2D, mBuffers->ExposureTexture);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);

View file

@ -45,17 +45,7 @@ FGLPostProcessState::FGLPostProcessState()
{ {
glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding[0]); SaveTextureBindings(1);
glBindTexture(GL_TEXTURE_2D, 0);
if (gl.flags & RFL_SAMPLER_OBJECTS)
{
glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding[0]);
glBindSampler(0, 0);
glActiveTexture(GL_TEXTURE0 + 1);
glGetIntegerv(GL_SAMPLER_BINDING, &samplerBinding[1]);
glBindSampler(1, 0);
glActiveTexture(GL_TEXTURE0);
}
glGetBooleanv(GL_BLEND, &blendEnabled); glGetBooleanv(GL_BLEND, &blendEnabled);
glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled); glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled);
@ -75,12 +65,26 @@ FGLPostProcessState::FGLPostProcessState()
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void FGLPostProcessState::SaveTextureBinding1() void FGLPostProcessState::SaveTextureBindings(unsigned int numUnits)
{ {
glActiveTexture(GL_TEXTURE1); while (textureBinding.Size() < numUnits)
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding[1]); {
unsigned int i = textureBinding.Size();
GLint texture;
glActiveTexture(GL_TEXTURE0 + i);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
textureBinding1Saved = true; textureBinding.Push(texture);
if (gl.flags & RFL_SAMPLER_OBJECTS)
{
GLint sampler;
glGetIntegerv(GL_SAMPLER_BINDING, &sampler);
glBindSampler(i, 0);
samplerBinding.Push(sampler);
}
}
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
} }
@ -117,25 +121,22 @@ FGLPostProcessState::~FGLPostProcessState()
glUseProgram(currentProgram); glUseProgram(currentProgram);
if (textureBinding1Saved) // Fully unbind to avoid incomplete texture warnings from Nvidia's driver when gl_debug_level 4 is active
for (unsigned int i = 0; i < textureBinding.Size(); i++)
{ {
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
glActiveTexture(GL_TEXTURE0); for (unsigned int i = 0; i < samplerBinding.Size(); i++)
glBindTexture(GL_TEXTURE_2D, 0);
if (gl.flags & RFL_SAMPLER_OBJECTS)
{ {
glBindSampler(0, samplerBinding[0]); glBindSampler(i, samplerBinding[i]);
glBindSampler(1, samplerBinding[1]);
} }
glBindTexture(GL_TEXTURE_2D, textureBinding[0]);
if (textureBinding1Saved) for (unsigned int i = 0; i < textureBinding.Size(); i++)
{ {
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, textureBinding[1]); glBindTexture(GL_TEXTURE_2D, textureBinding[i]);
} }
glActiveTexture(activeTex); glActiveTexture(activeTex);

View file

@ -14,15 +14,15 @@ public:
FGLPostProcessState(); FGLPostProcessState();
~FGLPostProcessState(); ~FGLPostProcessState();
void SaveTextureBinding1(); void SaveTextureBindings(unsigned int numUnits);
private: private:
FGLPostProcessState(const FGLPostProcessState &) = delete; FGLPostProcessState(const FGLPostProcessState &) = delete;
FGLPostProcessState &operator=(const FGLPostProcessState &) = delete; FGLPostProcessState &operator=(const FGLPostProcessState &) = delete;
GLint activeTex; GLint activeTex;
GLint textureBinding[2]; TArray<GLint> textureBinding;
GLint samplerBinding[2]; TArray<GLint> samplerBinding;
GLboolean blendEnabled; GLboolean blendEnabled;
GLboolean scissorEnabled; GLboolean scissorEnabled;
GLboolean depthEnabled; GLboolean depthEnabled;
@ -34,7 +34,6 @@ private:
GLint blendSrcAlpha; GLint blendSrcAlpha;
GLint blendDestRgb; GLint blendDestRgb;
GLint blendDestAlpha; GLint blendDestAlpha;
bool textureBinding1Saved = false;
}; };
#endif #endif

View file

@ -86,13 +86,15 @@ void FGLRenderBuffers::ClearScene()
if (mSceneUsesTextures) if (mSceneUsesTextures)
{ {
DeleteTexture(mSceneMultisample); DeleteTexture(mSceneMultisample);
DeleteTexture(mSceneData); DeleteTexture(mSceneFog);
DeleteTexture(mSceneNormal);
DeleteTexture(mSceneDepthStencil); DeleteTexture(mSceneDepthStencil);
} }
else else
{ {
DeleteRenderBuffer(mSceneMultisample); DeleteRenderBuffer(mSceneMultisample);
DeleteRenderBuffer(mSceneData); DeleteRenderBuffer(mSceneFog);
DeleteRenderBuffer(mSceneNormal);
DeleteRenderBuffer(mSceneDepthStencil); DeleteRenderBuffer(mSceneDepthStencil);
} }
} }
@ -264,16 +266,17 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples, bool need
{ {
mSceneMultisample = Create2DMultisampleTexture("SceneMultisample", GL_RGBA16F, width, height, samples, false); mSceneMultisample = Create2DMultisampleTexture("SceneMultisample", GL_RGBA16F, width, height, samples, false);
mSceneDepthStencil = Create2DMultisampleTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples, false); mSceneDepthStencil = Create2DMultisampleTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples, false);
mSceneData = Create2DMultisampleTexture("SceneSSAOData", GL_RGBA8, width, height, samples, false); mSceneFog = Create2DMultisampleTexture("SceneFog", GL_RGBA8, width, height, samples, false);
mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, 0, mSceneDepthStencil, true); mSceneNormal = Create2DMultisampleTexture("SceneNormal", GL_RGB10_A2, width, height, samples, false);
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", mSceneMultisample, mSceneData, mSceneDepthStencil, true); mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, 0, 0, mSceneDepthStencil, true);
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mSceneMultisample, mSceneFog, mSceneNormal, mSceneDepthStencil, true);
} }
else else
{ {
mSceneMultisample = CreateRenderBuffer("SceneMultisample", GL_RGBA16F, width, height, samples); mSceneMultisample = CreateRenderBuffer("SceneMultisample", GL_RGBA16F, width, height, samples);
mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples); mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples);
mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, mSceneDepthStencil, true); mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, mSceneDepthStencil, true);
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", mSceneMultisample, mSceneDepthStencil, true); mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mSceneMultisample, mSceneDepthStencil, true);
} }
} }
else else
@ -281,15 +284,16 @@ void FGLRenderBuffers::CreateScene(int width, int height, int samples, bool need
if (needsSceneTextures) if (needsSceneTextures)
{ {
mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height); mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
mSceneData = Create2DTexture("SceneSSAOData", GL_RGBA8, width, height); mSceneFog = Create2DTexture("SceneFog", GL_RGBA8, width, height);
mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], 0, mSceneDepthStencil, false); mSceneNormal = Create2DTexture("SceneNormal", GL_RGB10_A2, width, height);
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", mPipelineTexture[0], mSceneData, mSceneDepthStencil, false); mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], 0, 0, mSceneDepthStencil, false);
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mPipelineTexture[0], mSceneFog, mSceneNormal, mSceneDepthStencil, false);
} }
else else
{ {
mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height); mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], mSceneDepthStencil, false); mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], mSceneDepthStencil, false);
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", mPipelineTexture[0], mSceneDepthStencil, false); mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mPipelineTexture[0], mSceneDepthStencil, false);
} }
} }
} }
@ -471,6 +475,7 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break; case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break; case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break; case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break;
case GL_RGB10_A2: dataformat = GL_RGBA; datatype = GL_UNSIGNED_INT_10_10_10_2; break;
case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break; case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break;
case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX; datatype = GL_INT; break; case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX; datatype = GL_INT; break;
case GL_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break; case GL_DEPTH24_STENCIL8: dataformat = GL_DEPTH_STENCIL; datatype = GL_UNSIGNED_INT_24_8; break;
@ -560,7 +565,7 @@ GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuff
return handle; return handle;
} }
GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint depthstencil, bool multisample) GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint colorbuffer2, GLuint depthstencil, bool multisample)
{ {
GLuint handle = 0; GLuint handle = 0;
glGenFramebuffers(1, &handle); glGenFramebuffers(1, &handle);
@ -571,6 +576,8 @@ GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuff
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer0, 0);
if (colorbuffer1 != 0) if (colorbuffer1 != 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer1, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer1, 0);
if (colorbuffer2 != 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, colorbuffer2, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depthstencil, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depthstencil, 0);
} }
else else
@ -578,6 +585,8 @@ GLuint FGLRenderBuffers::CreateFrameBuffer(const FString &name, GLuint colorbuff
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0, 0);
if (colorbuffer1 != 0) if (colorbuffer1 != 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorbuffer1, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorbuffer1, 0);
if (colorbuffer2 != 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorbuffer2, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthstencil, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthstencil, 0);
} }
if (CheckFrameBufferCompleteness()) if (CheckFrameBufferCompleteness())
@ -742,17 +751,32 @@ void FGLRenderBuffers::BindSceneColorTexture(int index)
//========================================================================== //==========================================================================
// //
// Binds the scene data texture to the specified texture unit // Binds the scene fog data texture to the specified texture unit
// //
//========================================================================== //==========================================================================
void FGLRenderBuffers::BindSceneDataTexture(int index) void FGLRenderBuffers::BindSceneFogTexture(int index)
{ {
glActiveTexture(GL_TEXTURE0 + index); glActiveTexture(GL_TEXTURE0 + index);
if (mSamples > 1) if (mSamples > 1)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneData); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneFog);
else else
glBindTexture(GL_TEXTURE_2D, mSceneData); glBindTexture(GL_TEXTURE_2D, mSceneFog);
}
//==========================================================================
//
// Binds the scene normal data texture to the specified texture unit
//
//==========================================================================
void FGLRenderBuffers::BindSceneNormalTexture(int index)
{
glActiveTexture(GL_TEXTURE0 + index);
if (mSamples > 1)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mSceneNormal);
else
glBindTexture(GL_TEXTURE_2D, mSceneNormal);
} }
//========================================================================== //==========================================================================

View file

@ -34,7 +34,8 @@ public:
void BindSceneFB(bool sceneData); void BindSceneFB(bool sceneData);
void BindSceneColorTexture(int index); void BindSceneColorTexture(int index);
void BindSceneDataTexture(int index); void BindSceneFogTexture(int index);
void BindSceneNormalTexture(int index);
void BindSceneDepthTexture(int index); void BindSceneDepthTexture(int index);
void BlitSceneToTexture(); void BlitSceneToTexture();
@ -93,7 +94,7 @@ private:
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height); GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer); GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer); GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer);
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint depthstencil, bool multisample); GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint colorbuffer2, GLuint depthstencil, bool multisample);
bool CheckFrameBufferCompleteness(); bool CheckFrameBufferCompleteness();
void ClearFrameBuffer(bool stencil, bool depth); void ClearFrameBuffer(bool stencil, bool depth);
void DeleteTexture(GLuint &handle); void DeleteTexture(GLuint &handle);
@ -113,7 +114,8 @@ private:
// Buffers for the scene // Buffers for the scene
GLuint mSceneMultisample = 0; GLuint mSceneMultisample = 0;
GLuint mSceneDepthStencil = 0; GLuint mSceneDepthStencil = 0;
GLuint mSceneData = 0; GLuint mSceneFog = 0;
GLuint mSceneNormal = 0;
GLuint mSceneFB = 0; GLuint mSceneFB = 0;
GLuint mSceneDataFB = 0; GLuint mSceneDataFB = 0;
bool mSceneUsesTextures = false; bool mSceneUsesTextures = false;

View file

@ -160,8 +160,8 @@ void FGLRenderer::Set3DViewport(bool mainview)
{ {
bool useSSAO = (gl_ssao != 0); bool useSSAO = (gl_ssao != 0);
mBuffers->BindSceneFB(useSSAO); mBuffers->BindSceneFB(useSSAO);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(useSSAO ? 2 : 1, buffers); glDrawBuffers(useSSAO ? 3 : 1, buffers);
gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS); gl_RenderState.SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
gl_RenderState.Apply(); gl_RenderState.Apply();
} }
@ -507,8 +507,8 @@ void FGLRenderer::DrawScene(int drawmode)
// If SSAO is active, switch to gbuffer shaders and use the framebuffer with gbuffers // If SSAO is active, switch to gbuffer shaders and use the framebuffer with gbuffers
if (applySSAO) if (applySSAO)
{ {
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(2, buffers); glDrawBuffers(3, buffers);
gl_RenderState.SetPassType(GBUFFER_PASS); gl_RenderState.SetPassType(GBUFFER_PASS);
gl_RenderState.Apply(); gl_RenderState.Apply();
gl_RenderState.ApplyMatrices(); gl_RenderState.ApplyMatrices();

View file

@ -31,54 +31,65 @@
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
#include "gl/shaders/gl_ambientshader.h" #include "gl/shaders/gl_ambientshader.h"
void FLinearDepthShader::Bind(bool multisample) void FLinearDepthShader::Bind()
{ {
auto &shader = mShader[multisample]; bool multisample = (gl_multisample > 1);
if (!shader) if (mMultisample != multisample)
mShader.reset();
if (!mShader)
{ {
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader = std::make_unique<FShaderProgram>();
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader.SetFragDataLocation(0, "FragColor"); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/lineardepth.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
shader.Link("shaders/glsl/lineardepth"); mShader->SetFragDataLocation(0, "FragColor");
shader.SetAttribLocation(0, "PositionInProjection"); mShader->Link("shaders/glsl/lineardepth");
DepthTexture[multisample].Init(shader, "DepthTexture"); mShader->SetAttribLocation(0, "PositionInProjection");
ColorTexture[multisample].Init(shader, "ColorTexture"); DepthTexture.Init(*mShader, "DepthTexture");
SampleCount[multisample].Init(shader, "SampleCount"); ColorTexture.Init(*mShader, "ColorTexture");
LinearizeDepthA[multisample].Init(shader, "LinearizeDepthA"); SampleCount.Init(*mShader, "SampleCount");
LinearizeDepthB[multisample].Init(shader, "LinearizeDepthB"); LinearizeDepthA.Init(*mShader, "LinearizeDepthA");
InverseDepthRangeA[multisample].Init(shader, "InverseDepthRangeA"); LinearizeDepthB.Init(*mShader, "LinearizeDepthB");
InverseDepthRangeB[multisample].Init(shader, "InverseDepthRangeB"); InverseDepthRangeA.Init(*mShader, "InverseDepthRangeA");
Scale[multisample].Init(shader, "Scale"); InverseDepthRangeB.Init(*mShader, "InverseDepthRangeB");
Offset[multisample].Init(shader, "Offset"); Scale.Init(*mShader, "Scale");
Offset.Init(*mShader, "Offset");
mMultisample = multisample;
} }
shader.Bind(); mShader->Bind();
} }
void FSSAOShader::Bind() void FSSAOShader::Bind()
{ {
auto &shader = mShader[gl_ssao]; bool multisample = (gl_multisample > 1);
if (!shader) if (mCurrentQuality != gl_ssao || mMultisample != multisample)
mShader.reset();
if (!mShader)
{ {
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader = std::make_unique<FShaderProgram>();
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao), 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader.SetFragDataLocation(0, "FragColor"); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssao.fp", GetDefines(gl_ssao, multisample), 330);
shader.Link("shaders/glsl/ssao"); mShader->SetFragDataLocation(0, "FragColor");
shader.SetAttribLocation(0, "PositionInProjection"); mShader->Link("shaders/glsl/ssao");
DepthTexture.Init(shader, "DepthTexture"); mShader->SetAttribLocation(0, "PositionInProjection");
RandomTexture.Init(shader, "RandomTexture"); DepthTexture.Init(*mShader, "DepthTexture");
UVToViewA.Init(shader, "UVToViewA"); NormalTexture.Init(*mShader, "NormalTexture");
UVToViewB.Init(shader, "UVToViewB"); RandomTexture.Init(*mShader, "RandomTexture");
InvFullResolution.Init(shader, "InvFullResolution"); UVToViewA.Init(*mShader, "UVToViewA");
NDotVBias.Init(shader, "NDotVBias"); UVToViewB.Init(*mShader, "UVToViewB");
NegInvR2.Init(shader, "NegInvR2"); InvFullResolution.Init(*mShader, "InvFullResolution");
RadiusToScreen.Init(shader, "RadiusToScreen"); NDotVBias.Init(*mShader, "NDotVBias");
AOMultiplier.Init(shader, "AOMultiplier"); NegInvR2.Init(*mShader, "NegInvR2");
AOStrength.Init(shader, "AOStrength"); RadiusToScreen.Init(*mShader, "RadiusToScreen");
AOMultiplier.Init(*mShader, "AOMultiplier");
AOStrength.Init(*mShader, "AOStrength");
mMultisample = multisample;
} }
shader.Bind(); mShader->Bind();
} }
FString FSSAOShader::GetDefines(int mode) FString FSSAOShader::GetDefines(int mode, bool multisample)
{ {
int numDirections, numSteps; int numDirections, numSteps;
switch (gl_ssao) switch (gl_ssao)
@ -96,6 +107,9 @@ FString FSSAOShader::GetDefines(int mode)
#define NUM_DIRECTIONS %d.0 #define NUM_DIRECTIONS %d.0
#define NUM_STEPS %d.0 #define NUM_STEPS %d.0
)", numDirections, numSteps); )", numDirections, numSteps);
if (multisample)
defines += "\n#define MULTISAMPLE\n";
return defines; return defines;
} }
@ -117,21 +131,26 @@ void FDepthBlurShader::Bind(bool vertical)
shader.Bind(); shader.Bind();
} }
void FSSAOCombineShader::Bind(bool multisample) void FSSAOCombineShader::Bind()
{ {
auto &shader = mShader[multisample]; bool multisample = (gl_multisample > 1);
if (!shader) if (mMultisample != multisample)
mShader.reset();
if (!mShader)
{ {
shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); mShader = std::make_unique<FShaderProgram>();
shader.Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330); mShader->Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330);
shader.SetFragDataLocation(0, "FragColor"); mShader->Compile(FShaderProgram::Fragment, "shaders/glsl/ssaocombine.fp", multisample ? "#define MULTISAMPLE\n" : "", 330);
shader.Link("shaders/glsl/ssaocombine"); mShader->SetFragDataLocation(0, "FragColor");
shader.SetAttribLocation(0, "PositionInProjection"); mShader->Link("shaders/glsl/ssaocombine");
AODepthTexture[multisample].Init(shader, "AODepthTexture"); mShader->SetAttribLocation(0, "PositionInProjection");
SceneDataTexture[multisample].Init(shader, "SceneDataTexture"); AODepthTexture.Init(*mShader, "AODepthTexture");
SampleCount[multisample].Init(shader, "SampleCount"); SceneFogTexture.Init(*mShader, "SceneFogTexture");
Scale[multisample].Init(shader, "Scale"); SampleCount.Init(*mShader, "SampleCount");
Offset[multisample].Init(shader, "Offset"); Scale.Init(*mShader, "Scale");
Offset.Init(*mShader, "Offset");
mMultisample = multisample;
} }
shader.Bind(); mShader->Bind();
} }

View file

@ -6,20 +6,21 @@
class FLinearDepthShader class FLinearDepthShader
{ {
public: public:
void Bind(bool multisample); void Bind();
FBufferedUniformSampler DepthTexture[2]; FBufferedUniformSampler DepthTexture;
FBufferedUniformSampler ColorTexture[2]; FBufferedUniformSampler ColorTexture;
FBufferedUniform1i SampleCount[2]; FBufferedUniform1i SampleCount;
FBufferedUniform1f LinearizeDepthA[2]; FBufferedUniform1f LinearizeDepthA;
FBufferedUniform1f LinearizeDepthB[2]; FBufferedUniform1f LinearizeDepthB;
FBufferedUniform1f InverseDepthRangeA[2]; FBufferedUniform1f InverseDepthRangeA;
FBufferedUniform1f InverseDepthRangeB[2]; FBufferedUniform1f InverseDepthRangeB;
FBufferedUniform2f Scale[2]; FBufferedUniform2f Scale;
FBufferedUniform2f Offset[2]; FBufferedUniform2f Offset;
private: private:
FShaderProgram mShader[2]; std::unique_ptr<FShaderProgram> mShader;
bool mMultisample = false;
}; };
class FSSAOShader class FSSAOShader
@ -28,6 +29,7 @@ public:
void Bind(); void Bind();
FBufferedUniformSampler DepthTexture; FBufferedUniformSampler DepthTexture;
FBufferedUniformSampler NormalTexture;
FBufferedUniformSampler RandomTexture; FBufferedUniformSampler RandomTexture;
FBufferedUniform2f UVToViewA; FBufferedUniform2f UVToViewA;
FBufferedUniform2f UVToViewB; FBufferedUniform2f UVToViewB;
@ -48,9 +50,11 @@ private:
NumQualityModes NumQualityModes
}; };
FString GetDefines(int mode); FString GetDefines(int mode, bool multisample);
FShaderProgram mShader[NumQualityModes]; std::unique_ptr<FShaderProgram> mShader;
Quality mCurrentQuality = Off;
bool mMultisample = false;
}; };
class FDepthBlurShader class FDepthBlurShader
@ -70,16 +74,17 @@ private:
class FSSAOCombineShader class FSSAOCombineShader
{ {
public: public:
void Bind(bool multisample); void Bind();
FBufferedUniformSampler AODepthTexture[2]; FBufferedUniformSampler AODepthTexture;
FBufferedUniformSampler SceneDataTexture[2]; FBufferedUniformSampler SceneFogTexture;
FBufferedUniform1i SampleCount[2]; FBufferedUniform1i SampleCount;
FBufferedUniform2f Scale[2]; FBufferedUniform2f Scale;
FBufferedUniform2f Offset[2]; FBufferedUniform2f Offset;
private: private:
FShaderProgram mShader[2]; std::unique_ptr<FShaderProgram> mShader;
bool mMultisample = false;
}; };
#endif #endif

View file

@ -182,7 +182,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
glBindAttribLocation(hShader, VATTR_NORMAL, "aNormal"); glBindAttribLocation(hShader, VATTR_NORMAL, "aNormal");
glBindFragDataLocation(hShader, 0, "FragColor"); glBindFragDataLocation(hShader, 0, "FragColor");
glBindFragDataLocation(hShader, 1, "FragData"); glBindFragDataLocation(hShader, 1, "FragFog");
glBindFragDataLocation(hShader, 2, "FragNormal");
glLinkProgram(hShader); glLinkProgram(hShader);

View file

@ -53,7 +53,7 @@ EXTERN_CVAR(Float, gl_lens_chromatic)
EXTERN_CVAR(Int, gl_ssao) EXTERN_CVAR(Int, gl_ssao)
EXTERN_CVAR(Int, gl_ssao_portals) EXTERN_CVAR(Int, gl_ssao_portals)
EXTERN_CVAR(Float, gl_ssao_strength) EXTERN_CVAR(Float, gl_ssao_strength)
EXTERN_CVAR(Bool, gl_ssao_debug) EXTERN_CVAR(Int, gl_ssao_debug)
EXTERN_CVAR(Float, gl_ssao_bias) EXTERN_CVAR(Float, gl_ssao_bias)
EXTERN_CVAR(Float, gl_ssao_radius) EXTERN_CVAR(Float, gl_ssao_radius)
EXTERN_CVAR(Float, gl_ssao_blur_amount) EXTERN_CVAR(Float, gl_ssao_blur_amount)

View file

@ -8,7 +8,8 @@ in vec4 vColor;
out vec4 FragColor; out vec4 FragColor;
#ifdef GBUFFER_PASS #ifdef GBUFFER_PASS
out vec4 FragData; out vec4 FragFog;
out vec4 FragNormal;
#endif #endif
#ifdef SHADER_STORAGE_LIGHTS #ifdef SHADER_STORAGE_LIGHTS
@ -408,7 +409,8 @@ void main()
} }
FragColor = frag; FragColor = frag;
#ifdef GBUFFER_PASS #ifdef GBUFFER_PASS
FragData = vec4(AmbientOcclusionColor(), 1.0); FragFog = vec4(AmbientOcclusionColor(), 1.0);
FragNormal = vec4(vEyeNormal.xyz * 0.5 + 0.5, 1.0);
#endif #endif
} }

View file

@ -15,6 +15,12 @@ uniform float AOStrength;
uniform sampler2D DepthTexture; uniform sampler2D DepthTexture;
#if defined(MULTISAMPLE)
uniform sampler2DMS NormalTexture;
#else
uniform sampler2D NormalTexture;
#endif
#if defined(USE_RANDOM_TEXTURE) #if defined(USE_RANDOM_TEXTURE)
uniform sampler2D RandomTexture; uniform sampler2D RandomTexture;
#endif #endif
@ -28,6 +34,20 @@ vec3 FetchViewPos(vec2 uv)
return vec3((UVToViewA * uv + UVToViewB) * z, z); return vec3((UVToViewA * uv + UVToViewB) * z, z);
} }
#if defined(MULTISAMPLE)
vec3 FetchNormal(vec2 uv)
{
ivec2 texSize = textureSize(NormalTexture);
ivec2 ipos = ivec2(uv * vec2(texSize));
return normalize(texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0);
}
#else
vec3 FetchNormal(vec2 uv)
{
return normalize(texture(NormalTexture, uv).xyz * 2.0 - 1.0);
}
#endif
vec3 MinDiff(vec3 p, vec3 pr, vec3 pl) vec3 MinDiff(vec3 p, vec3 pr, vec3 pl)
{ {
vec3 v1 = pr - p; vec3 v1 = pr - p;
@ -106,7 +126,8 @@ float ComputeAO(vec3 viewPosition, vec3 viewNormal)
void main() void main()
{ {
vec3 viewPosition = FetchViewPos(TexCoord); vec3 viewPosition = FetchViewPos(TexCoord);
vec3 viewNormal = ReconstructNormal(viewPosition); //vec3 viewNormal = ReconstructNormal(viewPosition);
vec3 viewNormal = FetchNormal(TexCoord);
float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength); float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength);
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0); FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
} }

View file

@ -5,10 +5,10 @@ out vec4 FragColor;
uniform sampler2D AODepthTexture; uniform sampler2D AODepthTexture;
#if defined(MULTISAMPLE) #if defined(MULTISAMPLE)
uniform sampler2DMS SceneDataTexture; uniform sampler2DMS SceneFogTexture;
uniform int SampleCount; uniform int SampleCount;
#else #else
uniform sampler2D SceneDataTexture; uniform sampler2D SceneFogTexture;
#endif #endif
uniform vec2 Scale; uniform vec2 Scale;
@ -18,19 +18,19 @@ void main()
{ {
vec2 uv = Offset + TexCoord * Scale; vec2 uv = Offset + TexCoord * Scale;
#if defined(MULTISAMPLE) #if defined(MULTISAMPLE)
ivec2 texSize = textureSize(SceneDataTexture); ivec2 texSize = textureSize(SceneFogTexture);
#else #else
ivec2 texSize = textureSize(SceneDataTexture, 0); ivec2 texSize = textureSize(SceneFogTexture, 0);
#endif #endif
ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0))); ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0)));
#if defined(MULTISAMPLE) #if defined(MULTISAMPLE)
vec3 fogColor = vec3(0.0); vec3 fogColor = vec3(0.0);
for (int i = 0; i < SampleCount; i++) for (int i = 0; i < SampleCount; i++)
fogColor += texelFetch(SceneDataTexture, ipos, i).rgb; fogColor += texelFetch(SceneFogTexture, ipos, i).rgb;
fogColor /= float(SampleCount); fogColor /= float(SampleCount);
#else #else
vec3 fogColor = texelFetch(SceneDataTexture, ipos, 0).rgb; vec3 fogColor = texelFetch(SceneFogTexture, ipos, 0).rgb;
#endif #endif
float attenutation = texture(AODepthTexture, TexCoord).x; float attenutation = texture(AODepthTexture, TexCoord).x;