mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 12:46:03 +03:00
202 lines
5.6 KiB
GLSL
202 lines
5.6 KiB
GLSL
#version 460
|
|
|
|
#extension GL_EXT_nonuniform_qualifier : enable
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
#extension GL_EXT_samplerless_texture_functions : enable
|
|
|
|
#define SHARED_SAMPLER_SET 1
|
|
#include "common_shader.glsl"
|
|
|
|
vec3 prefilter(vec3 c, vec4 prefilterFactor)
|
|
{
|
|
float brightness = max(c.r, max(c.g, c.b));
|
|
|
|
float soft = brightness - prefilterFactor.y;
|
|
|
|
soft = clamp(soft, 0, prefilterFactor.z);
|
|
soft = soft * soft * prefilterFactor.w;
|
|
|
|
float contribution = max(soft, brightness - prefilterFactor.x);
|
|
contribution /= max(brightness, 0.00001);
|
|
|
|
return c * contribution;
|
|
}
|
|
|
|
#ifdef BLOOM_DOWNSAMPLE_PASS
|
|
|
|
layout(set = 0, binding = 0) uniform texture2D inputTexture;
|
|
layout(set = 0, binding = 1, rgba16f) uniform image2D hdrDownSample;
|
|
layout(set = 0, binding = 2) uniform texture2D inAdaptedLumTex;
|
|
layout(set = 0, binding = 3) uniform UniformFrameData { PerFrameData frameData; };
|
|
|
|
layout (push_constant) uniform PushConsts
|
|
{
|
|
vec4 prefilterFactor;
|
|
uint mipLevel;
|
|
};
|
|
|
|
// 13 tap downsample kernal.
|
|
const uint kDownSampleCount = 13;
|
|
const vec2 kDownSampleCoords[kDownSampleCount] =
|
|
{
|
|
{ 0.0, 0.0},
|
|
{-1.0, -1.0}, {1.0, -1.0}, {1.0, 1.0}, { -1.0, 1.0},
|
|
{-2.0, -2.0}, {0.0, -2.0}, {2.0, -2.0}, { 2.0, 0.0}, {2.0, 2.0}, {0.0, 2.0}, {-2.0, 2.0}, {-2.0, 0.0}
|
|
};
|
|
|
|
const float kWeights[kDownSampleCount] =
|
|
{
|
|
0.125,
|
|
0.125, 0.125, 0.125, 0.125,
|
|
0.03125, 0.0625, 0.03125, 0.0625, 0.03125, 0.0625, 0.03125, 0.0625
|
|
};
|
|
|
|
const int kDownSampleGroupCnt = 5;
|
|
const int kSamplePerGroup = 4;
|
|
const int kDownSampleGroups[kDownSampleGroupCnt][kSamplePerGroup] =
|
|
{
|
|
{ 1, 2, 3, 4},
|
|
{ 5, 6, 0, 12},
|
|
{ 6, 7, 8, 0},
|
|
{ 0, 8, 9, 10},
|
|
{12, 0, 10, 11}
|
|
};
|
|
const float kDownSampleGroupWeights[kDownSampleGroupCnt] =
|
|
{
|
|
0.5, 0.125, 0.125, 0.125, 0.125
|
|
};
|
|
|
|
layout (local_size_x = 8, local_size_y = 8) in;
|
|
void main()
|
|
{
|
|
ivec2 downsampleSize = imageSize(hdrDownSample);
|
|
ivec2 workPos = ivec2(gl_GlobalInvocationID.xy);
|
|
if(workPos.x >= downsampleSize.x || workPos.y >= downsampleSize.y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
vec2 uv = (vec2(workPos) + vec2(0.5)) / vec2(downsampleSize);
|
|
vec3 outColor = vec3(0.0);
|
|
|
|
const bool bFirstDownsample = (mipLevel == 0);
|
|
|
|
// Get src texture size and compute it's pixel size.
|
|
uvec2 srcSize = textureSize(inputTexture, 0);
|
|
vec2 pixelSize = 1.0f / vec2(srcSize);
|
|
|
|
vec3 samples[kDownSampleCount];
|
|
for(uint i = 0; i < kDownSampleCount; i ++)
|
|
{
|
|
vec2 sampleUv = uv + kDownSampleCoords[i] * pixelSize;
|
|
|
|
// When downsample, we should not use clamp to edge sampler.
|
|
// Evaluate some bright pixel on the edge, if clamp to edge, down sample level edge pixel will capture it in multi sample.
|
|
// And accumulate all of them then get a bright pixel.
|
|
samples[i] = texture(sampler2D(inputTexture, linearClampBorder0000Sampler), sampleUv).rgb;
|
|
|
|
if(bFirstDownsample)
|
|
{
|
|
samples[i] = prefilter(samples[i], prefilterFactor);
|
|
}
|
|
}
|
|
|
|
// Downsample
|
|
if(bFirstDownsample)
|
|
{
|
|
float sampleKarisWeight[kDownSampleCount];
|
|
for(uint i = 0; i < kDownSampleCount; i ++)
|
|
{
|
|
sampleKarisWeight[i] = 1.0 / (1.0 + luminance(samples[i]));
|
|
}
|
|
|
|
for(int i = 0; i < kDownSampleGroupCnt; i++)
|
|
{
|
|
float sumedKarisWeight = 0;
|
|
for(int j = 0; j < kSamplePerGroup; j++)
|
|
{
|
|
sumedKarisWeight += sampleKarisWeight[kDownSampleGroups[i][j]];
|
|
}
|
|
|
|
// Anti AA filter.
|
|
for(int j = 0; j < kSamplePerGroup; j++)
|
|
{
|
|
outColor += kDownSampleGroupWeights[i] * sampleKarisWeight[kDownSampleGroups[i][j]] / sumedKarisWeight * samples[kDownSampleGroups[i][j]];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(uint i = 0; i < kDownSampleCount; i ++)
|
|
{
|
|
outColor += samples[i] * kWeights[i];
|
|
}
|
|
}
|
|
|
|
imageStore(hdrDownSample, workPos, vec4(outColor, 1.0f));
|
|
}
|
|
|
|
#endif // BLOOM_DOWNSAMPLE_PASS
|
|
|
|
#ifdef BLOOM_UPSCALE_PASS
|
|
|
|
layout(set = 0, binding = 0) uniform texture2D inputTexture;
|
|
layout(set = 0, binding = 1) uniform texture2D inputCurTexture;
|
|
layout(set = 0, binding = 2, rgba16f) uniform image2D hdrUpscale;
|
|
|
|
layout (push_constant) uniform PushConsts
|
|
{
|
|
uint bBlurX;
|
|
uint bFinalBlur;
|
|
uint upscaleTime;
|
|
float blurRadius;
|
|
};
|
|
|
|
// TODO: Bake me.
|
|
const float kRadius = 16.0;
|
|
const float kSigma = 0.2;
|
|
float gaussianWeight(float x)
|
|
{
|
|
const float mu = 0; // From center.
|
|
const float dx = x - mu;
|
|
const float sigma2 = kSigma * kSigma;
|
|
return 0.398942280401 / kSigma * exp(- (dx * dx) * 0.5 / sigma2);
|
|
}
|
|
|
|
layout (local_size_x = 8, local_size_y = 8) in;
|
|
void main()
|
|
{
|
|
ivec2 upscaleSize = imageSize(hdrUpscale);
|
|
ivec2 workPos = ivec2(gl_GlobalInvocationID.xy);
|
|
if(workPos.x >= upscaleSize.x || workPos.y >= upscaleSize.y)
|
|
{
|
|
return;
|
|
}
|
|
|
|
vec2 uv = (vec2(workPos) + vec2(0.5)) / vec2(upscaleSize);
|
|
|
|
vec2 inputTexelSize = 1.0 / vec2(upscaleSize);
|
|
|
|
const bool bBlurXDirection = bBlurX > 0;
|
|
vec2 blurDirection = bBlurXDirection ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
blurDirection *= inputTexelSize;
|
|
|
|
vec4 sum = vec4(0.0);
|
|
for(float i = -kRadius; i <= kRadius; i++)
|
|
{
|
|
float weight = gaussianWeight(i / kRadius);
|
|
sum.xyz += weight * texture(sampler2D(inputTexture, pointClampEdgeSampler), uv + i * blurDirection).xyz;
|
|
sum.w += weight;
|
|
}
|
|
sum.xyz /= sum.w;
|
|
|
|
if((!bBlurXDirection) && (bFinalBlur == 0))
|
|
{
|
|
vec3 currentColor = texture(sampler2D(inputCurTexture, pointClampEdgeSampler), uv).rgb;
|
|
sum.xyz = mix(currentColor, sum.xyz, vec3(blurRadius));
|
|
}
|
|
|
|
imageStore(hdrUpscale, workPos, vec4(sum.xyz, 1.0f));
|
|
}
|
|
|
|
#endif |