mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 03:27:48 +02:00
Finally, a clean HBAO!
This commit is contained in:
parent
dee0a6afa2
commit
94a162893a
7 changed files with 134 additions and 105 deletions
|
@ -222,7 +222,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
||||||
#else
|
#else
|
||||||
numSamples{ 16 },
|
numSamples{ 16 },
|
||||||
#endif
|
#endif
|
||||||
resolutionLevel{ 1 },
|
resolutionLevel{ 2 },
|
||||||
blurRadius{ 4 },
|
blurRadius{ 4 },
|
||||||
ditheringEnabled{ true },
|
ditheringEnabled{ true },
|
||||||
borderingEnabled{ true },
|
borderingEnabled{ true },
|
||||||
|
@ -235,6 +235,9 @@ AmbientOcclusionEffect::AOParameters::AOParameters() {
|
||||||
_radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
|
_radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
|
||||||
_ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f };
|
_ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f };
|
||||||
_sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f };
|
_sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
AmbientOcclusionEffect::BlurParameters::BlurParameters() {
|
||||||
_blurInfo = { 1.0f, 3.0f, 2.0f, 0.0f };
|
_blurInfo = { 1.0f, 3.0f, 2.0f, 0.0f };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,14 +272,11 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
||||||
current.y = 1.0f / (1.0f - config.falloffAngle);
|
current.y = 1.0f / (1.0f - config.falloffAngle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.edgeSharpness != _aoParametersBuffer->getEdgeSharpness()) {
|
if (config.edgeSharpness != _hblurParametersBuffer.get().getEdgeSharpness()) {
|
||||||
auto& current = _aoParametersBuffer.edit()._blurInfo;
|
auto& hblur = _hblurParametersBuffer.edit()._blurInfo;
|
||||||
current.x = config.edgeSharpness;
|
auto& vblur = _vblurParametersBuffer.edit()._blurInfo;
|
||||||
}
|
hblur.x = config.edgeSharpness;
|
||||||
|
vblur.x = config.edgeSharpness;
|
||||||
if (config.blurDeviation != _aoParametersBuffer->getBlurDeviation()) {
|
|
||||||
auto& current = _aoParametersBuffer.edit()._blurInfo;
|
|
||||||
current.z = config.blurDeviation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
|
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
|
||||||
|
@ -327,9 +327,11 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
||||||
shouldUpdateBlurs = true;
|
shouldUpdateBlurs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.blurRadius != _aoParametersBuffer.get().getBlurRadius()) {
|
if (config.blurRadius != _hblurParametersBuffer.get().getBlurRadius()) {
|
||||||
auto& current = _aoParametersBuffer.edit()._blurInfo;
|
auto& hblur = _hblurParametersBuffer.edit()._blurInfo;
|
||||||
current.y = (float)config.blurRadius;
|
auto& vblur = _vblurParametersBuffer.edit()._blurInfo;
|
||||||
|
hblur.y = (float)config.blurRadius;
|
||||||
|
vblur.y = (float)config.blurRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
|
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
|
||||||
|
@ -353,31 +355,47 @@ void AmbientOcclusionEffect::updateBlurParameters() {
|
||||||
auto& vblur = _vblurParametersBuffer.edit();
|
auto& vblur = _vblurParametersBuffer.edit();
|
||||||
auto& hblur = _hblurParametersBuffer.edit();
|
auto& hblur = _hblurParametersBuffer.edit();
|
||||||
auto frameSize = _framebuffer->getSourceFrameSize();
|
auto frameSize = _framebuffer->getSourceFrameSize();
|
||||||
|
if (_framebuffer->isStereo()) {
|
||||||
|
frameSize.x >>= 1;
|
||||||
|
}
|
||||||
|
const auto occlusionSize = divideRoundUp(frameSize, resolutionScale);
|
||||||
|
|
||||||
hblur.scaleHeight.x = 1.0f / frameSize.x;
|
// Occlusion UV limit
|
||||||
hblur.scaleHeight.y = float(resolutionScale) / frameSize.x;
|
hblur._blurInfo.z = occlusionSize.x / float(frameSize.x);
|
||||||
hblur.scaleHeight.z = frameSize.y / resolutionScale;
|
hblur._blurInfo.w = occlusionSize.y / float(frameSize.y);
|
||||||
|
|
||||||
vblur.scaleHeight.x = 1.0f / frameSize.y;
|
vblur._blurInfo.z = 1.0f;
|
||||||
vblur.scaleHeight.y = float(resolutionScale) / frameSize.y;
|
vblur._blurInfo.w = occlusionSize.y / float(frameSize.y);
|
||||||
vblur.scaleHeight.z = frameSize.y;
|
|
||||||
|
// Depth axis
|
||||||
|
hblur._blurAxis.x = 1.0f / occlusionSize.x;
|
||||||
|
hblur._blurAxis.y = 0.0f;
|
||||||
|
|
||||||
|
vblur._blurAxis.x = 0.0f;
|
||||||
|
vblur._blurAxis.y = 1.0f / occlusionSize.y;
|
||||||
|
|
||||||
|
// Occlusion axis
|
||||||
|
hblur._blurAxis.z = hblur._blurAxis.x * hblur._blurInfo.z;
|
||||||
|
hblur._blurAxis.w = 0.0f;
|
||||||
|
|
||||||
|
vblur._blurAxis.z = 0.0f;
|
||||||
|
vblur._blurAxis.w = vblur._blurAxis.y * vblur._blurInfo.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmbientOcclusionEffect::updateFramebufferSizes() {
|
void AmbientOcclusionEffect::updateFramebufferSizes() {
|
||||||
auto& params = _aoParametersBuffer.edit();
|
auto& params = _aoParametersBuffer.edit();
|
||||||
const int widthScale = _framebuffer->isStereo() & 1;
|
const int widthScale = _framebuffer->isStereo() & 1;
|
||||||
auto sourceFrameSize = _framebuffer->getSourceFrameSize();
|
auto sourceFrameSideSize = _framebuffer->getSourceFrameSize();
|
||||||
const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel();
|
sourceFrameSideSize.x >>= widthScale;
|
||||||
const float resolutionScale = powf(0.5f, resolutionLevel);
|
|
||||||
// Depth is at maximum half depth
|
const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel();
|
||||||
const int depthResolutionLevel = std::min(1, resolutionLevel);
|
// Depth is at maximum half depth
|
||||||
const float depthResolutionScale = powf(2.0f, depthResolutionLevel);
|
const int depthResolutionLevel = getDepthResolutionLevel();
|
||||||
auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions();
|
const auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSideSize, 1 << depthResolutionLevel);
|
||||||
auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSize, depthResolutionLevel);
|
const auto occlusionFrameSize = divideRoundUp(sourceFrameSideSize, 1 << resolutionLevel);
|
||||||
|
auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions();
|
||||||
|
|
||||||
sourceFrameSize.x >>= widthScale;
|
|
||||||
normalTextureSize.x >>= widthScale;
|
normalTextureSize.x >>= widthScale;
|
||||||
occlusionDepthFrameSize.x >>= widthScale;
|
|
||||||
|
|
||||||
params._sideSizes[0].x = normalTextureSize.x;
|
params._sideSizes[0].x = normalTextureSize.x;
|
||||||
params._sideSizes[0].y = normalTextureSize.y;
|
params._sideSizes[0].y = normalTextureSize.y;
|
||||||
|
@ -386,7 +404,7 @@ void AmbientOcclusionEffect::updateFramebufferSizes() {
|
||||||
|
|
||||||
params._sideSizes[1].x = params._sideSizes[0].x;
|
params._sideSizes[1].x = params._sideSizes[0].x;
|
||||||
params._sideSizes[1].y = params._sideSizes[0].y;
|
params._sideSizes[1].y = params._sideSizes[0].y;
|
||||||
auto occlusionSplitSize = divideRoundUp(sourceFrameSize, 1 << (resolutionLevel + SSAO_USE_QUAD_SPLIT));
|
auto occlusionSplitSize = divideRoundUp(occlusionFrameSize, SSAO_SPLIT_COUNT);
|
||||||
params._sideSizes[1].z = occlusionSplitSize.x;
|
params._sideSizes[1].z = occlusionSplitSize.x;
|
||||||
params._sideSizes[1].w = occlusionSplitSize.y;
|
params._sideSizes[1].w = occlusionSplitSize.y;
|
||||||
}
|
}
|
||||||
|
@ -491,7 +509,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
// We need to take the rounded up resolution.
|
// We need to take the rounded up resolution.
|
||||||
auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel);
|
auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel);
|
||||||
auto firstBlurViewport = sourceViewport;
|
auto firstBlurViewport = sourceViewport;
|
||||||
firstBlurViewport.w = divideRoundUp(firstBlurViewport.w, 1 << resolutionLevel);
|
firstBlurViewport.w = occlusionViewport.w;
|
||||||
|
|
||||||
if (!_gpuTimer) {
|
if (!_gpuTimer) {
|
||||||
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
|
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
|
||||||
|
@ -550,9 +568,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
|
|
||||||
batch.resetViewTransform();
|
batch.resetViewTransform();
|
||||||
|
|
||||||
Transform model;
|
|
||||||
batch.setProjectionTransform(glm::mat4());
|
batch.setProjectionTransform(glm::mat4());
|
||||||
batch.setModelTransform(model);
|
batch.setModelTransform(Transform());
|
||||||
|
|
||||||
batch.pushProfileRange("Depth Mip Generation");
|
batch.pushProfileRange("Depth Mip Generation");
|
||||||
// We need this with the mips levels
|
// We need this with the mips levels
|
||||||
|
@ -578,11 +595,12 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
postPixelOffset.y - prePixelOffset.y,
|
postPixelOffset.y - prePixelOffset.y,
|
||||||
0.0f
|
0.0f
|
||||||
);
|
);
|
||||||
|
Transform model;
|
||||||
|
|
||||||
model.setScale(uvScale);
|
model.setScale(uvScale);
|
||||||
model.setTranslation(uvTranslate);
|
model.setTranslation(uvTranslate);
|
||||||
|
batch.setModelTransform(model);
|
||||||
}
|
}
|
||||||
batch.setModelTransform(model);
|
|
||||||
|
|
||||||
// Build face normals pass
|
// Build face normals pass
|
||||||
batch.setViewportTransform(normalViewport);
|
batch.setViewportTransform(normalViewport);
|
||||||
|
@ -608,11 +626,12 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||||
{
|
{
|
||||||
const auto uvScale = glm::vec3(
|
const auto uvScale = glm::vec3(
|
||||||
(splitSize.x * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
(splitSize.x * SSAO_SPLIT_COUNT) / float(occlusionViewport.z),
|
||||||
(splitSize.y * SSAO_SPLIT_COUNT * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
(splitSize.y * SSAO_SPLIT_COUNT) / float(occlusionViewport.w),
|
||||||
1.0f);
|
1.0f);
|
||||||
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionDepthSize);
|
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionViewport.z, occlusionViewport.w);
|
||||||
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize.x, splitSize.y);
|
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize);
|
||||||
|
Transform model;
|
||||||
|
|
||||||
batch.setViewportTransform(splitViewport);
|
batch.setViewportTransform(splitViewport);
|
||||||
|
|
||||||
|
@ -635,13 +654,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
batch.setViewportTransform(occlusionViewport);
|
batch.setViewportTransform(occlusionViewport);
|
||||||
{
|
model.setIdentity();
|
||||||
const auto uvScale = glm::vec3(
|
|
||||||
(occlusionViewport.z * depthResolutionScale) / (occlusionDepthSize.x * resolutionScale),
|
|
||||||
(occlusionViewport.w * depthResolutionScale) / (occlusionDepthSize.y * resolutionScale),
|
|
||||||
1.0f);
|
|
||||||
model.setScale(uvScale);
|
|
||||||
}
|
|
||||||
batch.setModelTransform(model);
|
batch.setModelTransform(model);
|
||||||
batch.setFramebuffer(occlusionFBO);
|
batch.setFramebuffer(occlusionFBO);
|
||||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||||
|
@ -666,8 +679,15 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
PROFILE_RANGE_BATCH(batch, "Bilateral Blur");
|
PROFILE_RANGE_BATCH(batch, "Bilateral Blur");
|
||||||
// Blur 1st pass
|
// Blur 1st pass
|
||||||
batch.pushProfileRange("Horizontal");
|
batch.pushProfileRange("Horizontal");
|
||||||
model.setScale(resolutionScale);
|
{
|
||||||
batch.setModelTransform(model);
|
const auto uvScale = glm::vec3(
|
||||||
|
occlusionViewport.z / float(sourceViewport.z),
|
||||||
|
occlusionViewport.w / float(sourceViewport.w),
|
||||||
|
1.0f);
|
||||||
|
Transform model;
|
||||||
|
model.setScale(uvScale);
|
||||||
|
batch.setModelTransform(model);
|
||||||
|
}
|
||||||
batch.setViewportTransform(firstBlurViewport);
|
batch.setViewportTransform(firstBlurViewport);
|
||||||
batch.setFramebuffer(occlusionBlurredFBO);
|
batch.setFramebuffer(occlusionBlurredFBO);
|
||||||
// Use full resolution depth and normal for bilateral upscaling and blur
|
// Use full resolution depth and normal for bilateral upscaling and blur
|
||||||
|
@ -680,8 +700,16 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
|
|
||||||
// Blur 2nd pass
|
// Blur 2nd pass
|
||||||
batch.pushProfileRange("Vertical");
|
batch.pushProfileRange("Vertical");
|
||||||
model.setScale(glm::vec3(1.0f, resolutionScale, 1.0f));
|
{
|
||||||
batch.setModelTransform(model);
|
const auto uvScale = glm::vec3(
|
||||||
|
1.0f,
|
||||||
|
occlusionViewport.w / float(sourceViewport.w),
|
||||||
|
1.0f);
|
||||||
|
|
||||||
|
Transform model;
|
||||||
|
model.setScale(uvScale);
|
||||||
|
batch.setModelTransform(model);
|
||||||
|
}
|
||||||
batch.setViewportTransform(sourceViewport);
|
batch.setViewportTransform(sourceViewport);
|
||||||
batch.setFramebuffer(occlusionFBO);
|
batch.setFramebuffer(occlusionFBO);
|
||||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer);
|
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer);
|
||||||
|
|
|
@ -149,14 +149,11 @@ public:
|
||||||
float getPerspectiveScale() const { return _resolutionInfo.z; }
|
float getPerspectiveScale() const { return _resolutionInfo.z; }
|
||||||
float getObscuranceLevel() const { return _radiusInfo.w; }
|
float getObscuranceLevel() const { return _radiusInfo.w; }
|
||||||
float getFalloffAngle() const { return (float)_ditheringInfo.z; }
|
float getFalloffAngle() const { return (float)_ditheringInfo.z; }
|
||||||
float getEdgeSharpness() const { return (float)_blurInfo.x; }
|
|
||||||
float getBlurDeviation() const { return _blurInfo.z; }
|
|
||||||
|
|
||||||
float getNumSpiralTurns() const { return _sampleInfo.z; }
|
float getNumSpiralTurns() const { return _sampleInfo.z; }
|
||||||
int getNumSamples() const { return (int)_sampleInfo.x; }
|
int getNumSamples() const { return (int)_sampleInfo.x; }
|
||||||
bool isFetchMipsEnabled() const { return _sampleInfo.w; }
|
bool isFetchMipsEnabled() const { return _sampleInfo.w; }
|
||||||
|
|
||||||
int getBlurRadius() const { return (int)_blurInfo.y; }
|
|
||||||
bool isDitheringEnabled() const { return _ditheringInfo.x; }
|
bool isDitheringEnabled() const { return _ditheringInfo.x; }
|
||||||
bool isBorderingEnabled() const { return _ditheringInfo.w; }
|
bool isBorderingEnabled() const { return _ditheringInfo.w; }
|
||||||
};
|
};
|
||||||
|
@ -165,11 +162,14 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
|
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
|
||||||
class BlurParameters {
|
class BlurParameters : public AmbientOcclusionBlurParams {
|
||||||
public:
|
public:
|
||||||
glm::vec4 scaleHeight{ 0.0f };
|
|
||||||
|
|
||||||
BlurParameters() {}
|
BlurParameters();
|
||||||
|
|
||||||
|
float getEdgeSharpness() const { return (float)_blurInfo.x; }
|
||||||
|
int getBlurRadius() const { return (int)_blurInfo.y; }
|
||||||
|
|
||||||
};
|
};
|
||||||
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
|
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
|
||||||
|
|
||||||
|
|
|
@ -115,14 +115,6 @@ int doFetchMips() {
|
||||||
return int(params._sampleInfo.w);
|
return int(params._sampleInfo.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getBlurEdgeSharpness() {
|
|
||||||
return params._blurInfo.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getBlurRadius() {
|
|
||||||
return int(params._blurInfo.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
<@func declareSamplingDisk()@>
|
<@func declareSamplingDisk()@>
|
||||||
|
@ -247,6 +239,11 @@ float getZEyeAtUV(vec2 texCoord, int level) {
|
||||||
return -textureLod(depthPyramidTex, texCoord, level).x;
|
return -textureLod(depthPyramidTex, texCoord, level).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float getZEyeAtUV(ivec4 side, vec2 texCoord, int level) {
|
||||||
|
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
|
||||||
|
return getZEyeAtUV(texCoord, level);
|
||||||
|
}
|
||||||
|
|
||||||
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
|
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
|
||||||
return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
|
return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
|
||||||
}
|
}
|
||||||
|
@ -417,37 +414,42 @@ float evalVisibilityHBAO(ivec4 side, vec2 fragUVPos, vec2 invSideImageSize, vec2
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
||||||
<@func declareBlurPass(axis)@>
|
<@func declareBlurPass()@>
|
||||||
|
|
||||||
<$declarePackOcclusionDepth()$>
|
|
||||||
<$declareAmbientOcclusion()$>
|
<$declareAmbientOcclusion()$>
|
||||||
<$declareFetchDepthPyramidMap()$>
|
<$declareFetchDepthPyramidMap()$>
|
||||||
|
<$declarePackOcclusionDepth()$>
|
||||||
|
|
||||||
// the source occlusion texture
|
// the source occlusion texture
|
||||||
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
|
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
|
||||||
|
|
||||||
struct BlurParams {
|
|
||||||
vec4 scaleHeight;
|
|
||||||
};
|
|
||||||
|
|
||||||
layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
|
layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
|
||||||
BlurParams blurParams;
|
AmbientOcclusionBlurParams blurParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
float getOcclusionBlurScale() {
|
vec2 getBlurOcclusionAxis() {
|
||||||
return blurParams.scaleHeight.x;
|
return blurParams._blurAxis.zw;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getDepthBlurScale() {
|
vec2 getBlurDepthAxis() {
|
||||||
return blurParams.scaleHeight.y;
|
return blurParams._blurAxis.xy;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getBlurImageHeight() {
|
vec2 getBlurOcclusionUVLimit() {
|
||||||
return int(blurParams.scaleHeight.z);
|
return blurParams._blurInfo.zw;
|
||||||
}
|
}
|
||||||
|
|
||||||
float fetchOcclusion(vec2 coords) {
|
float getBlurEdgeSharpness() {
|
||||||
vec3 raw = texture(occlusionMap, coords, 0).xyz;
|
return blurParams._blurInfo.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBlurRadius() {
|
||||||
|
return int(blurParams._blurInfo.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fetchOcclusion(ivec4 side, vec2 texCoord) {
|
||||||
|
texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo());
|
||||||
|
vec3 raw = textureLod(occlusionMap, texCoord, 0).xyz;
|
||||||
return raw.x;
|
return raw.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,19 +460,19 @@ float evalBlurCoefficient(vec2 blurScales, float radialDistance, float zDistance
|
||||||
return exp2(dot(blurScales, distances*distances));
|
return exp2(dot(blurScales, distances*distances));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 evalTapWeightedValue(vec2 blurScales, ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float fragDepth) {
|
vec2 evalTapWeightedValue(vec2 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, vec2 depthTexCoord, float fragDepth) {
|
||||||
ivec2 tapOffset = <$axis$> * r;
|
vec2 tapOcclusionTexCoord = getBlurOcclusionAxis() * r + occlusionTexCoord;
|
||||||
ivec2 tapPixelCoord = destPixelCoord + ivec2(tapOffset);
|
vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit();
|
||||||
|
|
||||||
if ((tapPixelCoord.x < side.y || tapPixelCoord.x >= side.z + side.y) || (tapPixelCoord.y < 0 || tapPixelCoord.y >= getBlurImageHeight())) {
|
if (tapOcclusionTexCoord.x < side.x || tapOcclusionTexCoord.x >= (side.x + occlusionTexCoordLimits.x)
|
||||||
|
|| tapOcclusionTexCoord.y < 0 || tapOcclusionTexCoord.y >= occlusionTexCoordLimits.y) {
|
||||||
return vec2(0.0);
|
return vec2(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 tapTexCoord = scaledTexCoord + tapOffset * getOcclusionBlurScale();
|
float tapOcclusion = fetchOcclusion(side, tapOcclusionTexCoord);
|
||||||
float tapOcclusion = fetchOcclusion(tapTexCoord);
|
|
||||||
|
|
||||||
tapTexCoord = fullTexCoord + tapOffset * getDepthBlurScale();
|
vec2 tapDepthTexCoord = getBlurDepthAxis() * r + depthTexCoord;
|
||||||
float tapDepth = getZEyeAtUV(tapTexCoord, 0);
|
float tapDepth = getZEyeAtUV(side, tapDepthTexCoord, 0);
|
||||||
|
|
||||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
||||||
float zDistance = tapDepth - fragDepth;
|
float zDistance = tapDepth - fragDepth;
|
||||||
|
@ -479,11 +481,11 @@ vec2 evalTapWeightedValue(vec2 blurScales, ivec3 side, int r, ivec2 destPixelCoo
|
||||||
return vec2(tapOcclusion * weight, weight);
|
return vec2(tapOcclusion * weight, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord) {
|
vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 depthTexCoord) {
|
||||||
// Stereo side info
|
// Stereo side info
|
||||||
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
|
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
|
||||||
|
|
||||||
float fragDepth = getZEyeAtUV(fullTexCoord, 0);
|
float fragDepth = getZEyeAtUV(side, depthTexCoord, 0);
|
||||||
vec2 weightedSums = vec2(0.0);
|
vec2 weightedSums = vec2(0.0);
|
||||||
|
|
||||||
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
|
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
|
||||||
|
@ -494,17 +496,17 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
|
||||||
|
|
||||||
// negative side first
|
// negative side first
|
||||||
for (int r = -blurRadius; r <= -1; ++r) {
|
for (int r = -blurRadius; r <= -1; ++r) {
|
||||||
weightedSums += evalTapWeightedValue(blurScales, side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth);
|
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Central pixel contribution
|
// Central pixel contribution
|
||||||
float mainWeight = 1.0;
|
float mainWeight = 1.0;
|
||||||
float pixelOcclusion = fetchOcclusion(scaledTexCoord);
|
float pixelOcclusion = fetchOcclusion(side, occlusionTexCoord);
|
||||||
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
|
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
|
||||||
|
|
||||||
// then positive side
|
// then positive side
|
||||||
for (int r = 1; r <= blurRadius; ++r) {
|
for (int r = 1; r <= blurRadius; ++r) {
|
||||||
weightedSums += evalTapWeightedValue(blurScales, side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth);
|
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final normalization
|
// Final normalization
|
||||||
|
|
|
@ -28,11 +28,9 @@ void main(void) {
|
||||||
// Gather the four splits of the occlusion result back into an interleaved full size
|
// Gather the four splits of the occlusion result back into an interleaved full size
|
||||||
// result (at the resolution level, of course)
|
// result (at the resolution level, of course)
|
||||||
ivec2 destPixelCoord = ivec2(gl_FragCoord.xy);
|
ivec2 destPixelCoord = ivec2(gl_FragCoord.xy);
|
||||||
ivec2 sourcePixelCoord = destPixelCoord / SSAO_SPLIT_COUNT;
|
ivec2 sourcePixelCoord = destPixelCoord >> SSAO_SPLIT_LOG2_COUNT;
|
||||||
ivec2 splitImageSize = getWidthHeightRoundUp(getResolutionLevel()+SSAO_SPLIT_LOG2_COUNT);
|
ivec2 modPixelCoord = destPixelCoord & (SSAO_SPLIT_COUNT-1);
|
||||||
ivec2 modPixelCoord = destPixelCoord % ivec2(SSAO_SPLIT_COUNT);
|
int occlusionMapIndex = modPixelCoord.x + (modPixelCoord.y << SSAO_SPLIT_LOG2_COUNT);
|
||||||
int occlusionMapIndex = modPixelCoord.x + modPixelCoord.y*SSAO_SPLIT_COUNT;
|
|
||||||
vec2 sourceUV = (sourcePixelCoord + vec2(0.5)) / splitImageSize;
|
|
||||||
|
|
||||||
outFragColor = texture(occlusionMaps, vec3(sourceUV, occlusionMapIndex));
|
outFragColor = texelFetch(occlusionMaps, ivec3(sourcePixelCoord, occlusionMapIndex), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
|
|
||||||
// Hack comment
|
// Hack comment
|
||||||
|
|
||||||
const ivec2 horizontal = ivec2(1,0);
|
<$declareBlurPass()$>
|
||||||
<$declareBlurPass(horizontal)$>
|
|
||||||
|
|
||||||
layout(location=0) in vec4 varTexCoord0;
|
layout(location=0) in vec4 varTexCoord0;
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,12 @@
|
||||||
|
|
||||||
// Hack comment
|
// Hack comment
|
||||||
|
|
||||||
const ivec2 vertical = ivec2(0,1);
|
<$declareBlurPass()$>
|
||||||
<$declareBlurPass(vertical)$>
|
|
||||||
|
|
||||||
layout(location=0) in vec4 varTexCoord0;
|
layout(location=0) in vec4 varTexCoord0;
|
||||||
|
|
||||||
layout(location=0) out vec4 outFragColor;
|
layout(location=0) out vec4 outFragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
float occlusion = getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw).x;
|
outFragColor = vec4(getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw), 1.0);
|
||||||
outFragColor = vec4(occlusion, 0.0, 0.0, occlusion);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
// glsl / C++ compatible source as interface for ambient occlusion
|
// glsl / C++ compatible source as interface for ambient occlusion
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
# define SSAO_VEC4 glm::vec4
|
# define SSAO_VEC4 glm::vec4
|
||||||
# define SSAO_IVEC4 glm::ivec4
|
# define SSAO_MAT4 glm::mat4
|
||||||
#else
|
#else
|
||||||
# define SSAO_VEC4 vec4
|
# define SSAO_VEC4 vec4
|
||||||
# define SSAO_IVEC4 ivec4
|
# define SSAO_MAT4 mat4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct AmbientOcclusionParams {
|
struct AmbientOcclusionParams {
|
||||||
|
@ -38,7 +38,6 @@ struct AmbientOcclusionParams {
|
||||||
SSAO_VEC4 _radiusInfo;
|
SSAO_VEC4 _radiusInfo;
|
||||||
SSAO_VEC4 _ditheringInfo;
|
SSAO_VEC4 _ditheringInfo;
|
||||||
SSAO_VEC4 _sampleInfo;
|
SSAO_VEC4 _sampleInfo;
|
||||||
SSAO_VEC4 _blurInfo;
|
|
||||||
SSAO_VEC4 _sideSizes[2];
|
SSAO_VEC4 _sideSizes[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,6 +45,11 @@ struct AmbientOcclusionFrameParams {
|
||||||
SSAO_VEC4 _angleInfo;
|
SSAO_VEC4 _angleInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AmbientOcclusionBlurParams {
|
||||||
|
SSAO_VEC4 _blurInfo;
|
||||||
|
SSAO_VEC4 _blurAxis;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // RENDER_UTILS_SHADER_CONSTANTS_H
|
#endif // RENDER_UTILS_SHADER_CONSTANTS_H
|
||||||
|
|
||||||
// <@if 1@>
|
// <@if 1@>
|
||||||
|
|
Loading…
Reference in a new issue