311 lines
9.1 KiB
GDScript
311 lines
9.1 KiB
GDScript
@tool
|
|
class_name PostProcessController
|
|
extends Node
|
|
|
|
@export_group("Profile")
|
|
@export var profile: PostProcessProfile:
|
|
set(value):
|
|
profile = value
|
|
_apply_profile()
|
|
|
|
@export_group("Environment")
|
|
@export var target_environment: Environment
|
|
|
|
@export_group("Sky Gradient")
|
|
@export var sky_top_color: Color = Color(0.2, 0.4, 0.8)
|
|
@export var sky_horizon_color: Color = Color(0.6, 0.7, 0.9)
|
|
@export var sky_bottom_color: Color = Color(0.4, 0.5, 0.6)
|
|
@export var gradient_intensity: float = 1.0
|
|
|
|
@export_group("Skybox")
|
|
@export var skybox_texture: Texture2D:
|
|
set(value):
|
|
skybox_texture = value
|
|
_update_sky_material()
|
|
@export var skybox_blend: float = 1.0:
|
|
set(value):
|
|
skybox_blend = clampf(value, 0.0, 1.0)
|
|
_update_sky_material()
|
|
|
|
@export_group("Fog Shaping")
|
|
@export var fog_enabled: bool = true
|
|
@export var fog_color: Color = Color(0.7, 0.8, 0.9)
|
|
@export var fog_density: float = 0.01
|
|
@export var height_fog_enabled: bool = true
|
|
@export var height_fog_min: float = 0.0
|
|
@export var height_fog_max: float = 100.0
|
|
@export var height_fog_curve: float = 1.0
|
|
|
|
@export_group("Sun Glow")
|
|
@export var sun_glow_enabled: bool = true
|
|
@export var sun_glow_intensity: float = 0.5
|
|
@export var sun_glow_size: float = 0.2
|
|
@export var sun_glow_falloff: float = 2.0
|
|
@export var sun_glow_color: Color = Color(1.0, 0.95, 0.8)
|
|
@export var sun_direction: Vector3 = Vector3(0.0, 1.0, 0.0)
|
|
|
|
@export_group("Dawn/Dusk Enhancement")
|
|
@export var dawn_dusk_enabled: bool = true
|
|
@export var dawn_dusk_intensity: float = 0.5
|
|
@export var dawn_dusk_blend: float = 0.0
|
|
|
|
@export_group("Performance")
|
|
@export var effects_enabled: bool = true
|
|
|
|
var _sky_material: ShaderMaterial
|
|
var _post_process_quad: MeshInstance3D
|
|
|
|
|
|
func _ready() -> void:
|
|
if profile == null:
|
|
profile = PostProcessProfile.new()
|
|
_apply_profile()
|
|
_setup_environment()
|
|
|
|
|
|
func _apply_profile() -> void:
|
|
if profile == null:
|
|
return
|
|
|
|
gradient_intensity = profile.gradient_intensity
|
|
fog_enabled = profile.fog_enabled
|
|
height_fog_enabled = profile.height_fog_enabled
|
|
height_fog_min = profile.height_fog_start
|
|
height_fog_max = profile.height_fog_end
|
|
height_fog_curve = profile.height_fog_curve
|
|
sun_glow_enabled = profile.sun_glow_enabled
|
|
sun_glow_intensity = profile.sun_glow_intensity
|
|
sun_glow_size = profile.sun_glow_size
|
|
sun_glow_falloff = profile.sun_glow_falloff
|
|
sun_glow_color = profile.sun_glow_color
|
|
dawn_dusk_enabled = profile.dawn_dusk_enabled
|
|
dawn_dusk_intensity = profile.dawn_dusk_intensity
|
|
|
|
|
|
func _setup_environment() -> void:
|
|
if target_environment == null:
|
|
return
|
|
|
|
_update_fog()
|
|
_update_sky()
|
|
|
|
|
|
func _update_fog() -> void:
|
|
if target_environment == null:
|
|
return
|
|
|
|
target_environment.fog_enabled = fog_enabled and effects_enabled
|
|
|
|
if fog_enabled:
|
|
target_environment.fog_light_color = fog_color
|
|
target_environment.fog_density = fog_density
|
|
|
|
if height_fog_enabled:
|
|
target_environment.fog_height = height_fog_min
|
|
target_environment.fog_height_density = height_fog_curve * 0.1
|
|
|
|
|
|
func _update_sky() -> void:
|
|
if target_environment == null:
|
|
return
|
|
|
|
if target_environment.sky == null:
|
|
target_environment.sky = Sky.new()
|
|
|
|
if target_environment.sky.sky_material == null or not target_environment.sky.sky_material is ShaderMaterial:
|
|
_create_sky_material()
|
|
|
|
_sky_material = target_environment.sky.sky_material as ShaderMaterial
|
|
if _sky_material:
|
|
_update_sky_material()
|
|
|
|
|
|
func _create_sky_material() -> void:
|
|
_sky_material = ShaderMaterial.new()
|
|
_sky_material.shader = _get_sky_shader()
|
|
|
|
if target_environment and target_environment.sky:
|
|
target_environment.sky.sky_material = _sky_material
|
|
|
|
|
|
func _get_sky_shader() -> Shader:
|
|
var shader := Shader.new()
|
|
shader.code = """
|
|
shader_type sky;
|
|
|
|
uniform sampler2D skybox_texture : source_color, filter_linear_mipmap, repeat_enable;
|
|
uniform bool skybox_enabled = false;
|
|
uniform float skybox_blend = 1.0;
|
|
|
|
uniform vec4 sky_top_color : source_color = vec4(0.2, 0.4, 0.8, 1.0);
|
|
uniform vec4 sky_horizon_color : source_color = vec4(0.6, 0.7, 0.9, 1.0);
|
|
uniform vec4 sky_bottom_color : source_color = vec4(0.4, 0.5, 0.6, 1.0);
|
|
uniform float gradient_intensity = 1.0;
|
|
uniform float horizon_blend = 0.5;
|
|
|
|
uniform bool sun_glow_enabled = true;
|
|
uniform vec3 sun_direction = vec3(0.0, 1.0, 0.0);
|
|
uniform vec4 sun_glow_color : source_color = vec4(1.0, 0.95, 0.8, 1.0);
|
|
uniform float sun_glow_intensity = 0.5;
|
|
uniform float sun_glow_size = 0.2;
|
|
uniform float sun_glow_falloff = 2.0;
|
|
|
|
uniform bool dawn_dusk_enabled = true;
|
|
uniform vec4 dawn_dusk_color : source_color = vec4(1.0, 0.6, 0.4, 1.0);
|
|
uniform float dawn_dusk_intensity = 0.5;
|
|
uniform float dawn_dusk_blend = 0.0;
|
|
|
|
uniform float stars_visibility = 0.0;
|
|
uniform vec4 stars_tint : source_color = vec4(1.0);
|
|
|
|
float hash(vec2 p) {
|
|
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
}
|
|
|
|
float stars(vec3 dir) {
|
|
vec2 uv = dir.xz / (abs(dir.y) + 0.001) * 50.0;
|
|
vec2 cell = floor(uv);
|
|
vec2 local = fract(uv) - 0.5;
|
|
|
|
float star = 0.0;
|
|
float h = hash(cell);
|
|
if (h > 0.97) {
|
|
float dist = length(local);
|
|
star = smoothstep(0.1, 0.0, dist) * (h - 0.97) / 0.03;
|
|
star *= step(0.0, dir.y);
|
|
}
|
|
return star;
|
|
}
|
|
|
|
vec2 pano_uv(vec3 dir) {
|
|
dir = normalize(dir);
|
|
float u = atan(dir.x, dir.z) / (2.0 * PI) + 0.5;
|
|
float v = acos(clamp(dir.y, -1.0, 1.0)) / PI;
|
|
return vec2(u, v);
|
|
}
|
|
|
|
void sky() {
|
|
vec3 dir = EYEDIR;
|
|
float y = dir.y;
|
|
|
|
vec3 color;
|
|
if (y > 0.0) {
|
|
float t = pow(y, horizon_blend);
|
|
color = mix(sky_horizon_color.rgb, sky_top_color.rgb, t);
|
|
} else {
|
|
float t = pow(-y, horizon_blend);
|
|
color = mix(sky_horizon_color.rgb, sky_bottom_color.rgb, t);
|
|
}
|
|
|
|
color = mix(vec3(0.5), color, gradient_intensity);
|
|
|
|
if (skybox_enabled) {
|
|
vec3 pano_color = texture(skybox_texture, pano_uv(dir)).rgb;
|
|
color = mix(color, pano_color, skybox_blend);
|
|
}
|
|
|
|
if (sun_glow_enabled && sun_direction.y > -0.2) {
|
|
float sun_dot = max(0.0, dot(dir, normalize(sun_direction)));
|
|
float glow = pow(sun_dot, 1.0 / max(0.001, sun_glow_size));
|
|
glow = pow(glow, sun_glow_falloff);
|
|
color += sun_glow_color.rgb * glow * sun_glow_intensity;
|
|
}
|
|
|
|
if (dawn_dusk_enabled && dawn_dusk_blend > 0.0) {
|
|
float horizon_factor = 1.0 - abs(y);
|
|
horizon_factor = pow(horizon_factor, 2.0);
|
|
color = mix(color, dawn_dusk_color.rgb, horizon_factor * dawn_dusk_intensity * dawn_dusk_blend);
|
|
}
|
|
|
|
if (stars_visibility > 0.0 && y > 0.0) {
|
|
float star_value = stars(dir) * stars_visibility;
|
|
color += stars_tint.rgb * star_value;
|
|
}
|
|
|
|
COLOR = color;
|
|
}
|
|
"""
|
|
return shader
|
|
|
|
|
|
func _update_sky_material() -> void:
|
|
if _sky_material == null:
|
|
return
|
|
|
|
if skybox_texture:
|
|
_sky_material.set_shader_parameter("skybox_enabled", true)
|
|
_sky_material.set_shader_parameter("skybox_texture", skybox_texture)
|
|
_sky_material.set_shader_parameter("skybox_blend", skybox_blend)
|
|
else:
|
|
_sky_material.set_shader_parameter("skybox_enabled", false)
|
|
_sky_material.set_shader_parameter("skybox_blend", skybox_blend)
|
|
|
|
_sky_material.set_shader_parameter("sky_top_color", sky_top_color)
|
|
_sky_material.set_shader_parameter("sky_horizon_color", sky_horizon_color)
|
|
_sky_material.set_shader_parameter("sky_bottom_color", sky_bottom_color)
|
|
_sky_material.set_shader_parameter("gradient_intensity", gradient_intensity)
|
|
|
|
_sky_material.set_shader_parameter("sun_glow_enabled", sun_glow_enabled and effects_enabled)
|
|
_sky_material.set_shader_parameter("sun_direction", sun_direction)
|
|
_sky_material.set_shader_parameter("sun_glow_color", sun_glow_color)
|
|
_sky_material.set_shader_parameter("sun_glow_intensity", sun_glow_intensity)
|
|
_sky_material.set_shader_parameter("sun_glow_size", sun_glow_size)
|
|
_sky_material.set_shader_parameter("sun_glow_falloff", sun_glow_falloff)
|
|
|
|
_sky_material.set_shader_parameter("dawn_dusk_enabled", dawn_dusk_enabled and effects_enabled)
|
|
_sky_material.set_shader_parameter("dawn_dusk_blend", dawn_dusk_blend)
|
|
_sky_material.set_shader_parameter("dawn_dusk_intensity", dawn_dusk_intensity)
|
|
|
|
|
|
func set_sky_colors(top: Color, horizon: Color, bottom: Color) -> void:
|
|
sky_top_color = top
|
|
sky_horizon_color = horizon
|
|
sky_bottom_color = bottom
|
|
_update_sky_material()
|
|
|
|
|
|
func set_fog_settings(color: Color, density: float) -> void:
|
|
fog_color = color
|
|
fog_density = density
|
|
_update_fog()
|
|
|
|
|
|
func set_sun_glow(direction: Vector3, color: Color, intensity: float, size: float) -> void:
|
|
sun_direction = direction.normalized()
|
|
sun_glow_color = color
|
|
sun_glow_intensity = intensity
|
|
sun_glow_size = size
|
|
_update_sky_material()
|
|
|
|
|
|
func set_dawn_dusk_blend(blend: float) -> void:
|
|
dawn_dusk_blend = clampf(blend, 0.0, 1.0)
|
|
_update_sky_material()
|
|
|
|
|
|
func set_stars_visibility(visibility: float, tint: Color = Color.WHITE) -> void:
|
|
if _sky_material:
|
|
_sky_material.set_shader_parameter("stars_visibility", visibility)
|
|
_sky_material.set_shader_parameter("stars_tint", tint)
|
|
|
|
|
|
func set_effects_enabled(enabled: bool) -> void:
|
|
effects_enabled = enabled
|
|
_update_fog()
|
|
_update_sky_material()
|
|
|
|
|
|
func apply_config(config: SkyConfig) -> void:
|
|
sky_top_color = config.sky_top_color
|
|
sky_horizon_color = config.sky_horizon_color
|
|
sky_bottom_color = config.sky_bottom_color
|
|
fog_color = config.fog_color
|
|
fog_density = config.fog_density
|
|
sun_glow_intensity = config.sun_glow_intensity
|
|
sun_glow_size = config.sun_glow_size
|
|
gradient_intensity = config.gradient_intensity
|
|
|
|
_update_fog()
|
|
_update_sky_material()
|
|
set_stars_visibility(config.stars_visibility, config.stars_tint)
|