mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-14 16:41:07 +00:00
Merge branch 'ssao' into qzdoom
This commit is contained in:
commit
94d8e10f96
15 changed files with 432 additions and 258 deletions
|
@ -121,10 +121,15 @@ 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.2f, 0)
|
||||||
CVAR(Float, gl_ssao_radius, 100.0f, 0)
|
CVAR(Float, gl_ssao_radius, 80.0f, 0)
|
||||||
CUSTOM_CVAR(Float, gl_ssao_blur_amount, 4.0f, 0)
|
CUSTOM_CVAR(Float, gl_ssao_blur, 16.0f, 0)
|
||||||
|
{
|
||||||
|
if (self < 0.1f) self = 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Float, gl_ssao_exponent, 1.8f, 0)
|
||||||
{
|
{
|
||||||
if (self < 0.1f) self = 0.1f;
|
if (self < 0.1f) self = 0.1f;
|
||||||
}
|
}
|
||||||
|
@ -162,13 +167,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;
|
||||||
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];
|
||||||
|
@ -179,8 +183,15 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
|
|
||||||
float blurSharpness = 1.0f / blurAmount;
|
float blurSharpness = 1.0f / blurAmount;
|
||||||
|
|
||||||
|
float sceneScaleX = mSceneViewport.width / (float)mScreenViewport.width;
|
||||||
|
float sceneScaleY = mSceneViewport.height / (float)mScreenViewport.height;
|
||||||
|
float sceneOffsetX = mSceneViewport.left / (float)mScreenViewport.width;
|
||||||
|
float sceneOffsetY = mSceneViewport.top / (float)mScreenViewport.height;
|
||||||
|
|
||||||
|
int randomTexture = clamp(gl_ssao - 1, 0, FGLRenderBuffers::NumAmbientRandomTextures - 1);
|
||||||
|
|
||||||
// Calculate linear depth values
|
// Calculate linear depth values
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->LinearDepthFB);
|
||||||
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
|
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
|
||||||
mBuffers->BindSceneDepthTexture(0);
|
mBuffers->BindSceneDepthTexture(0);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -189,44 +200,53 @@ 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->SampleIndex.Set(0);
|
||||||
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(sceneScaleX, sceneScaleY);
|
||||||
mLinearDepthShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
mLinearDepthShader->Offset.Set(sceneOffsetX, sceneOffsetY);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
||||||
// Apply ambient occlusion
|
// Apply ambient occlusion
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
||||||
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
|
glBindTexture(GL_TEXTURE_2D, mBuffers->LinearDepthTexture);
|
||||||
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_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientRandomTexture);
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientRandomTexture[randomTexture]);
|
||||||
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);
|
||||||
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->UVToViewA.Set(2.0f * invFocalLenX, -2.0f * invFocalLenY);
|
mSSAOShader->NormalTexture.Set(2);
|
||||||
mSSAOShader->UVToViewB.Set(-invFocalLenX, invFocalLenY);
|
if (gl_multisample > 1) mSSAOShader->SampleIndex.Set(0);
|
||||||
|
mSSAOShader->UVToViewA.Set(2.0f * invFocalLenX, 2.0f * 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);
|
||||||
mSSAOShader->NDotVBias.Set(nDotVBias);
|
mSSAOShader->NDotVBias.Set(nDotVBias);
|
||||||
mSSAOShader->NegInvR2.Set(-1.0f / r2);
|
mSSAOShader->NegInvR2.Set(-1.0f / r2);
|
||||||
mSSAOShader->RadiusToScreen.Set(aoRadius * 0.5 / tanHalfFovy * mBuffers->AmbientHeight);
|
mSSAOShader->RadiusToScreen.Set(aoRadius * 0.5 / tanHalfFovy * mBuffers->AmbientHeight);
|
||||||
mSSAOShader->AOMultiplier.Set(1.0f / (1.0f - nDotVBias));
|
mSSAOShader->AOMultiplier.Set(1.0f / (1.0f - nDotVBias));
|
||||||
mSSAOShader->AOStrength.Set(aoStrength);
|
mSSAOShader->AOStrength.Set(aoStrength);
|
||||||
|
mSSAOShader->Scale.Set(sceneScaleX, sceneScaleY);
|
||||||
|
mSSAOShader->Offset.Set(sceneOffsetX, sceneOffsetY);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
||||||
// Blur SSAO texture
|
// Blur SSAO texture
|
||||||
|
if (gl_ssao_debug < 2)
|
||||||
|
{
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
||||||
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -241,31 +261,32 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
mDepthBlurShader->Bind(true);
|
mDepthBlurShader->Bind(true);
|
||||||
mDepthBlurShader->BlurSharpness[true].Set(blurSharpness);
|
mDepthBlurShader->BlurSharpness[true].Set(blurSharpness);
|
||||||
mDepthBlurShader->InvFullResolution[true].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
mDepthBlurShader->InvFullResolution[true].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
||||||
mDepthBlurShader->PowExponent[true].Set(1.8f);
|
mDepthBlurShader->PowExponent[true].Set(gl_ssao_exponent);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
|
||||||
else
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
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);
|
||||||
|
}
|
||||||
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(sceneScaleX, sceneScaleY);
|
||||||
mSSAOCombineShader->Offset[multisample].Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
mSSAOCombineShader->Offset.Set(sceneOffsetX, sceneOffsetY);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
FGLDebug::PopGroup();
|
||||||
|
@ -285,7 +306,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 +379,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 +482,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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -59,6 +59,11 @@ FGLRenderBuffers::FGLRenderBuffers()
|
||||||
mPipelineFB[i] = 0;
|
mPipelineFB[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < NumAmbientRandomTextures; i++)
|
||||||
|
{
|
||||||
|
AmbientRandomTexture[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&mOutputFB);
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&mOutputFB);
|
||||||
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
||||||
}
|
}
|
||||||
|
@ -83,9 +88,20 @@ void FGLRenderBuffers::ClearScene()
|
||||||
{
|
{
|
||||||
DeleteFrameBuffer(mSceneFB);
|
DeleteFrameBuffer(mSceneFB);
|
||||||
DeleteFrameBuffer(mSceneDataFB);
|
DeleteFrameBuffer(mSceneDataFB);
|
||||||
|
if (mSceneUsesTextures)
|
||||||
|
{
|
||||||
DeleteTexture(mSceneMultisample);
|
DeleteTexture(mSceneMultisample);
|
||||||
DeleteTexture(mSceneData);
|
DeleteTexture(mSceneFog);
|
||||||
|
DeleteTexture(mSceneNormal);
|
||||||
DeleteTexture(mSceneDepthStencil);
|
DeleteTexture(mSceneDepthStencil);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeleteRenderBuffer(mSceneMultisample);
|
||||||
|
DeleteRenderBuffer(mSceneFog);
|
||||||
|
DeleteRenderBuffer(mSceneNormal);
|
||||||
|
DeleteRenderBuffer(mSceneDepthStencil);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearPipeline()
|
void FGLRenderBuffers::ClearPipeline()
|
||||||
|
@ -136,11 +152,14 @@ void FGLRenderBuffers::ClearEyeBuffers()
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearAmbientOcclusion()
|
void FGLRenderBuffers::ClearAmbientOcclusion()
|
||||||
{
|
{
|
||||||
|
DeleteFrameBuffer(LinearDepthFB);
|
||||||
DeleteFrameBuffer(AmbientFB0);
|
DeleteFrameBuffer(AmbientFB0);
|
||||||
DeleteFrameBuffer(AmbientFB1);
|
DeleteFrameBuffer(AmbientFB1);
|
||||||
|
DeleteTexture(LinearDepthTexture);
|
||||||
DeleteTexture(AmbientTexture0);
|
DeleteTexture(AmbientTexture0);
|
||||||
DeleteTexture(AmbientTexture1);
|
DeleteTexture(AmbientTexture1);
|
||||||
DeleteTexture(AmbientRandomTexture);
|
for (int i = 0; i < NumAmbientRandomTextures; i++)
|
||||||
|
DeleteTexture(AmbientRandomTexture[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
|
void FGLRenderBuffers::DeleteTexture(GLuint &handle)
|
||||||
|
@ -188,6 +207,7 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height);
|
I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height);
|
||||||
|
|
||||||
int samples = clamp((int)gl_multisample, 0, mMaxSamples);
|
int samples = clamp((int)gl_multisample, 0, mMaxSamples);
|
||||||
|
bool needsSceneTextures = (gl_ssao != 0);
|
||||||
|
|
||||||
GLint activeTex;
|
GLint activeTex;
|
||||||
GLint textureBinding;
|
GLint textureBinding;
|
||||||
|
@ -195,19 +215,16 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
||||||
|
|
||||||
if (width == mWidth && height == mHeight && mSamples != samples)
|
if (width != mWidth || height != mHeight)
|
||||||
{
|
|
||||||
CreateScene(mWidth, mHeight, samples);
|
|
||||||
mSamples = samples;
|
|
||||||
}
|
|
||||||
else if (width != mWidth || height != mHeight)
|
|
||||||
{
|
|
||||||
CreatePipeline(width, height);
|
CreatePipeline(width, height);
|
||||||
CreateScene(width, height, samples);
|
|
||||||
|
if (width != mWidth || height != mHeight || mSamples != samples || mSceneUsesTextures != needsSceneTextures)
|
||||||
|
CreateScene(width, height, samples, needsSceneTextures);
|
||||||
|
|
||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
mSamples = samples;
|
mSamples = samples;
|
||||||
}
|
mSceneUsesTextures = needsSceneTextures;
|
||||||
|
|
||||||
// Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts
|
// Bloom bluring buffers need to match the scene to avoid bloom bleeding artifacts
|
||||||
if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight)
|
if (mSceneWidth != sceneWidth || mSceneHeight != sceneHeight)
|
||||||
|
@ -247,24 +264,46 @@ bool FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHei
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FGLRenderBuffers::CreateScene(int width, int height, int samples)
|
void FGLRenderBuffers::CreateScene(int width, int height, int samples, bool needsSceneTextures)
|
||||||
{
|
{
|
||||||
ClearScene();
|
ClearScene();
|
||||||
|
|
||||||
if (samples > 1)
|
if (samples > 1)
|
||||||
|
{
|
||||||
|
if (needsSceneTextures)
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
mSceneNormal = Create2DMultisampleTexture("SceneNormal", GL_RGB10_A2, width, height, samples, false);
|
||||||
|
mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, 0, 0, mSceneDepthStencil, true);
|
||||||
|
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mSceneMultisample, mSceneFog, mSceneNormal, mSceneDepthStencil, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
mSceneMultisample = CreateRenderBuffer("SceneMultisample", GL_RGBA16F, width, height, samples);
|
||||||
mSceneData = Create2DTexture("SceneSSAOData", GL_RGBA8, width, height);
|
mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height, samples);
|
||||||
|
mSceneFB = CreateFrameBuffer("SceneFB", mSceneMultisample, mSceneDepthStencil, true);
|
||||||
|
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mSceneMultisample, mSceneDepthStencil, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (needsSceneTextures)
|
||||||
|
{
|
||||||
|
mSceneDepthStencil = Create2DTexture("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
||||||
|
mSceneFog = Create2DTexture("SceneFog", GL_RGBA8, width, height);
|
||||||
|
mSceneNormal = Create2DTexture("SceneNormal", GL_RGB10_A2, width, height);
|
||||||
|
mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], 0, 0, mSceneDepthStencil, false);
|
||||||
|
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mPipelineTexture[0], mSceneFog, mSceneNormal, mSceneDepthStencil, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSceneDepthStencil = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
||||||
|
mSceneFB = CreateFrameBuffer("SceneFB", mPipelineTexture[0], mSceneDepthStencil, false);
|
||||||
|
mSceneDataFB = CreateFrameBuffer("SceneGBufferFB", mPipelineTexture[0], mSceneDepthStencil, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mSceneFB = CreateFrameBuffer("SceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], 0, mSceneDepthStencil, samples > 1);
|
|
||||||
mSceneDataFB = CreateFrameBuffer("SSAOSceneFB", samples > 1 ? mSceneMultisample : mPipelineTexture[0], mSceneData, mSceneDepthStencil, samples > 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -299,13 +338,13 @@ void FGLRenderBuffers::CreateBloom(int width, int height)
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int bloomWidth = MAX(width / 2, 1);
|
int bloomWidth = (width + 1) / 2;
|
||||||
int bloomHeight = MAX(height / 2, 1);
|
int bloomHeight = (height + 1) / 2;
|
||||||
for (int i = 0; i < NumBloomLevels; i++)
|
for (int i = 0; i < NumBloomLevels; i++)
|
||||||
{
|
{
|
||||||
auto &level = BloomLevels[i];
|
auto &level = BloomLevels[i];
|
||||||
level.Width = MAX(bloomWidth / 2, 1);
|
level.Width = (bloomWidth + 1) / 2;
|
||||||
level.Height = MAX(bloomHeight / 2, 1);
|
level.Height = (bloomHeight + 1) / 2;
|
||||||
|
|
||||||
level.VTexture = Create2DTexture("Bloom.VTexture", GL_RGBA16F, level.Width, level.Height);
|
level.VTexture = Create2DTexture("Bloom.VTexture", GL_RGBA16F, level.Width, level.Height);
|
||||||
level.HTexture = Create2DTexture("Bloom.HTexture", GL_RGBA16F, level.Width, level.Height);
|
level.HTexture = Create2DTexture("Bloom.HTexture", GL_RGBA16F, level.Width, level.Height);
|
||||||
|
@ -330,20 +369,27 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
|
||||||
if (width <= 0 || height <= 0)
|
if (width <= 0 || height <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AmbientWidth = width / 2;
|
AmbientWidth = (width + 1) / 2;
|
||||||
AmbientHeight = height / 2;
|
AmbientHeight = (height + 1) / 2;
|
||||||
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG32F, AmbientWidth, AmbientHeight);
|
LinearDepthTexture = Create2DTexture("LinearDepthTexture", GL_R32F, AmbientWidth, AmbientHeight);
|
||||||
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG32F, AmbientWidth, AmbientHeight);
|
AmbientTexture0 = Create2DTexture("AmbientTexture0", GL_RG16F, AmbientWidth, AmbientHeight);
|
||||||
|
AmbientTexture1 = Create2DTexture("AmbientTexture1", GL_RG16F, AmbientWidth, AmbientHeight);
|
||||||
|
LinearDepthFB = CreateFrameBuffer("LinearDepthFB", LinearDepthTexture);
|
||||||
AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0);
|
AmbientFB0 = CreateFrameBuffer("AmbientFB0", AmbientTexture0);
|
||||||
AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1);
|
AmbientFB1 = CreateFrameBuffer("AmbientFB1", AmbientTexture1);
|
||||||
|
|
||||||
int16_t randomValues[16 * 4];
|
// Must match quality enum in FSSAOShader::GetDefines
|
||||||
|
double numDirections[NumAmbientRandomTextures] = { 2.0, 4.0, 8.0 };
|
||||||
|
|
||||||
std::mt19937 generator(1337);
|
std::mt19937 generator(1337);
|
||||||
std::uniform_real_distribution<double> distribution(-1.0, 1.0);
|
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++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
double num_directions = 8.0; // Must be same as the define in ssao.fp
|
double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality];
|
||||||
double angle = 2.0 * M_PI * distribution(generator) / num_directions;
|
|
||||||
double x = cos(angle);
|
double x = cos(angle);
|
||||||
double y = sin(angle);
|
double y = sin(angle);
|
||||||
double z = distribution(generator);
|
double z = distribution(generator);
|
||||||
|
@ -355,7 +401,8 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
|
||||||
randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0);
|
randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
AmbientRandomTexture = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
|
AmbientRandomTexture[quality] = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -442,12 +489,15 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
|
||||||
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
|
case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break;
|
||||||
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||||
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break;
|
||||||
|
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
|
||||||
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
|
case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break;
|
||||||
|
case GL_R16F: 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_RG16F: 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;
|
||||||
case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break;
|
|
||||||
default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture");
|
default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +536,7 @@ GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format,
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height)
|
GLuint FGLRenderBuffers::CreateRenderBuffer(const FString &name, GLuint format, int width, int height, int samples)
|
||||||
{
|
{
|
||||||
if (samples <= 1)
|
if (samples <= 1)
|
||||||
return CreateRenderBuffer(name, format, width, height);
|
return CreateRenderBuffer(name, format, width, height);
|
||||||
|
@ -517,7 +567,23 @@ 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 colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer)
|
||||||
|
{
|
||||||
|
GLuint handle = 0;
|
||||||
|
glGenFramebuffers(1, &handle);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, handle);
|
||||||
|
FGLDebug::LabelObject(GL_FRAMEBUFFER, handle, name);
|
||||||
|
if (colorIsARenderBuffer)
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer);
|
||||||
|
else
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0);
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthstencil);
|
||||||
|
if (CheckFrameBufferCompleteness())
|
||||||
|
ClearFrameBuffer(true, true);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
@ -528,6 +594,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
|
||||||
|
@ -535,6 +603,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())
|
||||||
|
@ -699,17 +769,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
@ -58,13 +59,16 @@ public:
|
||||||
bool FirstExposureFrame = true;
|
bool FirstExposureFrame = true;
|
||||||
|
|
||||||
// Ambient occlusion buffers
|
// Ambient occlusion buffers
|
||||||
|
GLuint LinearDepthTexture = 0;
|
||||||
|
GLuint LinearDepthFB = 0;
|
||||||
GLuint AmbientTexture0 = 0;
|
GLuint AmbientTexture0 = 0;
|
||||||
GLuint AmbientTexture1 = 0;
|
GLuint AmbientTexture1 = 0;
|
||||||
GLuint AmbientFB0 = 0;
|
GLuint AmbientFB0 = 0;
|
||||||
GLuint AmbientFB1 = 0;
|
GLuint AmbientFB1 = 0;
|
||||||
int AmbientWidth = 0;
|
int AmbientWidth = 0;
|
||||||
int AmbientHeight = 0;
|
int AmbientHeight = 0;
|
||||||
GLuint AmbientRandomTexture = 0;
|
enum { NumAmbientRandomTextures = 3 };
|
||||||
|
GLuint AmbientRandomTexture[NumAmbientRandomTextures];
|
||||||
|
|
||||||
static bool IsEnabled();
|
static bool IsEnabled();
|
||||||
|
|
||||||
|
@ -81,7 +85,7 @@ private:
|
||||||
void ClearBloom();
|
void ClearBloom();
|
||||||
void ClearExposureLevels();
|
void ClearExposureLevels();
|
||||||
void ClearAmbientOcclusion();
|
void ClearAmbientOcclusion();
|
||||||
void CreateScene(int width, int height, int samples);
|
void CreateScene(int width, int height, int samples, bool needsSceneTextures);
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateBloom(int width, int height);
|
void CreateBloom(int width, int height);
|
||||||
void CreateExposureLevels(int width, int height);
|
void CreateExposureLevels(int width, int height);
|
||||||
|
@ -90,9 +94,10 @@ private:
|
||||||
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
|
GLuint Create2DTexture(const FString &name, GLuint format, int width, int height, const void *data = nullptr);
|
||||||
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
|
GLuint Create2DMultisampleTexture(const FString &name, GLuint format, int width, int height, int samples, bool fixedSampleLocations);
|
||||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
|
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height);
|
||||||
GLuint CreateRenderBuffer(const FString &name, GLuint format, int samples, int width, int height);
|
GLuint CreateRenderBuffer(const FString &name, GLuint format, int width, int height, int samples);
|
||||||
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
|
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer);
|
||||||
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer0, GLuint colorbuffer1, GLuint depthstencil, bool multisample);
|
GLuint CreateFrameBuffer(const FString &name, GLuint colorbuffer, GLuint depthstencil, bool colorIsARenderBuffer);
|
||||||
|
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);
|
||||||
|
@ -112,9 +117,11 @@ 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;
|
||||||
|
|
||||||
// Effect/HUD buffers
|
// Effect/HUD buffers
|
||||||
GLuint mPipelineTexture[NumPipelineTextures];
|
GLuint mPipelineTexture[NumPipelineTextures];
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -31,55 +31,70 @@
|
||||||
#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");
|
SampleIndex.Init(*mShader, "SampleIndex");
|
||||||
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");
|
||||||
|
Scale.Init(*mShader, "Scale");
|
||||||
|
Offset.Init(*mShader, "Offset");
|
||||||
|
SampleIndex.Init(*mShader, "SampleIndex");
|
||||||
|
mMultisample = multisample;
|
||||||
}
|
}
|
||||||
shader.Bind();
|
mShader->Bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
FString FSSAOShader::GetDefines(int mode)
|
FString FSSAOShader::GetDefines(int mode, bool multisample)
|
||||||
{
|
{
|
||||||
|
// Must match quality values in FGLRenderBuffers::CreateAmbientOcclusion
|
||||||
int numDirections, numSteps;
|
int numDirections, numSteps;
|
||||||
switch (gl_ssao)
|
switch (gl_ssao)
|
||||||
{
|
{
|
||||||
|
@ -96,6 +111,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 +135,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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 SampleIndex;
|
||||||
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;
|
||||||
|
@ -37,6 +39,9 @@ public:
|
||||||
FBufferedUniform1f RadiusToScreen;
|
FBufferedUniform1f RadiusToScreen;
|
||||||
FBufferedUniform1f AOMultiplier;
|
FBufferedUniform1f AOMultiplier;
|
||||||
FBufferedUniform1f AOStrength;
|
FBufferedUniform1f AOStrength;
|
||||||
|
FBufferedUniform2f Scale;
|
||||||
|
FBufferedUniform2f Offset;
|
||||||
|
FBufferedUniform1i SampleIndex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Quality
|
enum Quality
|
||||||
|
@ -48,9 +53,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 +77,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
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -7,7 +7,7 @@ uniform float BlurSharpness;
|
||||||
uniform vec2 InvFullResolution;
|
uniform vec2 InvFullResolution;
|
||||||
uniform float PowExponent;
|
uniform float PowExponent;
|
||||||
|
|
||||||
#define KERNEL_RADIUS 7.0
|
#define KERNEL_RADIUS 3.0
|
||||||
|
|
||||||
float CrossBilateralWeight(float r, float sampleDepth, float centerDepth)
|
float CrossBilateralWeight(float r, float sampleDepth, float centerDepth)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,7 @@ out vec4 FragColor;
|
||||||
#if defined(MULTISAMPLE)
|
#if defined(MULTISAMPLE)
|
||||||
uniform sampler2DMS DepthTexture;
|
uniform sampler2DMS DepthTexture;
|
||||||
uniform sampler2DMS ColorTexture;
|
uniform sampler2DMS ColorTexture;
|
||||||
uniform int SampleCount;
|
uniform int SampleIndex;
|
||||||
#else
|
#else
|
||||||
uniform sampler2D DepthTexture;
|
uniform sampler2D DepthTexture;
|
||||||
uniform sampler2D ColorTexture;
|
uniform sampler2D ColorTexture;
|
||||||
|
@ -18,6 +18,12 @@ uniform float InverseDepthRangeB;
|
||||||
uniform vec2 Scale;
|
uniform vec2 Scale;
|
||||||
uniform vec2 Offset;
|
uniform vec2 Offset;
|
||||||
|
|
||||||
|
float normalizeDepth(float depth)
|
||||||
|
{
|
||||||
|
float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0);
|
||||||
|
return 1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB);
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 uv = Offset + TexCoord * Scale;
|
vec2 uv = Offset + TexCoord * Scale;
|
||||||
|
@ -28,19 +34,13 @@ void main()
|
||||||
ivec2 texSize = textureSize(DepthTexture, 0);
|
ivec2 texSize = textureSize(DepthTexture, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Use floor here because as we downscale the sampling error has to remain uniform to prevent
|
ivec2 ipos = ivec2(max(uv * vec2(texSize), vec2(0.0)));
|
||||||
// noise in the depth values.
|
|
||||||
ivec2 ipos = ivec2(max(floor(uv * vec2(texSize) - 0.75), vec2(0.0)));
|
|
||||||
|
|
||||||
#if defined(MULTISAMPLE)
|
#if defined(MULTISAMPLE)
|
||||||
float depth = 0.0;
|
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, SampleIndex).a != 0.0 ? texelFetch(DepthTexture, ipos, SampleIndex).x : 1.0);
|
||||||
for (int i = 0; i < SampleCount; i++)
|
|
||||||
depth += texelFetch(ColorTexture, ipos, i).a != 0.0 ? texelFetch(DepthTexture, ipos, i).x : 1.0;
|
|
||||||
depth /= float(SampleCount);
|
|
||||||
#else
|
#else
|
||||||
float depth = texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0;
|
float depth = normalizeDepth(texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0);
|
FragColor = vec4(depth, 0.0, 0.0, 1.0);
|
||||||
FragColor = vec4(1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB), 0.0, 0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,18 @@ uniform float AOMultiplier;
|
||||||
|
|
||||||
uniform float AOStrength;
|
uniform float AOStrength;
|
||||||
|
|
||||||
|
uniform vec2 Scale;
|
||||||
|
uniform vec2 Offset;
|
||||||
|
|
||||||
uniform sampler2D DepthTexture;
|
uniform sampler2D DepthTexture;
|
||||||
|
|
||||||
|
#if defined(MULTISAMPLE)
|
||||||
|
uniform sampler2DMS NormalTexture;
|
||||||
|
uniform int SampleIndex;
|
||||||
|
#else
|
||||||
|
uniform sampler2D NormalTexture;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_RANDOM_TEXTURE)
|
#if defined(USE_RANDOM_TEXTURE)
|
||||||
uniform sampler2D RandomTexture;
|
uniform sampler2D RandomTexture;
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,21 +38,36 @@ vec3 FetchViewPos(vec2 uv)
|
||||||
return vec3((UVToViewA * uv + UVToViewB) * z, z);
|
return vec3((UVToViewA * uv + UVToViewB) * z, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 MinDiff(vec3 p, vec3 pr, vec3 pl)
|
#if defined(MULTISAMPLE)
|
||||||
|
vec3 SampleNormal(vec2 uv)
|
||||||
{
|
{
|
||||||
vec3 v1 = pr - p;
|
ivec2 texSize = textureSize(NormalTexture);
|
||||||
vec3 v2 = p - pl;
|
ivec2 ipos = ivec2(uv * vec2(texSize));
|
||||||
return (dot(v1, v1) < dot(v2, v2)) ? v1 : v2;
|
return texelFetch(NormalTexture, ipos, SampleIndex).xyz * 2.0 - 1.0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
// Reconstruct eye space normal from nearest neighbors
|
vec3 SampleNormal(vec2 uv)
|
||||||
vec3 ReconstructNormal(vec3 p)
|
|
||||||
{
|
{
|
||||||
vec3 pr = FetchViewPos(TexCoord + vec2(InvFullResolution.x, 0));
|
ivec2 texSize = textureSize(NormalTexture, 0);
|
||||||
vec3 pl = FetchViewPos(TexCoord + vec2(-InvFullResolution.x, 0));
|
ivec2 ipos = ivec2(uv * vec2(texSize));
|
||||||
vec3 pt = FetchViewPos(TexCoord + vec2(0, InvFullResolution.y));
|
return texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0;
|
||||||
vec3 pb = FetchViewPos(TexCoord + vec2(0, -InvFullResolution.y));
|
}
|
||||||
return normalize(cross(MinDiff(p, pr, pl), MinDiff(p, pt, pb)));
|
#endif
|
||||||
|
|
||||||
|
// Look up the eye space normal for the specified texture coordinate
|
||||||
|
vec3 FetchNormal(vec2 uv)
|
||||||
|
{
|
||||||
|
vec3 normal = SampleNormal(Offset + uv * Scale);
|
||||||
|
if (length(normal) > 0.1)
|
||||||
|
{
|
||||||
|
normal = normalize(normal);
|
||||||
|
normal.z = -normal.z;
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return vec3(0.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute normalized 2D direction
|
// Compute normalized 2D direction
|
||||||
|
@ -106,7 +131,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 = FetchNormal(TexCoord);
|
||||||
float occlusion = ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength);
|
float occlusion = viewNormal != vec3(0.0) ? ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength) : 1.0;
|
||||||
|
|
||||||
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
|
FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -17,20 +17,21 @@ uniform vec2 Offset;
|
||||||
void main()
|
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(uv * vec2(texSize));
|
||||||
|
|
||||||
#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;
|
||||||
|
|
Loading…
Reference in a new issue