Skip to content

Instantly share code, notes, and snippets.

@szamq
Created February 17, 2019 02:12
Show Gist options
  • Save szamq/44694061e190b748722e6dc5c04885d8 to your computer and use it in GitHub Desktop.
Save szamq/44694061e190b748722e6dc5c04885d8 to your computer and use it in GitHub Desktop.
shader_type particles;
//render_mode disable_velocity,disable_force,keep_data;
uniform sampler2D map;
uniform float map_mipmap=2.0;
uniform vec2 collider_position;
uniform float collider_radius;
uniform float particle_radius;
uniform float sample_range=5.0;
uniform float sample_step=1.0;
uniform vec2 partcile_counter_position=vec2(-250.0,0.0);
uniform vec4 partcile_counter_one_color=vec4(1.0,0.0,0.0,0.01);
uniform float spread;
uniform float scale;
uniform float scale_random;
uniform float initial_linear_velocity;
uniform float initial_linear_velocity_random;
uniform float initial_angle;
uniform float initial_angle_random;
uniform float angular_velocity;
uniform float angular_velocity_random;
uniform vec3 emission_box_extents;
uniform vec4 color_value : hint_color;
uniform vec3 gravity;
float when_lt(float x, float y)
{
return max(sign(y - x), 0.0);
}
float pixel_is_solid(vec2 pos)
{
return textureLod(map,pos/8192.0,map_mipmap).a;
}
vec2 collision_normal(vec2 pos)
{
vec2 avg=vec2(0.0,0.0);
for(float i = -sample_range; i<=sample_range;i+=sample_step)
{
for(float j = -sample_range; j<=sample_range;j+=sample_step)
{
avg -= vec2(i,j)*(pixel_is_solid(vec2(pos.x+i,pos.y+j)));
}
}
if(avg.x==0.0 && avg.y==0.0)
avg=vec2(0.0);
else
avg=normalize(avg);
return avg;
}
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;
}
float rand_from_seed_m1_p1(inout uint seed) {
return rand_from_seed(seed) * 2.0 - 1.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;
}
void vertex() {
CUSTOM.w=0.0;
uint base_number = NUMBER ;
uint alt_seed = hash(base_number + uint(1) + RANDOM_SEED);
float angle_rand = rand_from_seed(alt_seed);
float scale_rand = rand_from_seed(alt_seed);
float hue_rot_rand = rand_from_seed(alt_seed);
float anim_offset_rand = rand_from_seed(alt_seed);
float pi = 3.14159;
float degree_to_rad = pi / 180.0;
float base_scale = mix(scale , 1.0, scale_random * scale_rand);
base_scale = max(0.000001,base_scale);
float base_angle = (initial_angle) * mix(1.0, angle_rand, initial_angle_random);
if (RESTART) {
COLOR=color_value;
float spread_rad = spread * degree_to_rad;
float angle1_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad;
vec3 rot = vec3(cos(angle1_rad), sin(angle1_rad), 0.0);
VELOCITY = rot * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);
CUSTOM.x = 1.0; // Scale multiplier
CUSTOM.y = angular_velocity * mix(1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, angular_velocity_random); // Time rotation
CUSTOM.z =0.0; // is dying
CUSTOM.w =0.0; // count me in (only one frame)
TRANSFORM[3].xyz = vec3(rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, rand_from_seed(alt_seed) * 2.0 - 1.0) * emission_box_extents;
TRANSFORM = EMISSION_TRANSFORM * TRANSFORM;
VELOCITY.z = 0.0;
}
//CUSTOM.y += DELTA ;
float collision=pixel_is_solid(TRANSFORM[3].xy);
if(!RESTART && collision>0.01)
{
vec2 normal = collision_normal(TRANSFORM[3].xy);
if(normal.x==0.0 && normal.y==0.0)
{
VELOCITY.xy=max(VELOCITY.xy*0.90,vec2(0.0));
}
else
{
VELOCITY+=normalize(vec3(angle_rand-0.5,angle_rand-0.5,0.0))*initial_linear_velocity*when_lt( length(VELOCITY),0.0001);
float projection = dot(VELOCITY.xy,normal);
VELOCITY.xy=reflect(vec3(VELOCITY.xy,0.0),vec3(normal,0.0)).xy;
//VELOCITY.xy -= 2.0*(normal * projection ).xy;
VELOCITY.xy=normalize(VELOCITY.xy)*initial_linear_velocity;
TRANSFORM[3].xy+=VELOCITY.xy*DELTA;
TRANSFORM[3].xy+=normal;
}
}else
{
//VELOCITY=normalize(vec3(angle_rand-0.5,angle_rand-0.5,0.0))*initial_linear_velocity*when_lt( length(VELOCITY),initial_linear_velocity);
VELOCITY.xy+=vec2(angle_rand-0.5,angle_rand-0.5)*when_lt( length(VELOCITY),0.01);
VELOCITY.xy=normalize(VELOCITY.xy)*initial_linear_velocity;
//
}
if(CUSTOM.z<1.0 && distance(TRANSFORM[3].xy,collider_position)<(collider_radius+particle_radius))
{
CUSTOM.w=1.0;//count
CUSTOM.z=1.0;//is dying flag
}
if(CUSTOM.z>1.2) //remove particle
{
CUSTOM.x=0.0; //scale to zero
COLOR=vec4(0.0,0.0,0.0,0.0); // transparent color
}else
if(CUSTOM.z>0.0) //dying animaiton
{
COLOR.a=clamp(COLOR.a-0.05,0.0,1.0);
// VELOCITY.xy*=0.9;
float scal=1.3;
CUSTOM.x*=scal;
CUSTOM.x=CUSTOM.x*when_lt(CUSTOM.x ,53.9);//TOOTOT
if(COLOR.a<=0.0)// move to the special place for counting
{
CUSTOM.x=2.0; //scale up to make sure it covers the pixel
VELOCITY=vec3(0.0); // dont move
CUSTOM.z=2.0; // flag to 2.0 to remove the particle in the next frame
TRANSFORM[3].xy=partcile_counter_position;
COLOR=partcile_counter_one_color;
}
}
base_angle += CUSTOM.y*(1.0-when_lt(length(VELOCITY.xy),0.1))*when_lt(collision,0.1);/* (angular_velocity ) /** mix(1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, angular_velocity_random)*/
CUSTOM.y+=angular_velocity*mix(1.0, rand_from_seed(alt_seed) * 2.0 - 1.0, angular_velocity_random);
float rotation= base_angle * degree_to_rad;
TRANSFORM[0] = vec4(cos(rotation), -sin(rotation), 0.0, 0.0);
TRANSFORM[1] = vec4(sin(rotation), cos(rotation), 0.0, 0.0);
TRANSFORM[2] = vec4(0.0, 0.0, 1.0, 0.0);
TRANSFORM[0].xyz *= base_scale*clamp(CUSTOM.x,0.0,3.0);
TRANSFORM[1].xyz *= base_scale*clamp(CUSTOM.x,0.0,3.0);
TRANSFORM[2].xyz *= base_scale*clamp(CUSTOM.x,0.0,3.0);
TRANSFORM[3].z = 0.0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment