/* clang-format off */ #[modes] // Based on Dual filtering glow as explained in Marius Bjørge presentation at Siggraph 2015 "Bandwidth-Efficient Rendering" mode_filter = #define MODE_FILTER mode_downsample = #define MODE_DOWNSAMPLE mode_upsample = #define MODE_UPSAMPLE #[specializations] USE_MULTIVIEW = false #[vertex] layout(location = 0) in vec2 vertex_attrib; /* clang-format on */ out vec2 uv_interp; void main() { uv_interp = vertex_attrib * 0.5 + 0.5; gl_Position = vec4(vertex_attrib, 1.0, 1.0); } /* clang-format off */ #[fragment] /* clang-format on */ #ifdef MODE_FILTER #ifdef USE_MULTIVIEW uniform sampler2DArray source_color; // texunit:0 #else uniform sampler2D source_color; // texunit:0 #endif // USE_MULTIVIEW uniform float view; uniform vec2 pixel_size; uniform float luminance_multiplier; uniform float glow_bloom; uniform float glow_hdr_threshold; uniform float glow_hdr_scale; uniform float glow_luminance_cap; #endif // MODE_FILTER #ifdef MODE_DOWNSAMPLE uniform sampler2D source_color; // texunit:0 uniform vec2 pixel_size; #endif // MODE_DOWNSAMPLE #ifdef MODE_UPSAMPLE uniform sampler2D source_color; // texunit:0 uniform vec2 pixel_size; #endif // MODE_UPSAMPLE in vec2 uv_interp; layout(location = 0) out vec4 frag_color; void main() { #ifdef MODE_FILTER // Note, we read from an image with double resolution, so we average those out #ifdef USE_MULTIVIEW vec2 half_pixel = pixel_size * 0.5; vec3 uv = vec3(uv_interp, view); vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0; color += textureLod(source_color, uv - vec3(half_pixel, 0.0), 0.0).rgb; color += textureLod(source_color, uv + vec3(half_pixel, 0.0), 0.0).rgb; color += textureLod(source_color, uv - vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb; color += textureLod(source_color, uv + vec3(half_pixel.x, -half_pixel.y, 0.0), 0.0).rgb; #else vec2 half_pixel = pixel_size * 0.5; vec2 uv = uv_interp; vec3 color = textureLod(source_color, uv, 0.0).rgb * 4.0; color += textureLod(source_color, uv - half_pixel, 0.0).rgb; color += textureLod(source_color, uv + half_pixel, 0.0).rgb; color += textureLod(source_color, uv - vec2(half_pixel.x, -half_pixel.y), 0.0).rgb; color += textureLod(source_color, uv + vec2(half_pixel.x, -half_pixel.y), 0.0).rgb; #endif // USE_MULTIVIEW color /= luminance_multiplier * 8.0; float feedback_factor = max(color.r, max(color.g, color.b)); float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, feedback_factor), glow_bloom); color = min(color * feedback, vec3(glow_luminance_cap)); frag_color = vec4(luminance_multiplier * color, 1.0); #endif // MODE_FILTER #ifdef MODE_DOWNSAMPLE vec2 half_pixel = pixel_size * 0.5; vec4 color = textureLod(source_color, uv_interp, 0.0) * 4.0; color += textureLod(source_color, uv_interp - half_pixel, 0.0); color += textureLod(source_color, uv_interp + half_pixel, 0.0); color += textureLod(source_color, uv_interp - vec2(half_pixel.x, -half_pixel.y), 0.0); color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0); frag_color = color / 8.0; #endif // MODE_DOWNSAMPLE #ifdef MODE_UPSAMPLE vec2 half_pixel = pixel_size * 0.5; vec4 color = textureLod(source_color, uv_interp + vec2(-half_pixel.x * 2.0, 0.0), 0.0); color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, half_pixel.y), 0.0) * 2.0; color += textureLod(source_color, uv_interp + vec2(0.0, half_pixel.y * 2.0), 0.0); color += textureLod(source_color, uv_interp + vec2(half_pixel.x, half_pixel.y), 0.0) * 2.0; color += textureLod(source_color, uv_interp + vec2(half_pixel.x * 2.0, 0.0), 0.0); color += textureLod(source_color, uv_interp + vec2(half_pixel.x, -half_pixel.y), 0.0) * 2.0; color += textureLod(source_color, uv_interp + vec2(0.0, -half_pixel.y * 2.0), 0.0); color += textureLod(source_color, uv_interp + vec2(-half_pixel.x, -half_pixel.y), 0.0) * 2.0; frag_color = color / 12.0; #endif // MODE_UPSAMPLE }