Use dithering when performing SSR roughness to improve quality
This works best when TAA or FSR2 is enabled to jitter the result every frame, letting TAA accumulation do its work.
This commit is contained in:
parent
506d6e427a
commit
35d1c70bc1
3 changed files with 32 additions and 2 deletions
|
@ -1525,6 +1525,8 @@ void SSEffects::screen_space_reflection(Ref<RenderSceneBuffersRD> p_render_buffe
|
|||
push_constant.view_index = v;
|
||||
push_constant.orthogonal = p_projections[v].is_orthogonal();
|
||||
push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
|
||||
constexpr int taa_phase_count = 16;
|
||||
push_constant.taa_frame_count = (RSG::rasterizer->get_frame_number() % taa_phase_count) / float(taa_phase_count);
|
||||
push_constant.proj_info[0] = -2.0f / (p_ssr_buffers.size.width * p_projections[v].columns[0][0]);
|
||||
push_constant.proj_info[1] = -2.0f / (p_ssr_buffers.size.height * p_projections[v].columns[1][1]);
|
||||
push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
|
||||
|
|
|
@ -490,6 +490,12 @@ private:
|
|||
int32_t screen_size[2]; // 8 - 40
|
||||
uint32_t vertical; // 4 - 44
|
||||
uint32_t steps; // 4 - 48
|
||||
|
||||
// Used to add break up samples over multiple frames. Value is an integer from 0 to taa_phase_count -1.
|
||||
float taa_frame_count; // 4 - 52
|
||||
uint32_t pad0; // 4 - 56
|
||||
uint32_t pad1; // 4 - 60
|
||||
uint32_t pad2; // 4 - 64
|
||||
};
|
||||
|
||||
enum SSRReflectionMode {
|
||||
|
|
|
@ -27,6 +27,12 @@ layout(push_constant, std430) uniform Params {
|
|||
ivec2 screen_size;
|
||||
bool vertical;
|
||||
uint steps;
|
||||
|
||||
// Used to add break up samples over multiple frames. Value is an integer from 0 to taa_phase_count -1.
|
||||
float taa_frame_count;
|
||||
uint pad0;
|
||||
uint pad1;
|
||||
uint pad2;
|
||||
}
|
||||
params;
|
||||
|
||||
|
@ -66,6 +72,13 @@ float gauss_weight(float p_val) {
|
|||
|
||||
#define M_PI 3.14159265359
|
||||
|
||||
// Interleaved Gradient Noise
|
||||
// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
|
||||
float quick_hash(vec2 pos) {
|
||||
const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
|
||||
return fract(magic.z * fract(dot(pos, magic.xy)));
|
||||
}
|
||||
|
||||
void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
|
||||
for (int i = 1; i < params.steps; i++) {
|
||||
float d = float(i * params.increment);
|
||||
|
@ -118,10 +131,19 @@ void main() {
|
|||
float divisor = gauss_table[0];
|
||||
accum *= divisor;
|
||||
accum_radius *= divisor;
|
||||
|
||||
// The intent is to spread the increment on Low quality (3) to be between 1 and 5.
|
||||
// On Medium quality (2), it would be between 1 and 3.
|
||||
//
|
||||
// See https://github.com/godotengine/godot/blob/ad2722f48180c21147a31ee59e15722a237a7445/servers/rendering/renderer_rd/effects/ss_effects.cpp#L1535-L1544
|
||||
// for values of `params.increment` depending on quality.
|
||||
int increment_offset = params.increment - 1;
|
||||
int taa_jitter = int(quick_hash(vec2(ssC.xy) + vec2(params.taa_frame_count * 5.0, params.taa_frame_count * 2.0)) * (params.increment + increment_offset) - increment_offset);
|
||||
|
||||
#ifdef VERTICAL_PASS
|
||||
ivec2 direction = ivec2(0, params.increment);
|
||||
ivec2 direction = ivec2(0, params.increment + taa_jitter);
|
||||
#else
|
||||
ivec2 direction = ivec2(params.increment, 0);
|
||||
ivec2 direction = ivec2(params.increment + taa_jitter, 0);
|
||||
#endif
|
||||
float depth = imageLoad(source_depth, ssC).r;
|
||||
vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth);
|
||||
|
|
Loading…
Reference in a new issue