-
Notifications
You must be signed in to change notification settings - Fork 1
/
sand.html
109 lines (93 loc) · 3.83 KB
/
sand.html
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
<!DOCTYPE html>
<html>
<head>
<title>Sand</title>
<script src="myr.js"></script>
<script src="convTex.js"></script>
</head>
<body>
<canvas id="renderer" width=1200 height=800></canvas>
<script>
const canvas = document.getElementById("renderer");
const rect = canvas.getBoundingClientRect();
const mousePrevious = new Myr.Vector(0, 0);
const mouseCurrent = new Myr.Vector(0, 0);
const myr = new Myr(canvas);
const hueStep = 0.211;
const brushRadius = 16;
const brushSpacing = 6;
const scale = 2;
const texture = new ConvTex(
myr,
new myr.Shader(
"lowp vec4 get(int dx, int dy) {" +
"mediump vec2 location = uv + pixelSize * vec2(dx, dy);" +
"if (location.y > 1.0)" +
"return vec4(1);" +
"else if (location.y < 0.0)" +
"return vec4(0);" +
"return texture(source, location);" +
"}" +
"void main() {" +
"color = get(0, 0);" +
"if (color.a == 0.0) {" +
"if (get(0, -1).a == 1.0)" +
"color = get(0, -1);" +
"else if (get(1, -1).a == 1.0 && get(2, 0).a == 1.0 && get(1, 0).a == 1.0 && !(get(-1, -1).a == 1.0 && get(-2, 0).a == 1.0 && get(-1, 0).a == 1.0))" +
"color = get(1, -1);" +
"else if (get(-1, -1).a == 1.0 && get(-2, 0).a == 1.0 && get(-1, 0).a == 1.0)" +
"color = get(-1, -1);" +
"} else if (" +
"get(0, 1).a == 0.0 || (" +
"(get(-1, 1).a == 0.0 && get(1, 1).a == 1.0 && get(-1, 0).a == 0.0 && !(get(-2, 0).a == 1.0 && get(-3, 1).a == 1.0 && get(-2, 1).a == 1.0)) ||" +
"(get(1, 1).a == 0.0 && get(-1, 1).a == 1.0 && get(1, 0).a == 0.0)))" +
"color = vec4(0);" +
"}",
["source"],
[]
),
myr.getWidth() / scale,
myr.getHeight() / scale);
let brushDown = false;
let brushColor = null;
let hue = Math.random();
myr.setClearColor(new Myr.Color(0.9, 0.88, 0.84));
myr.utils.loop(function(timeStep) {
for (let i = 0; i < 3; ++i)
texture.update();
myr.bind();
myr.clear();
texture.getFront().drawScaled(0, 0, scale, scale);
myr.flush();
return true;
});
canvas.addEventListener("mousedown", event => {
brushDown = true;
hue = (hue + hueStep) % 1;
brushColor = Myr.Color.fromHSV(hue, 0.7, 0.7);
});
canvas.addEventListener("mouseup", () => {
brushDown = false;
});
canvas.addEventListener("mousemove", event => {
mousePrevious.x = mouseCurrent.x;
mousePrevious.y = mouseCurrent.y;
mouseCurrent.x = (event.clientX - rect.left) / scale;
mouseCurrent.y = (event.clientY - rect.top) / scale;
if (brushDown && !mousePrevious.equals(mouseCurrent)) {
const dx = mouseCurrent.x - mousePrevious.x;
const dy = mouseCurrent.y - mousePrevious.y;
const dl = Math.sqrt(dx * dx + dy * dy);
texture.getFront().bind();
for (let d = 0; d < dl; d += brushSpacing)
myr.primitives.fillCircle(
brushColor,
mousePrevious.x + (dx / dl) * d,
mousePrevious.y + (dy / dl) * d,
brushRadius
);
}
});
</script>
</body>
</html>