Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions GPUTrail3D.gd
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class_name GPUTrail3D extends GPUParticles3D

# PUBLIC

## Active determines if the trails render or not
@export var active := true : set = _set_active

@export_category("Length")
## Length is the number of steps in the trail
@export var length : int = 100 : set = _set_length
@export var length_seconds : float : set = _set_length
Expand Down Expand Up @@ -53,6 +57,26 @@ class_name GPUTrail3D extends GPUParticles3D
## Enable [member use_red_as_alpha] to use the red color channel of [member texture] as alpha
@export var use_red_as_alpha := false : set = _set_use_red_as_alpha

## An independent alpha value to control total trail transparency. Is also modified if using Fade In Seconds or Fade Out Seconds
@export var alpha : float = 1.0 : set = _set_alpha


@export_category("Fade")
## Fade Curve is a texture that is used to determine the alpha of the trail over it's lifetime
@export var fade_curve : CurveTexture : set = _set_fade_curve
## Fade Curve Intensity is a value used to modify the strength of the Fade Curve
@export var fade_curve_intensity: float = 1.0 : set = _set_fade_curve_intensity

## Fade In Seconds is how many seconds it takes to fade in the trail if active is set to true
@export var fade_in_seconds : float = 0.0 : set = _set_fade_in_seconds
## Fade In Alpha is the Alpha value that the whole trail will go to. The alpha value is also a parameter on the trail
@export var fade_in_alpha : float = 1.0 : set = _set_fade_in_alpha

## Fade Out Seconds is how many seconds it takes to fade out the trail if active is set to false
@export var fade_out_seconds : float = 0.0 : set = _set_fade_out_seconds
## Fade Out Alpha is the Alpha value that the whole trail will go to. The alpha value is also a parameter on the trail
@export var fade_out_alpha : float = 0.0 : set = _set_fade_out_alpha


@export_category("Mesh tweaks")

Expand Down Expand Up @@ -115,6 +139,34 @@ func _ready():
clip_overlaps = clip_overlaps
snap_to_transform = snap_to_transform

func _set_active(value):
active = value
if active and fade_in_seconds > 0.0:
process_material.set_shader_parameter("active", active)
restart()
var tween: Tween = create_tween()
tween.tween_property(self, "alpha", fade_in_alpha, fade_in_seconds)
elif not active and fade_out_seconds > 0.0:
var tween: Tween = create_tween()
tween.tween_property(self, "alpha", fade_out_alpha, fade_out_seconds)
tween.tween_callback(func(): process_material.set_shader_parameter("active", active))
else:
process_material.set_shader_parameter("active", active)
_set_alpha(fade_in_alpha)
restart()

func _set_fade_in_seconds(value):
fade_in_seconds = value

func _set_fade_out_seconds(value):
fade_out_seconds = value

func _set_fade_in_alpha(value):
fade_in_alpha = value

func _set_fade_out_alpha(value):
fade_out_alpha = value

func _set_length(value):
if value is int: # length is being set
length = value
Expand Down Expand Up @@ -161,6 +213,21 @@ func _set_curve(value):
draw_pass_1.material.set_shader_parameter("curve", curve)
else:
draw_pass_1.material.set_shader_parameter("curve", preload(_DEFAULT_CURVE))
func _set_alpha(value):
alpha = clamp(value,0.0,1.0)
if value:
draw_pass_1.material.set_shader_parameter("alpha", value)
else:
draw_pass_1.material.set_shader_parameter("alpha", 1.0)
func _set_fade_curve(value):
fade_curve = value
draw_pass_1.material.set_shader_parameter("fade_curve", fade_curve)
func _set_fade_curve_intensity(value):
fade_curve_intensity = clamp(value,0.0,10.0)
if value:
draw_pass_1.material.set_shader_parameter("fade_curve_intensity", value)
else:
draw_pass_1.material.set_shader_parameter("fade_curve_intensity", 1.0)
func _set_vertical_texture(value):
vertical_texture = value
_flags = _set_flag(_flags,0,value)
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,22 @@ GPUTrail is a GPU-based trail plugin for Godot 4, offering an efficient alternat
3. Attach the `GPUTrail3D` node to the object you want to trail

## Properties

