diff --git a/addons/post_processing/node/children/particle_storm.tscn b/addons/post_processing/node/children/particle_storm.tscn new file mode 100644 index 0000000..54d8fbe --- /dev/null +++ b/addons/post_processing/node/children/particle_storm.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=3 format=3 uid="uid://c0d4h1un0350r"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/particle_storm.gdshader" id="1_wnruh"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_particle_storm"] +shader = ExtResource("1_wnruh") +shader_parameter/particle_color = Color(0.87, 0.78, 0.6, 1) +shader_parameter/wind_direction = Vector2(1, 0.2) +shader_parameter/wind_speed = 1.0 +shader_parameter/intensity = 0.5 +shader_parameter/chaos = 1.075 +shader_parameter/scale = 1.0 +shader_parameter/density = 1.0 + +[node name="particle_storm" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_particle_storm") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/post_process.gd b/addons/post_processing/node/post_process.gd index 31428c6..988abf4 100644 --- a/addons/post_processing/node/post_process.gd +++ b/addons/post_processing/node/post_process.gd @@ -15,6 +15,7 @@ enum EffectType { GRAIN, OUTLINE, PALETTE, + PARTICLE_STORM, PIXELATE, SCREEN_SHAKE, SPEED_LINES, @@ -112,6 +113,14 @@ func _update_shader_parameters( _type : EffectType, _material : Material) -> voi _material.set_shader_parameter("clip_warp", configuration.clip_warp) _material.set_shader_parameter("vignette_intensity", configuration.vignette_intensity) _material.set_shader_parameter("vignette_opacity", configuration.vignette_opacity) + EffectType.PARTICLE_STORM: # Add new case + _material.set_shader_parameter("particle_color", configuration.particle_storm_color) + _material.set_shader_parameter("wind_direction", configuration.particle_storm_wind_direction) + _material.set_shader_parameter("wind_speed", configuration.particle_storm_wind_speed) + _material.set_shader_parameter("intensity", configuration.particle_storm_intensity) + _material.set_shader_parameter("chaos", configuration.particle_storm_chaos) + _material.set_shader_parameter("scale", configuration.particle_storm_scale) + _material.set_shader_parameter("density", configuration.particle_storm_density) _: push_error("Unhandled/Invalid EffectType: " + str(_type)) @@ -150,6 +159,8 @@ func _check_shader_visibility(_type: EffectType) -> bool: return configuration.SpeedLines EffectType.VIGNETTE: return configuration.Vignette + EffectType.PARTICLE_STORM: + return configuration.particle_storm _: push_error("Unhandled/Invalid EffectType: " + str(_type)) return false @@ -172,6 +183,7 @@ func _ready(): _add_canvas_layer_children("res://addons/post_processing/node/children/color_correction.tscn", EffectType.COLOR_CORRECTION) _add_canvas_layer_children("res://addons/post_processing/node/children/pixelate.tscn", EffectType.PIXELATE) _add_canvas_layer_children("res://addons/post_processing/node/children/palette.tscn", EffectType.PALETTE) + _add_canvas_layer_children("res://addons/post_processing/node/children/particle_storm.tscn", EffectType.PARTICLE_STORM) var null_effects: PackedStringArray = [] for e in effects: diff --git a/addons/post_processing/resource/no_effects_example.tres b/addons/post_processing/resource/no_effects_example.tres index 3348330..ea4ce00 100644 --- a/addons/post_processing/resource/no_effects_example.tres +++ b/addons/post_processing/resource/no_effects_example.tres @@ -32,10 +32,6 @@ Outline = false OutlineColor = Color(0, 0, 0, 1) OutlineThreshold = 0.0 OutlineBlend = 0.01 -ScreenShake = false -ScreenShakePower = 0.1 -AnalogMonitor = false -AnalogMonitorResolution = Vector2(256, 256) Grain = false GrainPower = 75 CircularWaves = false @@ -47,3 +43,42 @@ SpeedLinesColor = Color(1, 1, 1, 1) SpeedLinesCount = 2 SpeedLineDensity = 0.072 SpeedLineSpeed = 20 +particle_storm = false +particle_storm_color = Color(0.87, 0.78, 0.6, 1) +particle_storm_intensity = 0.5 +particle_storm_chaos = 1.0 +particle_storm_scale = 1.0 +particle_storm_density = 1.0 +particle_storm_wind_direction = Vector2(1, 0.2) +particle_storm_wind_speed = 1.0 +ColorCorrection = false +ColorCorrectionTint = Color(0, 0, 0, 1) +ColorCorrectionBrightness = 0.0 +ColorCorrectionSaturation = 0.0 +Palette = false +Pixelate = false +PixelatePixelSize = 8 +CRT = false +overlay = false +scanlines_opacity = 0.4 +scanlines_width = 0.25 +grille_opacity = 0.3 +pixelate = true +roll_speed = 8.0 +roll_size = 15.0 +roll_variation = 1.8 +distort_intensity = 0.05 +noise_opacity = 0.4 +noise_speed = 5.0 +static_noise_intensity = 0.06 +aberration = 0.03 +brightness = 1.4 +discolor = true +warp_amount = 1.0 +clip_warp = false +vignette_intensity = 0.4 +vignette_opacity = 0.5 +AnalogMonitor = false +AnalogMonitorResolution = Vector2(256, 256) +ScreenShake = false +ScreenShakePower = 0.1 diff --git a/addons/post_processing/resource/post_processing_configuration.gd b/addons/post_processing/resource/post_processing_configuration.gd index 184e7fb..1e23bb4 100644 --- a/addons/post_processing/resource/post_processing_configuration.gd +++ b/addons/post_processing/resource/post_processing_configuration.gd @@ -166,6 +166,41 @@ class_name PostProcessingConfiguration extends Resource set(value): SpeedLineSpeed = value reload = true +@export_subgroup("Particle Storm") +@export var particle_storm: bool: + set(value): + particle_storm = value + reload = true +@export var particle_storm_color: Color = Color(0.87, 0.78, 0.60, 1.0): + set(value): + particle_storm_color = value + reload = true +@export_range(0.0, 10.0) var particle_storm_intensity = 0.5: + set(value): + particle_storm_intensity = value + reload = true +@export_range(0.0, 10.0) var particle_storm_chaos = 1.0: + set(value): + particle_storm_chaos = value + reload = true +@export_range(0.5, 10.0) var particle_storm_scale = 1.0: + set(value): + particle_storm_scale = value + reload = true +@export_range(0.0, 10.0) var particle_storm_density = 1.0: + set(value): + particle_storm_density = value + reload = true +@export var particle_storm_wind_direction = Vector2(1.0, 0.2): + set(value): + particle_storm_wind_direction = value + reload = true +@export_range(0.1, 5.0) var particle_storm_wind_speed = 1.0: + set(value): + particle_storm_wind_speed = value + reload = true + + @export_group("Display") @export_subgroup("Color Correction") diff --git a/addons/post_processing/shaders/particle_storm.gdshader b/addons/post_processing/shaders/particle_storm.gdshader new file mode 100644 index 0000000..30fa243 --- /dev/null +++ b/addons/post_processing/shaders/particle_storm.gdshader @@ -0,0 +1,95 @@ +shader_type canvas_item; + +// Visual appearance parameters +uniform vec4 particle_color : source_color = vec4(0.87, 0.78, 0.60, 1.0); +uniform vec2 wind_direction = vec2(1.0, 0.2); // Normalized direction vector +uniform float wind_speed = 1.0; // Movement speed multiplier +uniform float intensity = 0.5; // Overall particle visibility +uniform float chaos = 1.0; // Swirl movement intensity +uniform float scale = 1.0; // UV coordinate scaling factor +uniform float density = 1.0; // Particles per cell multiplier + +// Generates a stable pseudo-random 2D vector from a 2D input +vec2 hash22(vec2 seed_position) { + vec3 hash_input = fract(vec3(seed_position.xyx) * vec3(443.897, 441.423, 437.195)); + hash_input += dot(hash_input, hash_input.yzx + 19.19); + return fract((hash_input.xx + hash_input.yz) * hash_input.zy); +} + +// Calculates particle position based on time and initial conditions +vec2 get_particle_pos(vec2 cell_position, float particle_index, float current_time) { + // Generate initial position using cell and particle index + vec2 initial_position = hash22(cell_position + particle_index * 123.456); + + // Generate unique movement characteristics for this particle + vec2 particle_characteristics = hash22(initial_position * 123.456); + float velocity_variation = 0.7 + particle_characteristics.x * 0.6; + + // Calculate wind-driven movement + vec2 wind_offset = wind_direction * current_time * velocity_variation; + + // Calculate swirling motion parameters + float swirl_phase = current_time * (0.5 + particle_characteristics.y * 0.5); + float swirl_amplitude = 0.1 + particle_characteristics.x * 0.1; + vec2 swirl_offset = vec2( + sin(swirl_phase + initial_position.y * 6.28), + cos(swirl_phase + initial_position.x * 6.28) + ) * swirl_amplitude * chaos; + + // Combine movements and wrap around unit space + return fract(initial_position + wind_offset + swirl_offset); +} + +// Renders a single square particle with soft edges +float get_pixel(vec2 current_uv, vec2 particle_center) { + vec2 distance_to_center = abs(current_uv - particle_center); + + // Base particle size with scale adjustment + float particle_size = 0.04 / scale; + + // Create soft-edged square shape + float square_distance = max(distance_to_center.x, distance_to_center.y); + return 1.0 - smoothstep(particle_size * 0.8, particle_size, square_distance); +} + +void fragment() { + // Transform UV coordinates to scaled space + vec2 scaled_uv = UV * scale; + vec2 current_cell = floor(scaled_uv); + vec2 cell_local_uv = fract(scaled_uv); + + // Calculate time-based movement + float current_time = TIME * wind_speed; + + float total_sand_density = 0.0; + + // Calculate particle count based on density parameter + float particles_per_cell = floor(4.0 + density * 12.0); + + // Render particles from current and neighboring cells + for (float x = -1.0; x <= 1.0; x++) { + for (float y = -1.0; y <= 1.0; y++) { + vec2 neighbor_offset = vec2(x, y); + vec2 neighbor_cell = current_cell + neighbor_offset; + + // Generate and render all particles in this cell + for (float particle_idx = 0.0; particle_idx < particles_per_cell; particle_idx++) { + vec2 particle_pos = get_particle_pos(neighbor_cell, particle_idx, current_time); + vec2 world_pos = (particle_pos + neighbor_offset); + + // Accumulate particle density + total_sand_density += get_pixel(cell_local_uv, world_pos) * 0.25; + } + } + } + + // Apply intensity and clamp to valid range + total_sand_density *= intensity; + total_sand_density = clamp(total_sand_density, 0.0, 1.0); + + // Quantize density for sharper particle appearance + total_sand_density = floor(total_sand_density * 6.0) / 6.0; + + // Output final color with transparency + COLOR = vec4(particle_color.rgb, total_sand_density * particle_color.a); +} \ No newline at end of file