-
Notifications
You must be signed in to change notification settings - Fork 2
/
particles.gdshader
121 lines (89 loc) · 3.27 KB
/
particles.gdshader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
shader_type particles;
uniform float spray : hint_range(0.0,5.0) = 0.4;
uniform float bounciness : hint_range(0.0,1.0) = 0.5;
uniform float friction : hint_range(0.0,20.0) = 0.5;
uniform vec3 start_velocity;
uniform sampler2D tex;
uniform vec2 my_screen_pixel_size;
uniform mat4 my_camera;
uniform mat4 my_scuffed_projection;
float rand_from_seed(inout uint seed) {
int k;
int s = int(seed);
if (s == 0)
s = 305420679;
k = s / 127773;
s = 16807 * (s - k * 127773) - 2836 * k;
if (s < 0)
s += 2147483647;
seed = uint(s);
return float(seed % uint(65536)) / 65535.0;
}
uint hash(uint x) {
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = ((x >> uint(16)) ^ x) * uint(73244475);
x = (x >> uint(16)) ^ x;
return x;
}
vec2 getUV(vec3 pos,mat4 viewToClip, mat4 worldToView){
vec4 p = viewToClip*worldToView*vec4(pos,1);
p.xyz /= p.w;
return p.xy*.5+.5;
}
vec3 getWorldPos(vec2 screen, float depth, mat4 clipToView, mat4 viewToWorld){
vec3 ndc = vec3(screen, depth) * 2.0 - 1.0;
/*vec4 view = clipToView * vec4(ndc, 1.0);
view.xyz /= view.w;
float linear_depth = -view.z;*/
vec4 world = viewToWorld * clipToView * vec4(ndc, 1.0);
vec3 world_position = world.xyz / world.w;
return world_position;
}
void vertex(){
if(RESTART){
// random vector
uint base_number = NUMBER;
uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);
vec3 rv = vec3(rand_from_seed(alt_seed),rand_from_seed(alt_seed),rand_from_seed(alt_seed))-.5;
CUSTOM.w = 0.;
COLOR.xyz = vec3(rv+.5);
TRANSFORM[3].xyz = EMISSION_TRANSFORM[3].xyz; //-rand_from_seed(alt_seed)*start_velocity*DELTA;
VELOCITY = start_velocity+rv*spray;
}
else{
// reconstruct projection matrix
mat4 my_projection = my_scuffed_projection;
my_projection[2][3] = -1.;
my_projection[3][3] = 0.;
// get screen space coordinates of particle
vec2 uv = getUV(TRANSFORM[3].xyz,my_projection,inverse(my_camera));
vec4 T = textureLod(tex,uv,0.);
vec3 scene_pos = getWorldPos(uv,T.w,inverse(my_projection),my_camera);
float scene_t = length(scene_pos - my_camera[3].xyz);
float particle_t = length(TRANSFORM[3].xyz - my_camera[3].xyz);
vec3 view = normalize(scene_pos - my_camera[3].xyz);
float penetration_depth = scene_t - particle_t;
bool colliding = penetration_depth <= 0. && penetration_depth >= -length(VELOCITY)*.1;
// handle collision
if(colliding){
// reconstruct normal on scene
vec3 e = vec3(my_screen_pixel_size,0);
vec4 Ta = textureLod(tex,uv+e.xz,0.);
vec4 Tb = textureLod(tex,uv+e.zy,0.);
vec3 scene_pos_a = getWorldPos(uv+e.xz,Ta.w,inverse(my_projection),my_camera);
vec3 scene_pos_b = getWorldPos(uv+e.zy,Tb.w,inverse(my_projection),my_camera);
vec3 collision_normal = normalize( cross(normalize(scene_pos_a-scene_pos),normalize(scene_pos_b-scene_pos)) );
float collision_depth = dot(collision_normal,scene_pos - TRANSFORM[3].xyz);
TRANSFORM[3].xyz += collision_normal * collision_depth;
vec3 a = collision_normal * dot(collision_normal, VELOCITY);
VELOCITY -= a;
VELOCITY = mix(VELOCITY, vec3(0.0), friction*DELTA); //V - Vf dt
VELOCITY -= a*bounciness;
}
// simulate
CUSTOM.w += DELTA;
// integrate gravity acceleration
VELOCITY += vec3(0,-2,0)*DELTA;
COLOR.w = smoothstep(LIFETIME,LIFETIME-.5,CUSTOM.w)*.5;
}
}