- `active`: Turn on or off the trail
- `length`: Number of steps in the trail
- `texture`: Main texture of the trail
- `mask`: A texture used to modify the alpha of trail. Uses the red channel of the texture to determine what is visible.
- `mask_strength`: A float value from 0.0 to 1.0 for determing how intense the mask texture is
- `color_ramp`: Color gradient along the trail's length
- `curve`: Width modulation along the trail's length
- `vertical_texture`: Adjust texture orientation
- `use_red_as_alpha`: Use the red channel of the texture as alpha
- `alpha`: Determines the overall alpha value of the trail. Is modified if using fade in and out parameters
- `fade_curve`: Curve to control the alpha along the trail's lifetime
- `fade_curve_intensity`: Value to control the strength of the fade curve value
- `fade_in_seconds`: Value to determine how quickly the whole trail fades in if active is set from false to true
- `fade_in_alpha`: Value to determine what alpha value the whole trail fades to if active is set from false to true
- `fade_out_seconds`: Value to determine how quickly the whole trail fades out if active is set from true to false
- `fade_out_alpha`: Value to determine what alpha value the whole trail fades to if active is set from true to false
- `billboard`: Make the trail face the camera (experimental)
- `dewiggle`: Improve texture mapping to the trail
- `clip_overlaps`: Prevent trail self-intersectionis
Expand Down
18 changes: 10 additions & 8 deletions shaders/trail.gdshader
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,39 @@ shader_type particles;

render_mode keep_data,disable_force,disable_velocity;


uniform bool active = true;

void process() {
ACTIVE = active;

// CUSTOM.w tracks the particles place in the trail, in range (0..LIFETIME]
// requires that LIFETIME = number of particles
float amount = LIFETIME;

vec4 a = EMISSION_TRANSFORM * vec4(0,1,0,1);
vec4 b = EMISSION_TRANSFORM * vec4(0,-1,0,1);

// start
if(CUSTOM.w == 0.0){
CUSTOM.w = float(INDEX)+1.0;

// needed to pass to draw pass
CUSTOM.z = amount;

// needed to initialize in case of CUSTOM.w == 2.0
TRANSFORM = mat4(a,a,b,b);
}

// restart
if(CUSTOM.w == amount+1.0){
CUSTOM.w = 1.0;
}

if(CUSTOM.w == 1.0){
// sets the quad to the line to cache this frame, it is not yet visible
TRANSFORM = mat4(a,a,b,b);
}

if(CUSTOM.w == 2.0){
// sets the right edge of the quad
TRANSFORM[1] = a;
Expand Down
21 changes: 16 additions & 5 deletions shaders/trail_draw_pass.gdshader
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ render_mode unshaded,world_vertex_coords,cull_disabled;
uniform sampler2D tex : repeat_enable, source_color, hint_default_white;
uniform sampler2D mask : hint_default_white;
uniform float mask_strength = 1.0;
uniform sampler2D fade_curve: repeat_disable, hint_default_white;
uniform float fade_curve_intensity = 1.0;
uniform float alpha = 1.0;
uniform vec2 uv_offset = vec2(0);
uniform sampler2D color_ramp : repeat_disable, source_color, hint_default_white;
uniform sampler2D curve : repeat_disable, hint_default_white;
Expand All @@ -27,6 +30,7 @@ uniform bool snap_to_transform = false;*/
varying float scale_interp;
varying vec2 clip;
varying vec2 mesh_uv;
varying float particle_lifetime;
void vertex(){
mesh_uv = UV;

Expand Down Expand Up @@ -76,6 +80,7 @@ void vertex(){
UV *= scale_interp;
}

particle_lifetime = INSTANCE_CUSTOM.y;

clip.x = dot(VERTEX - INV_VIEW_MATRIX[3].xyz,cross(my_model_matrix[1].xyz - INV_VIEW_MATRIX[3].xyz,my_model_matrix[2].xyz - INV_VIEW_MATRIX[3].xyz));
clip.y = dot(VERTEX - INV_VIEW_MATRIX[3].xyz,cross(my_model_matrix[3].xyz - INV_VIEW_MATRIX[3].xyz,my_model_matrix[0].xyz - INV_VIEW_MATRIX[3].xyz));
Expand Down Expand Up @@ -120,16 +125,22 @@ void fragment(){
ALPHA = T.r;
}

vec4 F = textureLod(fade_curve, raw_uv, 0.0);
float fade_alpha = F.x * (fade_curve_intensity - (particle_lifetime * fade_curve_intensity));
ALPHA *= fade_alpha;

T = textureLod(color_ramp, raw_uv, 0.0);
float texture_alpha = T.a;
ALBEDO *= T.rgb;
ALPHA *= T.a;

vec4 M = textureLod(mask, base_uv, 0.0);
ALPHA *= (M.r * mask_strength);
ALPHA *= texture_alpha;

//ALBEDO = vec3(UV,0);
vec4 M = textureLod(mask, raw_uv, 0.0);
float mask_alpha = (M.r * mask_strength);
ALPHA *= mask_alpha;

if((base_uv.x < .01) || (.99 < base_uv.x)){
//ALBEDO = vec3(1,0,1);
}

ALPHA *= alpha;
}