Blue Noise vs Interleaved Gradient Noise
A quick Godot shader for using blue noise instead of interleaved gradient noise for the material distance fade option. The blue noise texture is from: momentsingraphics.de I'm using the red channel with the LDR_RGB1_0.png 512px file, but the smaller images also work, such as HDR_RGB_0.png in 128px or 256px. Ensure that compression is disabled in the Godot import settings otherwise the results are blocky.
Shader Code Download
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_burley, specular_schlick_ggx;
uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color, filter_linear_mipmap, repeat_enable;
// Bluenoise texture from: http://momentsingraphics.de/BlueNoise.html
// Ensure compression is disabled.
uniform sampler2D texture_blue_noise : hint_default_white, filter_nearest, repeat_enable;
uniform float distance_fade_min : hint_range(0.0, 4096.0, 0.01);
uniform float distance_fade_max : hint_range(0.0, 4096.0, 0.01);
uniform float point_size : hint_range(0.1, 128.0, 0.1);
uniform float roughness : hint_range(0.0, 1.0);
uniform sampler2D texture_metallic : hint_default_white, filter_linear_mipmap, repeat_enable;
uniform vec4 metallic_texture_channel;
uniform sampler2D texture_roughness : hint_roughness_r, filter_linear_mipmap, repeat_enable;
uniform float specular : hint_range(0.0, 1.0, 0.01);
uniform float metallic : hint_range(0.0, 1.0, 0.01);
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
uniform vec3 uv2_scale;
uniform vec3 uv2_offset;
void vertex() {
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
void fragment() {
vec2 base_uv = UV;
vec4 albedo_tex = texture(texture_albedo, base_uv);
ALBEDO = albedo.rgb * albedo_tex.rgb;
float metallic_tex = dot(texture(texture_metallic, base_uv), metallic_texture_channel);
METALLIC = metallic_tex * metallic;
SPECULAR = specular;
vec4 roughness_texture_channel = vec4(1.0, 0.0, 0.0, 0.0);
float roughness_tex = dot(texture(texture_roughness, base_uv), roughness_texture_channel);
ROUGHNESS = roughness_tex * roughness;
{
float ratio = VIEWPORT_SIZE.x / VIEWPORT_SIZE.y;
ivec2 blue_size = textureSize(texture_blue_noise,0);
vec2 frag_screen_uv = vec2(mix(0.5, FRAGCOORD.x/float(blue_size.x), ratio),FRAGCOORD.y/float(blue_size.y));
vec4 blue_tex = texture(texture_blue_noise, frag_screen_uv);
// Distance Fade: Blue Noise Dither
float fade_distance = length(VERTEX);
float fade = clamp(smoothstep(distance_fade_min, distance_fade_max, fade_distance), 0.0, 1.0);
// Use a hard cap to prevent a few stray pixels from remaining when past the fade-out distance.
if (fade < 0.001 || fade < blue_tex.r) {
discard;
}
ALPHA = 1.0;
}
}
License: Zero-Clause BSD
