Skip to content

Commit c59e7c2

Browse files
author
Matt Henderson
authored
Add butterfly anaglyph (#3)
1 parent 7b13226 commit c59e7c2

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

public/images/butterfly-text.png

154 Bytes
Loading

src/animations/anaglyph.tsx

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// @ts-ignore
2+
import { GlslPipeline } from 'glsl-pipeline';
3+
import { RepeatWrapping, TextureLoader, WebGLRenderer } from 'three';
4+
5+
import { Animation, DrawArgs, DrawFn, MakeDrawFn, Parameter } from 'lib/Animation';
6+
import Utils from 'lib/utils';
7+
8+
import shader from './shaders/anaglyph.glsl';
9+
10+
const Anaglyph = () => {
11+
const duration = 6;
12+
const canvasWidth = 768;
13+
const canvasHeight = 768;
14+
15+
const parameters: Parameter[] = [
16+
{
17+
name: 'redness',
18+
minValue: 0,
19+
maxValue: 1,
20+
defaultValue: 0,
21+
compute: Utils.makeTransitionFunction([
22+
{
23+
easing: 'smoothstep',
24+
startT: 0.5,
25+
endT: duration - 0.5,
26+
startValue: 0,
27+
endValue: 1,
28+
},
29+
]),
30+
},
31+
];
32+
33+
const makeDrawFn: MakeDrawFn = (canvas) => {
34+
const texLoader = new TextureLoader();
35+
let u_tex0 = texLoader.load('/animations/images/butterfly-text.png', () => {
36+
drawFn({ t: 0, redness: 0 });
37+
});
38+
u_tex0.generateMipmaps = false;
39+
u_tex0.wrapS = RepeatWrapping;
40+
u_tex0.wrapT = RepeatWrapping;
41+
const renderer = new WebGLRenderer({
42+
canvas,
43+
});
44+
let pipeline = new GlslPipeline(renderer, { u_redness: { value: 0 }, u_tex0: { type: 't', value: u_tex0 } });
45+
pipeline.load(shader);
46+
Utils.resetGlslPipeline(pipeline);
47+
48+
const drawFn: DrawFn = ({ t, redness }: DrawArgs) => {
49+
if (t == 0) {
50+
Utils.resetGlslPipeline(pipeline);
51+
}
52+
pipeline.uniforms.u_redness.value = redness;
53+
pipeline.renderMain();
54+
};
55+
56+
return drawFn;
57+
};
58+
59+
return (
60+
<Animation
61+
duration={duration}
62+
initialCanvasWidth={canvasWidth}
63+
initialCanvasHeight={canvasHeight}
64+
makeDrawFn={makeDrawFn}
65+
parameters={parameters}
66+
/>
67+
);
68+
};
69+
70+
export default Anaglyph;

src/animations/shaders/anaglyph.glsl

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
uniform vec2 u_resolution;
2+
uniform float u_redness;
3+
uniform sampler2D u_tex0;
4+
5+
mat2 rotationMatrix(float angle) {
6+
float sine = sin(angle), cosine = cos(angle);
7+
return mat2(cosine, -sine, sine, cosine);
8+
}
9+
10+
vec3 hash32(vec2 p) {
11+
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
12+
p3 += dot(p3, p3.yxz + 33.33);
13+
return fract((p3.xxy + p3.yzz) * p3.zyx);
14+
}
15+
16+
float hash12(vec2 p) {
17+
vec3 p3 = fract(vec3(p.xyx) * .1031);
18+
p3 += dot(p3, p3.yzx + 33.33);
19+
return fract((p3.x + p3.y) * p3.z);
20+
}
21+
22+
float dist(vec2 uv) {
23+
uv -= 0.5;
24+
uv *= rotationMatrix(0.3);
25+
uv *= 2.;
26+
uv += vec2(0.2, 0.3);
27+
uv.x = max(uv.x, -uv.x);
28+
vec2 p = uv * 20.0;
29+
float r = length(p);
30+
float t = atan(p.y, p.x);
31+
float butterfly = 7. - 0.5 * sin(1. * t) + 2.5 * sin(3. * t) + 2.0 * sin(5. * t) - 1.7 * sin(7. * t) + 3.0 * cos(2. * t) - 2.0 * cos(4. * t) - 0.4 * cos(16. * t) - r;
32+
return butterfly;
33+
}
34+
35+
void main() {
36+
vec2 pixel = 1.0 / u_resolution.xy;
37+
38+
vec2 uv = gl_FragCoord.xy * pixel;
39+
40+
float res = 100.0;
41+
42+
// butterfly text texture is 42 by 7
43+
int y = int(floor(uv.y * res)) % 7;
44+
float rowIndex = floor(uv.y * res / 7.0);
45+
int x = int(floor(uv.x * res) + 20. * sin(rowIndex * 2.) + 100.0) % 42;
46+
47+
float butterflyText = texelFetch(u_tex0, ivec2(x, y), 0).r;
48+
49+
vec2 uvI = floor(uv * res) / res;
50+
51+
float message = 0.;
52+
53+
// Add the text
54+
message = mix(message, 0.9, smoothstep(0., pixel.x, 1. - butterflyText));
55+
56+
// Add outside of butterfly
57+
message = mix(message, 0.7, smoothstep(0., pixel.x, dist(uvI)));
58+
59+
// Subtract inside of butterfly
60+
message = mix(0.1, message, smoothstep(0., pixel.x, 2. - dist(uvI)));
61+
62+
// Add noise
63+
message = mix(message, 0.8, smoothstep(0.0, 1.5, hash12(uvI * u_resolution.xy)));
64+
65+
message = 1. - 0.6 * message;
66+
67+
// Start as noise
68+
vec3 color = hash32(uvI * u_resolution.xy);
69+
// combine random color with the message.
70+
color.r = mix(clamp(color.r, 0.7, 1.0), 0.2 * color.r, message);
71+
color = mix(color, vec3(1.0, 0, 0) * color, u_redness);
72+
color.g *= 0.5; // Reduce green.
73+
74+
// color = vec3(message);
75+
gl_FragColor = vec4(color, 1.0);
76+
77+
}

src/index.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Link, RouterProvider, createHashRouter } from 'react-router-dom';
1010
import Hypocycloids from './animations/hypocycloids';
1111
import './index.css';
1212
import './index.css';
13+
import Anaglyph from 'animations/anaglyph';
1314

1415
const animations = [
1516
{
@@ -24,6 +25,10 @@ const animations = [
2425
name: 'noiseDodecahedron',
2526
component: NoiseDodecahedron,
2627
},
28+
{
29+
name: 'anaglyph',
30+
component: Anaglyph,
31+
},
2732
{
2833
name: 'minimal2d',
2934
component: Minimal2D,

0 commit comments

Comments
 (0)