aboutsummaryrefslogtreecommitdiff
path: root/src/shader/compute.glsl
blob: eaf55793a3b841745d786248d49e50001c40b56a (plain)
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
static const std::string COMPUTE_SHADER_CODE = R"(
#version 430

layout (local_size_x = 1) in;
layout (std430, binding=1) buffer bufferA{ float data[]; };

uniform vec2 world;

// ODE solver

vec2 f(vec2); // field definition is to be appended

vec2 explicitEuler(float h, vec2 v) {
	return v + h * f(v);
}

vec2 classicalRungeKutta(float h, vec2 v) {
	const vec2 k1 = f(v);
	const vec2 k2 = f(v + h/2. * k1);
	const vec2 k3 = f(v + h/2. * k2);
	const vec2 k4 = f(v + h    * k3);

	return v + h * (1./6.*k1 + 1./3.*k2 + 1./3.*k3 + 1./6.*k4);
}

// pseudo random numbers for particle placement

float rand(vec2 v){
	return fract(sin(dot(v, vec2(12.9898,78.233))) * 43758.5453);
}

float mapUnitToWorldX(float s) {
	return -(world.x/2.) + s * world.x;
}

float mapUnitToWorldY(float s) {
	return -(world.y/2.) + s * world.y;
}

bool insideWorld(vec2 v) {
	return v.x > -world.x/2.
	    && v.x <  world.x/2.
	    && v.y > -world.y/2.
	    && v.y <  world.y/2.;
}

void main() {
	const uint i = 3*gl_GlobalInvocationID.x;
	const vec2 v = vec2(data[i+0], data[i+1]);
	const vec2 w = classicalRungeKutta(0.01, v);

	if ( data[i+2] < 5. && insideWorld(v) ) {
		data[i+0]  = w.x;
		data[i+1]  = w.y;
		data[i+2] += 0.01;
	} else {
		data[i+0] = mapUnitToWorldX(rand(v));
		data[i+1] = mapUnitToWorldY(rand(w));
		data[i+2] = rand(v+w) * 5.;
	}
}
)";