This repository has been archived by the owner on Dec 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 56
/
Glow.js
105 lines (91 loc) · 2.55 KB
/
Glow.js
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
import React from 'react';
import * as THREE from 'three';
import { useThree } from 'react-three-fiber';
import { useSpring, animated } from 'react-spring/three';
import { normalize } from '../../utils';
import useOnChange from '../../hooks/use-on-change.hook';
import { getSpringConfigForLight } from './Preview.helpers';
const ON_PROPS = { opacity: 0.75 };
const OFF_PROPS = { opacity: 0 };
const BRIGHT_PROPS = { opacity: 1 };
const vertexShader = `
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`;
const fragmentShader = `
uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}
`;
const Glow = ({
x,
y,
z,
color,
size,
status,
lastEventId,
isPlaying,
isBlooming,
}) => {
const { camera } = useThree();
let springConfig = getSpringConfigForLight(
[ON_PROPS, OFF_PROPS, BRIGHT_PROPS],
status
);
useOnChange(() => {
if (!isPlaying) {
return;
}
const statusShouldReset = status === 'flash' || status === 'fade';
springConfig.reset = statusShouldReset;
}, lastEventId);
const spring = useSpring(springConfig);
// When blooming, the `c` uniform makes it white and obnoxious, so tune the
// effect down in this case.
const MAX_C_VALUE = isBlooming ? 0.2 : 0.001;
return (
<mesh position={[x, y, z]}>
<sphereGeometry attach="geometry" args={[size, 32, 16]} />
<animated.shaderMaterial
attach="material"
args={[
{
uniforms: {
c: { type: 'f', value: MAX_C_VALUE },
p: { type: 'f', value: undefined },
glowColor: { type: 'c', value: new THREE.Color(color) },
viewVector: { type: 'v3', value: camera.position },
},
vertexShader,
fragmentShader,
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true,
},
]}
uniforms-glowColor-value={new THREE.Color(color)}
uniforms-p-value={spring.opacity.interpolate(o =>
normalize(o, 0, 1, 28, 7)
)}
uniforms-c-value={spring.opacity.interpolate(o =>
normalize(o, 0, 1, 0.1, MAX_C_VALUE)
)}
/>
</mesh>
);
};
export default Glow;