committed by
Mathias Agopian
parent
79a83e8c46
commit
bcde742bbc
@@ -694,20 +694,17 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::bilateralBlurPass(FrameGraph
|
||||
}
|
||||
|
||||
FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, uint8_t srcLevel, uint8_t dstLevel) noexcept {
|
||||
FrameGraphId<FrameGraphTexture> input, uint8_t srcLevel, uint8_t dstLevel, float alpha) noexcept {
|
||||
|
||||
Handle<HwRenderPrimitive> fullScreenRenderPrimitive = mEngine.getFullScreenRenderPrimitive();
|
||||
|
||||
auto computeGaussianCoefficients = [](float2* kernel, size_t size) -> size_t {
|
||||
// The kernel-size was determined empirically so that we don't get too many aritfacts
|
||||
// due to the down-sampling.
|
||||
const size_t n = 17;
|
||||
|
||||
// The relation between n and q the variance should 6q - 1 = n, however here we
|
||||
// use 4q - 1 = n, which gives a stronger blur, without bringing too many artifacts.
|
||||
const float q = (n + 1) / 4;
|
||||
const float alpha = 1.0f / (2.0f * q * q);
|
||||
|
||||
auto computeGaussianCoefficients = [](float2* kernel, size_t size, float alpha) -> size_t {
|
||||
// Figure out how many samples we need. A gaussian filter keeps its gaussianness
|
||||
// if it has at least 6q-1 coefficient (q = standard deviation)
|
||||
// standard deviation
|
||||
float q = 1 / std::sqrt(2.0f * alpha);
|
||||
// number of samples needed
|
||||
size_t n = (size_t)std::max(1.0f, std::ceil(6.0f * q - 1.0f));
|
||||
// number of positive-side samples needed, using linear sampling
|
||||
size_t m = (n - 1) / 4 + 1;
|
||||
// clamp to what we have
|
||||
@@ -757,8 +754,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
|
||||
desc.width = FTexture::valueForLevel(dstLevel, desc.width);
|
||||
// height of the source level (b/c it's not blurred in this pass)
|
||||
desc.height = FTexture::valueForLevel(srcLevel, desc.height);
|
||||
// only one level
|
||||
desc.levels = 1;
|
||||
|
||||
data.temp = builder.createTexture("Horizontal temporary buffer", desc);
|
||||
data.temp = builder.write(builder.sample(data.temp));
|
||||
@@ -784,7 +779,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::gaussianBlurPass(FrameGraph&
|
||||
|
||||
float2 kernel[128];
|
||||
size_t m = computeGaussianCoefficients(kernel,
|
||||
std::min(sizeof(kernel) / sizeof(*kernel), kernelStorageSize));
|
||||
std::min(sizeof(kernel) / sizeof(*kernel), kernelStorageSize), alpha);
|
||||
|
||||
// horizontal pass
|
||||
auto hwTempRT = resources.getRenderTarget(data.tempRT);
|
||||
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
|
||||
FrameGraphId<FrameGraphTexture> gaussianBlurPass(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, uint8_t srcLevel,
|
||||
uint8_t dstLevel) noexcept;
|
||||
uint8_t dstLevel, float alpha) noexcept;
|
||||
|
||||
backend::Handle<backend::HwTexture> getNoSSAOTexture() const {
|
||||
return mNoSSAOTexture;
|
||||
|
||||
@@ -455,24 +455,43 @@ FrameGraphId<FrameGraphTexture> FRenderer::refractionPass(FrameGraph& fg,
|
||||
|
||||
// Number of roughness levels we want. Perceptual roughness will be mapped between
|
||||
// 0 and 0.5 (see lodToPerceptualRoughness() below).
|
||||
const size_t kNumRoughnessLods = 10;
|
||||
const size_t kNumRoughnessLods = 5;
|
||||
|
||||
// maps a LOD to the perceptual roughness. this must match the inverse mapping
|
||||
// in light_indirect.fs
|
||||
auto lodToPerceptualRoughness = [](float lod) -> float {
|
||||
return 0.5f * std::pow(2.0f, lod - (kNumRoughnessLods - 1)); };
|
||||
|
||||
// Copy the color buffer into a texture, we use resolve() because in case of a multi-sample
|
||||
// buffer, it'll also resolve it.
|
||||
input = ppm.resolve(fg, "Refraction Buffer",
|
||||
kNumRoughnessLods, TextureFormat::R11F_G11F_B10F, input);
|
||||
|
||||
// // scale factor for the gaussian so it matches our resolution / FOV
|
||||
// scale factor for the gaussian so it matches our resolution / FOV
|
||||
const float verticalFieldOfView = view.getCameraUser().getFieldOfView(Camera::Fov::VERTICAL);
|
||||
const float s = pow2(verticalFieldOfView / desc.height);
|
||||
|
||||
float alpha0 = 0.2469f / s;
|
||||
// this compute the alpha parameter of a gaussian that is applied on a base gaussian
|
||||
// and for which the result of the convolution is given.
|
||||
auto deconvolveGaussian = [](float baseAlpha, float convolvedAlpha) -> float {
|
||||
return (baseAlpha * convolvedAlpha) / (baseAlpha - convolvedAlpha);
|
||||
};
|
||||
|
||||
float prevAlpha = 65536.0; // just need a large number
|
||||
for (size_t i = 1; i < kNumRoughnessLods; i++) {
|
||||
float alpha = alpha0 / float(1 << i * 2);
|
||||
float roughness = 1.0f / std::sqrt(alpha);
|
||||
float perceptualRoughness = std::sqrt(roughness);
|
||||
slog.d << "lod=" << i << ", alpha=" << alpha << ", perceptualRoughness=" << perceptualRoughness << io::endl;
|
||||
input = ppm.gaussianBlurPass(fg, input, i - 1, i);
|
||||
// compute our gaussian parameter, alpha, for a given pereceptual roughness
|
||||
// The gaussian kernel is e^(-alpha * x^2)
|
||||
// and alpha = 1/roughness^2, with x between -pi/2 and pi/2
|
||||
// with, roughness = perceptual_roughnes^2
|
||||
const float perceptualRoughness = lodToPerceptualRoughness(i);
|
||||
const float roughness = pow2(perceptualRoughness);
|
||||
const float alpha = s * (1.0f / pow2(roughness));
|
||||
const float r = float(1 << (i - 1) * 2);
|
||||
const float alphaForLod = r * deconvolveGaussian(prevAlpha, alpha);
|
||||
input = ppm.gaussianBlurPass(fg, input, i - 1, i, alphaForLod);
|
||||
prevAlpha = alpha;
|
||||
//slog.d << "roughness=" << perceptualRoughness
|
||||
// << ", alpha=" << alpha << ", " << alphaForLod << io::endl;
|
||||
}
|
||||
|
||||
struct PrepareSSRData {
|
||||
|
||||
@@ -650,7 +650,7 @@ void FView::prepareSSAO(Handle<HwTexture> ssao) const noexcept {
|
||||
void FView::prepareSSR(Handle<HwTexture> ssr) const noexcept {
|
||||
mPerViewSb.setSampler(PerViewSib::SSR, ssr, {
|
||||
.filterMag = SamplerMagFilter::LINEAR,
|
||||
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST
|
||||
.filterMin = SamplerMinFilter::LINEAR_MIPMAP_LINEAR
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ FrameGraphPassResources::getRenderTarget(FrameGraphRenderTargetHandle handle, ui
|
||||
|
||||
FrameGraph::FrameGraph(fg::ResourceAllocatorInterface& resourceAllocator)
|
||||
: mResourceAllocator(resourceAllocator),
|
||||
mArena("FrameGraph Arena", 65536), // TODO: the Area will eventually come from outside
|
||||
mArena("FrameGraph Arena", 32768), // TODO: the Area will eventually come from outside
|
||||
mPassNodes(mArena),
|
||||
mResourceNodes(mArena),
|
||||
mRenderTargets(mArena),
|
||||
|
||||
@@ -445,12 +445,11 @@ void applyRefraction(const PixelParams pixel,
|
||||
p.xy = uvToRenderTargetUV(p.xy * (0.5 / p.w) + 0.5);
|
||||
|
||||
// perceptualRoughness to LOD
|
||||
const float kNumRoughnessLods = 10.0;
|
||||
const float kNumRoughnessLods = 5.0;
|
||||
// Empirical factor to compensate for the gaussian approximation of Dggx, chosen so
|
||||
// cubemap and screen-space modes match at perceptualRoughness 0.125
|
||||
// float tweakedPerceptualRoughness = perceptualRoughness * 1.74;
|
||||
// float lod = log2(tweakedPerceptualRoughness * 2.0) + (kNumRoughnessLods - 1.0);
|
||||
float lod = perceptualRoughness * (kNumRoughnessLods - 1.0);
|
||||
float tweakedPerceptualRoughness = perceptualRoughness * 1.74;
|
||||
float lod = log2(tweakedPerceptualRoughness * 2.0) + (kNumRoughnessLods - 1.0);
|
||||
vec3 Ft = textureLod(light_ssr, p.xy, lod).rgb;
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user