slang-shaders/bezel/koko-aio/shaders-ng/avglum_pass.slang
2023-09-28 16:26:48 +02:00

127 lines
4.3 KiB
Plaintext

#version 450
/* In this pass we calculate the average luminance of the scene.
* It is cheaply obtained by the use of mipmaps. */
#include "config.inc"
//The mipmap wideness needed by the highlights on the bezel.
//the higher, the smoother.
#define mip_lod 5
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out float lod;
layout(location = 2) out vec2 vFuzzy_main_pass_stage_1;
#include "includes/functions.include.slang"
void main() {
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
if (DO_GAME_GEOM_OVERRIDE > 0.5)
vTexCoord = content_geom_override(vTexCoord, GAME_GEOM_ASPECT, get_in_aspect(), GAME_GEOM_VSHIFT, GAME_GEOM_HSHIFT, GAME_GEOM_ZOOM);
//Get fuzzy mul and pow factor
vFuzzy_main_pass_stage_1 = apply_fuzzy_main_pass_stage_1();
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in float lod;
layout(location = 2) in vec2 vFuzzy_main_pass_stage_1;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D flick_and_noise_pass;
layout(set = 0, binding = 3) uniform sampler2D avglum_passFeedback;
/* The following will allow to sample at reduced interval
The scene change detection logic will take advantage of it
So that quick fades will still be treated as scene changes
*/
// #define avglum_divider 4 <-- in config.inc
#include "includes/functions.include.slang"
#define RGB_TO_GRAYSCALE = vec3(0.299, 0.587, 0.114)
float get_avg_lum_from_mip() {
vec3 mip = textureLod(flick_and_noise_pass, vec2(0.5,0.5),20.0).rgb;
mip = apply_fuzzy_main_pass_stage_2(mip, vFuzzy_main_pass_stage_1);
//return (mip.r+mip.g+mip.b)/3.0;
return rgb_to_gray(mip);
}
//0.1 seems like a good tradeoff that works well with bloom exposire and fullscreen zoom
//...maybe bloom exposure works best at 0.05; you may consider another zone of smooth sampling.
#define SMOOTHNESS_SPEED 0.1
float get_avglum() {
/* avglum alpha has 3 zones::
* 0.25 -> reduced sampling, used for to aid scene detection
* 0.75 -> smoothed_sampling, used to adapt fullscreen zoom
* anything else: continuous sampling
*/
bool reduced_sampling_co =
vTexCoord.x > 0.24 && vTexCoord.x < 0.26 &&
vTexCoord.y > 0.24 && vTexCoord.y < 0.26 ;
bool smoothed_sampling_co =
vTexCoord.x > 0.74 && vTexCoord.x < 0.76 &&
vTexCoord.y > 0.74 && vTexCoord.y < 0.76 ;
if (reduced_sampling_co) {
//in the reduced sampling zone, only update at right time; else return the previous frame.
bool reduced_sample_time_is_now = (mod(params.FrameCount,AMBI_AVGLUM_DIVIDER) == 1); // (== 0 may be problematic for flycast + nvidia + glcore)
if (reduced_sample_time_is_now)
return get_avg_lum_from_mip();
float avglum_feedback = texture(avglum_passFeedback,vTexCoord).a;
avglum_feedback = max(avglum_feedback, 0.0); // <- Sanitize input to avoid glitches when enabling the option runtime.
return avglum_feedback;
}
if (smoothed_sampling_co) {
return mix(texture(avglum_passFeedback,vTexCoord).a, get_avg_lum_from_mip(), SMOOTHNESS_SPEED);
}
//Outside specific areas, update continuously; this is used by bezel highlights.
return get_avg_lum_from_mip();
}
void main() {
/*Grab a mipmap from the flick_and_noise_pass.
Calculate the average luminance from the smallest mipmap and put into the alpha channel
So that can be used:
1 - continuously at coordinate 0.5,0.5
2 - sampled less often for scene detection logic at coordinate 0.25,0.25
Put another small mipmap into the rgb channel to be used by the reflection code.
*/
//FIXME: see which is faster:
//if (DO_AMBILIGHT == 1.0 || DO_BEZEL == 1.0 || DO_DYNZOOM == 1.0) {
if ( DO_AMBILIGHT + DO_BEZEL + DO_DYNZOOM + DO_BLOOM == 0 ) return;
vec4 pixel_out;
pixel_out.a = get_avglum();
if (DO_BEZEL + DO_BLOOM > 0.0) {
//Create a small mipmap to be used to light the bezel corners
//and by the bloom pass to identify bright areas.
pixel_out.rgb = textureLod(flick_and_noise_pass, vTexCoord, mip_lod).rgb;
}
FragColor = pixel_out;
//FragColor = texture(flick_and_noise_pass, vTexCoord);
}