init
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
shader_type spatial;
|
||||
|
||||
render_mode unshaded, fog_disabled, depth_draw_never, cull_disabled, blend_mix;
|
||||
|
||||
const int MAX_LIGHTS = 256;
|
||||
|
||||
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear;
|
||||
uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;
|
||||
|
||||
// Camera matrices — set from GDScript.
|
||||
uniform mat4 inv_projection;
|
||||
uniform mat4 inv_view;
|
||||
|
||||
// Fog
|
||||
uniform vec3 fog_color : source_color = vec3(0.55, 0.65, 0.75);
|
||||
uniform float fog_density : hint_range(0.0, 10.0) = 0.5;
|
||||
uniform float fog_height_falloff : hint_range(0.0, 10.0) = 0.15;
|
||||
|
||||
// Light scattering
|
||||
uniform int light_count = 0;
|
||||
uniform vec3 light_positions[MAX_LIGHTS];
|
||||
uniform vec4 light_colors[MAX_LIGHTS];
|
||||
uniform float light_energies[MAX_LIGHTS];
|
||||
uniform float light_ranges[MAX_LIGHTS];
|
||||
|
||||
uniform float scattering : hint_range(0.0, 2.0) = 0.5;
|
||||
uniform float scattering_power : hint_range(0.1, 32.0) = 8.0;
|
||||
|
||||
uniform int steps : hint_range(8, 64) = 32;
|
||||
|
||||
vec3 reconstruct_view_position(vec2 uv, float depth) {
|
||||
vec3 ndc = vec3(uv * 2.0 - 1.0, depth);
|
||||
|
||||
vec4 view_pos = inv_projection * vec4(ndc, 1.0);
|
||||
view_pos.xyz /= view_pos.w;
|
||||
|
||||
return view_pos.xyz;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
vec2 screen_uv = SCREEN_UV;
|
||||
|
||||
vec4 scene = texture(screen_texture, screen_uv);
|
||||
float depth = texture(depth_texture, screen_uv).r;
|
||||
|
||||
vec3 ray_end_view =
|
||||
reconstruct_view_position(screen_uv, depth);
|
||||
|
||||
vec3 camera_position =
|
||||
(inv_view * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
||||
|
||||
vec3 ray_end =
|
||||
(inv_view * vec4(ray_end_view, 1.0)).xyz;
|
||||
|
||||
vec3 ray_vector = ray_end - camera_position;
|
||||
float ray_length = length(ray_vector);
|
||||
|
||||
vec3 ray_dir = normalize(ray_vector);
|
||||
|
||||
float step_length = ray_length / float(steps);
|
||||
|
||||
vec3 accumulated = vec3(0.0);
|
||||
float transmittance = 1.0;
|
||||
|
||||
for (int i = 0; i < steps; i++) {
|
||||
float t = (float(i) + 0.5) / float(steps);
|
||||
|
||||
vec3 world_position =
|
||||
camera_position +
|
||||
ray_dir * (ray_length * t);
|
||||
|
||||
float height_density =
|
||||
exp(-world_position.y * fog_height_falloff);
|
||||
|
||||
float density =
|
||||
fog_density * height_density;
|
||||
|
||||
vec3 light_scattering = vec3(0.0);
|
||||
|
||||
for (int l = 0; l < MAX_LIGHTS; l++) {
|
||||
if (l >= light_count)
|
||||
break;
|
||||
|
||||
vec3 to_light =
|
||||
light_positions[l] - world_position;
|
||||
|
||||
float light_distance = length(to_light);
|
||||
|
||||
if (light_distance <= 0.001)
|
||||
continue;
|
||||
|
||||
vec3 light_dir =
|
||||
to_light / light_distance;
|
||||
|
||||
float attenuation =
|
||||
1.0 - smoothstep(
|
||||
0.0,
|
||||
light_ranges[l],
|
||||
light_distance
|
||||
);
|
||||
|
||||
attenuation /=
|
||||
1.0 + light_distance * light_distance * 0.01;
|
||||
|
||||
float phase =
|
||||
pow(
|
||||
max(dot(-ray_dir, light_dir), 0.0),
|
||||
scattering_power
|
||||
);
|
||||
|
||||
light_scattering +=
|
||||
light_colors[l].rgb *
|
||||
light_energies[l] *
|
||||
attenuation *
|
||||
phase *
|
||||
scattering;
|
||||
}
|
||||
|
||||
float absorption =
|
||||
exp(-density * step_length * 10.0);
|
||||
|
||||
accumulated +=
|
||||
(fog_color + light_scattering) *
|
||||
(1.0 - absorption) *
|
||||
transmittance;
|
||||
|
||||
transmittance *= absorption;
|
||||
}
|
||||
|
||||
ALBEDO =
|
||||
scene.rgb * transmittance +
|
||||
accumulated;
|
||||
|
||||
ALPHA = 1.0;
|
||||
}
|
||||
Reference in New Issue
Block a user