mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 15:02:01 +00:00
SSAO math bug fixes
This commit is contained in:
parent
00e72028ef
commit
bb79dcb634
8 changed files with 125 additions and 83 deletions
|
@ -124,7 +124,7 @@ CVAR(Float, gl_ssao_strength, 0.7, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
CVAR(Int, gl_ssao_debug, 0, 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, 16.0f, 0)
|
||||||
{
|
{
|
||||||
if (self < 0.1f) self = 0.1f;
|
if (self < 0.1f) self = 0.1f;
|
||||||
}
|
}
|
||||||
|
@ -178,6 +178,13 @@ 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->AmbientFB0);
|
||||||
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
|
glViewport(0, 0, mBuffers->AmbientWidth, mBuffers->AmbientHeight);
|
||||||
|
@ -196,8 +203,8 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
mLinearDepthShader->LinearizeDepthB.Set(MAX(1.0f / GetZNear(), 1.e-8f));
|
mLinearDepthShader->LinearizeDepthB.Set(MAX(1.0f / GetZNear(), 1.e-8f));
|
||||||
mLinearDepthShader->InverseDepthRangeA.Set(1.0f);
|
mLinearDepthShader->InverseDepthRangeA.Set(1.0f);
|
||||||
mLinearDepthShader->InverseDepthRangeB.Set(0.0f);
|
mLinearDepthShader->InverseDepthRangeB.Set(0.0f);
|
||||||
mLinearDepthShader->Scale.Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
|
mLinearDepthShader->Scale.Set(sceneScaleX, sceneScaleY);
|
||||||
mLinearDepthShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
mLinearDepthShader->Offset.Set(sceneOffsetX, sceneOffsetY);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
||||||
// Apply ambient occlusion
|
// Apply ambient occlusion
|
||||||
|
@ -206,7 +213,7 @@ 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_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);
|
||||||
|
@ -219,44 +226,46 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
mSSAOShader->DepthTexture.Set(0);
|
mSSAOShader->DepthTexture.Set(0);
|
||||||
mSSAOShader->RandomTexture.Set(1);
|
mSSAOShader->RandomTexture.Set(1);
|
||||||
mSSAOShader->NormalTexture.Set(2);
|
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);
|
||||||
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
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
if (gl_ssao_debug < 2)
|
||||||
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
{
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB0);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture1);
|
||||||
mDepthBlurShader->Bind(false);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
mDepthBlurShader->BlurSharpness[false].Set(blurSharpness);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
mDepthBlurShader->InvFullResolution[false].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
mDepthBlurShader->Bind(false);
|
||||||
RenderScreenQuad();
|
mDepthBlurShader->BlurSharpness[false].Set(blurSharpness);
|
||||||
|
mDepthBlurShader->InvFullResolution[false].Set(1.0f / mBuffers->AmbientWidth, 1.0f / mBuffers->AmbientHeight);
|
||||||
|
RenderScreenQuad();
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
glBindFramebuffer(GL_FRAMEBUFFER, mBuffers->AmbientFB1);
|
||||||
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
|
glBindTexture(GL_TEXTURE_2D, mBuffers->AmbientTexture0);
|
||||||
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(1.8f);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
}
|
||||||
|
|
||||||
// Add SSAO back to scene texture:
|
// Add SSAO back to scene texture:
|
||||||
mBuffers->BindSceneFB(false);
|
mBuffers->BindSceneFB(false);
|
||||||
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 > 1)
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glBlendFunc(GL_ONE, GL_ZERO);
|
if (gl_ssao_debug != 0)
|
||||||
else
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
if (gl_ssao_debug == 1)
|
|
||||||
{
|
{
|
||||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
@ -270,8 +279,8 @@ void FGLRenderer::AmbientOccludeScene()
|
||||||
mSSAOCombineShader->AODepthTexture.Set(0);
|
mSSAOCombineShader->AODepthTexture.Set(0);
|
||||||
mSSAOCombineShader->SceneFogTexture.Set(1);
|
mSSAOCombineShader->SceneFogTexture.Set(1);
|
||||||
if (gl_multisample > 1) mSSAOCombineShader->SampleCount.Set(gl_multisample);
|
if (gl_multisample > 1) mSSAOCombineShader->SampleCount.Set(gl_multisample);
|
||||||
mSSAOCombineShader->Scale.Set(mBuffers->AmbientWidth * 2.0f / (float)mScreenViewport.width, mBuffers->AmbientHeight * 2.0f / (float)mScreenViewport.height);
|
mSSAOCombineShader->Scale.Set(sceneScaleX, sceneScaleY);
|
||||||
mSSAOCombineShader->Offset.Set(mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height);
|
mSSAOCombineShader->Offset.Set(sceneOffsetX, sceneOffsetY);
|
||||||
RenderScreenQuad();
|
RenderScreenQuad();
|
||||||
|
|
||||||
FGLDebug::PopGroup();
|
FGLDebug::PopGroup();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +156,8 @@ void FGLRenderBuffers::ClearAmbientOcclusion()
|
||||||
DeleteFrameBuffer(AmbientFB1);
|
DeleteFrameBuffer(AmbientFB1);
|
||||||
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)
|
||||||
|
@ -368,25 +374,31 @@ void FGLRenderBuffers::CreateAmbientOcclusion(int width, int height)
|
||||||
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 i = 0; i < 16; i++)
|
for (int quality = 0; quality < NumAmbientRandomTextures; quality++)
|
||||||
{
|
{
|
||||||
double num_directions = 8.0; // Must be same as the define in ssao.fp
|
int16_t randomValues[16 * 4];
|
||||||
double angle = 2.0 * M_PI * distribution(generator) / num_directions;
|
|
||||||
double x = cos(angle);
|
|
||||||
double y = sin(angle);
|
|
||||||
double z = distribution(generator);
|
|
||||||
double w = distribution(generator);
|
|
||||||
|
|
||||||
randomValues[i * 4 + 0] = (int16_t)clamp(x * 32767.0, -32768.0, 32767.0);
|
for (int i = 0; i < 16; i++)
|
||||||
randomValues[i * 4 + 1] = (int16_t)clamp(y * 32767.0, -32768.0, 32767.0);
|
{
|
||||||
randomValues[i * 4 + 2] = (int16_t)clamp(z * 32767.0, -32768.0, 32767.0);
|
double angle = 2.0 * M_PI * distribution(generator) / numDirections[quality];
|
||||||
randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0);
|
double x = cos(angle);
|
||||||
|
double y = sin(angle);
|
||||||
|
double z = distribution(generator);
|
||||||
|
double w = distribution(generator);
|
||||||
|
|
||||||
|
randomValues[i * 4 + 0] = (int16_t)clamp(x * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 1] = (int16_t)clamp(y * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 2] = (int16_t)clamp(z * 32767.0, -32768.0, 32767.0);
|
||||||
|
randomValues[i * 4 + 3] = (int16_t)clamp(w * 32767.0, -32768.0, 32767.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmbientRandomTexture[quality] = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
AmbientRandomTexture = Create2DTexture("AmbientRandomTexture", GL_RGBA16_SNORM, 4, 4, randomValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -65,7 +65,8 @@ public:
|
||||||
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();
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,8 @@ void FSSAOShader::Bind()
|
||||||
RadiusToScreen.Init(*mShader, "RadiusToScreen");
|
RadiusToScreen.Init(*mShader, "RadiusToScreen");
|
||||||
AOMultiplier.Init(*mShader, "AOMultiplier");
|
AOMultiplier.Init(*mShader, "AOMultiplier");
|
||||||
AOStrength.Init(*mShader, "AOStrength");
|
AOStrength.Init(*mShader, "AOStrength");
|
||||||
|
Scale.Init(*mShader, "Scale");
|
||||||
|
Offset.Init(*mShader, "Offset");
|
||||||
mMultisample = multisample;
|
mMultisample = multisample;
|
||||||
}
|
}
|
||||||
mShader->Bind();
|
mShader->Bind();
|
||||||
|
@ -91,6 +93,7 @@ void FSSAOShader::Bind()
|
||||||
|
|
||||||
FString FSSAOShader::GetDefines(int mode, bool multisample)
|
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
FBufferedUniform1f RadiusToScreen;
|
FBufferedUniform1f RadiusToScreen;
|
||||||
FBufferedUniform1f AOMultiplier;
|
FBufferedUniform1f AOMultiplier;
|
||||||
FBufferedUniform1f AOStrength;
|
FBufferedUniform1f AOStrength;
|
||||||
|
FBufferedUniform2f Scale;
|
||||||
|
FBufferedUniform2f Offset;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Quality
|
enum Quality
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,24 @@ 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, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0);
|
||||||
for (int i = 0; i < SampleCount; i++)
|
float sampleIndex = 0.0;
|
||||||
depth += texelFetch(ColorTexture, ipos, i).a != 0.0 ? texelFetch(DepthTexture, ipos, i).x : 1.0;
|
for (int i = 1; i < SampleCount; i++)
|
||||||
depth /= float(SampleCount);
|
{
|
||||||
|
float hardwareDepth = texelFetch(ColorTexture, ipos, i).a != 0.0 ? texelFetch(DepthTexture, ipos, i).x : 1.0;
|
||||||
|
float sampleDepth = normalizeDepth(hardwareDepth);
|
||||||
|
if (sampleDepth < depth)
|
||||||
|
{
|
||||||
|
depth = sampleDepth;
|
||||||
|
sampleIndex = float(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FragColor = vec4(depth, sampleIndex, 0.0, 1.0);
|
||||||
#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);
|
||||||
|
FragColor = vec4(depth, 0.0, 0.0, 1.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0);
|
|
||||||
FragColor = vec4(1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB), 0.0, 0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@ uniform float AOMultiplier;
|
||||||
|
|
||||||
uniform float AOStrength;
|
uniform float AOStrength;
|
||||||
|
|
||||||
|
uniform vec2 Scale;
|
||||||
|
uniform vec2 Offset;
|
||||||
|
|
||||||
uniform sampler2D DepthTexture;
|
uniform sampler2D DepthTexture;
|
||||||
|
|
||||||
#if defined(MULTISAMPLE)
|
#if defined(MULTISAMPLE)
|
||||||
|
@ -27,42 +30,42 @@ uniform sampler2D RandomTexture;
|
||||||
|
|
||||||
#define PI 3.14159265358979323846
|
#define PI 3.14159265358979323846
|
||||||
|
|
||||||
// Calculate eye space position for the specified texture coordinate
|
// Calculate eye space position for the specified texture coordinate and depth
|
||||||
vec3 FetchViewPos(vec2 uv)
|
vec3 FetchViewPos(vec2 uv, float z)
|
||||||
{
|
{
|
||||||
float z = texture(DepthTexture, uv).x;
|
|
||||||
return vec3((UVToViewA * uv + UVToViewB) * z, z);
|
return vec3((UVToViewA * uv + UVToViewB) * z, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MULTISAMPLE)
|
#if defined(MULTISAMPLE)
|
||||||
vec3 FetchNormal(vec2 uv)
|
vec3 SampleNormal(vec2 uv, float samplerIndex)
|
||||||
{
|
{
|
||||||
ivec2 texSize = textureSize(NormalTexture);
|
ivec2 texSize = textureSize(NormalTexture);
|
||||||
ivec2 ipos = ivec2(uv * vec2(texSize));
|
ivec2 ipos = ivec2(uv * vec2(texSize));
|
||||||
return normalize(texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0);
|
return texelFetch(NormalTexture, ipos, int(samplerIndex)).xyz * 2.0 - 1.0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
vec3 FetchNormal(vec2 uv)
|
vec3 SampleNormal(vec2 uv, float samplerIndex)
|
||||||
{
|
{
|
||||||
return normalize(texture(NormalTexture, uv).xyz * 2.0 - 1.0);
|
ivec2 texSize = textureSize(NormalTexture, 0);
|
||||||
|
ivec2 ipos = ivec2(uv * vec2(texSize));
|
||||||
|
return texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 MinDiff(vec3 p, vec3 pr, vec3 pl)
|
// Look up the eye space normal for the specified texture coordinate
|
||||||
|
vec3 FetchNormal(vec2 uv, float samplerIndex)
|
||||||
{
|
{
|
||||||
vec3 v1 = pr - p;
|
vec3 normal = SampleNormal(Offset + uv * Scale, samplerIndex);
|
||||||
vec3 v2 = p - pl;
|
if (length(normal) > 0.1)
|
||||||
return (dot(v1, v1) < dot(v2, v2)) ? v1 : v2;
|
{
|
||||||
}
|
normal = normalize(normal);
|
||||||
|
normal.z = -normal.z;
|
||||||
// Reconstruct eye space normal from nearest neighbors
|
return normal;
|
||||||
vec3 ReconstructNormal(vec3 p)
|
}
|
||||||
{
|
else
|
||||||
vec3 pr = FetchViewPos(TexCoord + vec2(InvFullResolution.x, 0));
|
{
|
||||||
vec3 pl = FetchViewPos(TexCoord + vec2(-InvFullResolution.x, 0));
|
return vec3(0.0);
|
||||||
vec3 pt = FetchViewPos(TexCoord + vec2(0, InvFullResolution.y));
|
}
|
||||||
vec3 pb = FetchViewPos(TexCoord + vec2(0, -InvFullResolution.y));
|
|
||||||
return normalize(cross(MinDiff(p, pr, pl), MinDiff(p, pt, pb)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute normalized 2D direction
|
// Compute normalized 2D direction
|
||||||
|
@ -113,7 +116,7 @@ float ComputeAO(vec3 viewPosition, vec3 viewNormal)
|
||||||
for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex)
|
for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex)
|
||||||
{
|
{
|
||||||
vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord;
|
vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord;
|
||||||
vec3 samplePos = FetchViewPos(sampleUV);
|
vec3 samplePos = FetchViewPos(sampleUV, texture(DepthTexture, sampleUV).x);
|
||||||
ao += ComputeSampleAO(viewPosition, viewNormal, samplePos);
|
ao += ComputeSampleAO(viewPosition, viewNormal, samplePos);
|
||||||
rayPixels += stepSizePixels;
|
rayPixels += stepSizePixels;
|
||||||
}
|
}
|
||||||
|
@ -125,9 +128,10 @@ float ComputeAO(vec3 viewPosition, vec3 viewNormal)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 viewPosition = FetchViewPos(TexCoord);
|
vec2 depthData = texture(DepthTexture, TexCoord).xy;
|
||||||
//vec3 viewNormal = ReconstructNormal(viewPosition);
|
vec3 viewPosition = FetchViewPos(TexCoord, depthData.x);
|
||||||
vec3 viewNormal = FetchNormal(TexCoord);
|
vec3 viewNormal = FetchNormal(TexCoord, depthData.y);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue