/
gpgpu-state.ts
127 lines (111 loc) · 3.08 KB
/
gpgpu-state.ts
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
122
123
124
125
126
127
import {
Mesh,
MeshBasicMaterial,
WebGLRenderer,
DoubleSide,
Group,
} from "three";
import {
sketch,
createStateTextureAst,
createDomeSimpleLight,
createDomeSimpleOpts,
createGeometryFactory,
GeometryAlignment,
encodeFillDataTexture4,
} from "@jamieowen/three";
import {
program,
defMain,
uniform,
assign,
vec4,
vec3,
sym,
texture,
input,
$xyz,
mul,
$w,
ifThen,
length,
lte,
float,
} from "@thi.ng/shader-ast";
const createStateUpdate = (renderer: WebGLRenderer, size: number) => {
return createStateTextureAst(renderer, {
count: 3,
geomType: "triangle",
width: size,
height: size,
updateProgram: (target) => {
// Read State.
const uni_state1 = uniform("sampler2D", "state_1");
const uni_state2 = uniform("sampler2D", "state_2");
const input_vUv = input("vec2", "vReadUV"); // TODO: Rename vReadUV - vUv
// Main
const s1 = sym(texture(uni_state1, input_vUv));
const s2 = sym(texture(uni_state2, input_vUv));
const time = uniform("float", "time");
return program([
uni_state1,
uni_state2,
input_vUv,
time,
defMain(() => [
s1,
s2,
ifThen(lte(length($xyz(s1)), float(0.001)), [
assign($xyz(s1), vec3(1.0)),
]),
assign(target.gl_FragColor, vec4(mul($xyz(s1), $w(s1)), $w(s1))),
]),
]);
},
});
};
sketch(({ render, renderer, scene, controls }) => {
const { lights } = createDomeSimpleLight(
scene,
createDomeSimpleOpts({ showHelpers: true, color: "#eeeeff" })
);
lights[1].position.x += 2;
const size = 128;
const startData = encodeFillDataTexture4(size, size, (arr, offset) => {
arr[offset] = Math.random() * 2.0 - 1.0;
arr[offset + 1] = Math.random() * 2.0 - 1.0;
arr[offset + 2] = Math.random() * 2.0 - 1.0;
arr[offset + 3] = 0.9 + Math.random() * 0.09; // set some decay speed
});
// Update
const state = createStateUpdate(renderer, size);
state.material.uniforms.time = { value: 0 };
// Write Start Data.
state.write(startData);
// state.update();
// Display texture for state.
const gf = createGeometryFactory();
const geom = gf.create("plane", GeometryAlignment.BOTTOM);
const mesh1 = new Mesh(geom, new MeshBasicMaterial({ side: DoubleSide }));
const mesh2 = new Mesh(geom, new MeshBasicMaterial({ side: DoubleSide }));
const group = new Group();
group.add(mesh1, mesh2);
scene.add(group);
mesh1.position.set(-0.55, 0, 0);
mesh2.position.set(0.55, 0, 0);
group.scale.multiplyScalar(6);
mesh1.castShadow = mesh2.castShadow = true;
renderer.shadowMap.enabled = true;
controls.target.y = 2.8;
controls.target.x = -0.2;
controls.object.position.y = 2;
controls.object.position.x -= 2;
controls.object.position.multiplyScalar(1.5);
controls.update();
render((clock) => {
state.material.uniforms.time.value = clock.time;
state.update();
(mesh1.material as MeshBasicMaterial).map = state.states[1].texture;
(mesh2.material as MeshBasicMaterial).map = state.states[2].texture;
});
});