Godot Version
Godot 4.3 (Stable)
Question
Could someone help me figure out how to create a bilateral filter? Earlier this year, I watched a video talking about how the developers of Ghost of Tsushima. I want to implement some of the stuff they talked about in it for a 3D project I wanna make, but the first one being the bilateral filter. I would appreciate any help in figuring out how to do this, as well as mixing a bilateral filter with other shaders in certain mixtures.
shader_type spatial;
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
uniform float spatial_sigma = 3.0; // Controls how much nearby pixels influence each other
uniform float range_sigma = 0.1; // Controls how much similar colors influence each other
uniform int kernel_size = 5; // Size of the sampling kernel (odd numbers only)
void fragment() {
vec2 pixel_size = 1.0 / VIEWPORT_SIZE;
vec3 center_color = texture(SCREEN_TEXTURE, SCREEN_UV).rgb;
vec3 final_color = vec3(0.0);
float weight_sum = 0.0;
// Calculate half kernel size for iteration
int half_kernel = kernel_size / 2;
// Iterate through kernel
for(int x = -half_kernel; x <= half_kernel; x++) {
for(int y = -half_kernel; y <= half_kernel; y++) {
// Sample position
vec2 sample_pos = SCREEN_UV + vec2(float(x), float(y)) * pixel_size;
vec3 sample_color = texture(SCREEN_TEXTURE, sample_pos).rgb;
// Calculate spatial weight (based on pixel distance)
float spatial_dist = length(vec2(float(x), float(y)));
float spatial_weight = exp(-0.5 * pow(spatial_dist / spatial_sigma, 2.0));
// Calculate range weight (based on color difference)
float color_dist = length(sample_color - center_color);
float range_weight = exp(-0.5 * pow(color_dist / range_sigma, 2.0));
// Combine weights
float weight = spatial_weight * range_weight;
// Accumulate weighted colors
final_color += sample_color * weight;
weight_sum += weight;
}
}
// Normalize
final_color /= weight_sum;
ALBEDO = final_color;
}
1 Like
Thank you so much for telling me how to do this! I just have two things I wanna ask: First, Do I need to make sure to have everything after the “//” is in the script? Secondly, how would the script look with the correct spacing? I want to make sure I knew where to correctly space it in case that is important. A picture of the script in Godot would be appreciated.
It would be a shader script. The spacing doesn’t matter in glsl, and you do not need comments //
in glsl.
Also, if you don’t mind me asking, what if I wanted to add a bilateral filter to a 2D scene?
Ah, okay. I was unsure if the comments and the spaces were needed for the script to work for the bilateral filter.
You’re ok now? or still have questions ?
Yes, I am with a 3D scene. I was tagging you because I wondered if you use the same script for a 2D scene or a different script. Also, if I have any more questions in the future, would it be alright to message you or not?
Glad to hear. I’ll be sure to message you whenever I have more questions relating to bilateral filtering. Also, is the script for a 2D scene’s bilateral filter much different to a 3D scene’s script?