Spaces:
Running
Running
File size: 2,708 Bytes
a28eca3 |
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 128 129 130 |
import {
Mesh,
ShaderMaterial,
SphereGeometry
} from 'three';
class LightProbeHelper extends Mesh {
constructor( lightProbe, size = 1 ) {
const material = new ShaderMaterial( {
type: 'LightProbeHelperMaterial',
uniforms: {
sh: { value: lightProbe.sh.coefficients }, // by reference
intensity: { value: lightProbe.intensity }
},
vertexShader: /* glsl */`
varying vec3 vNormal;
void main() {
vNormal = normalize( normalMatrix * normal );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`,
fragmentShader: /* glsl */`
#define RECIPROCAL_PI 0.318309886
vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {
// matrix is assumed to be orthogonal
return normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );
}
// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf,
vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {
// normal is assumed to have unit length,
float x = normal.x, y = normal.y, z = normal.z;
// band 0,
vec3 result = shCoefficients[ 0 ] * 0.886227;
// band 1,
result += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;
result += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;
result += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;
// band 2,
result += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;
result += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;
result += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );
result += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;
result += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );
return result;
}
uniform vec3 sh[ 9 ]; // sh coefficients
uniform float intensity; // light probe intensity
varying vec3 vNormal;
void main() {
vec3 normal = normalize( vNormal );
vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
vec3 irradiance = shGetIrradianceAt( worldNormal, sh );
vec3 outgoingLight = RECIPROCAL_PI * irradiance * intensity;
gl_FragColor = linearToOutputTexel( vec4( outgoingLight, 1.0 ) );
}
`,
} );
const geometry = new SphereGeometry( 1, 32, 16 );
super( geometry, material );
this.lightProbe = lightProbe;
this.size = size;
this.type = 'LightProbeHelper';
this.onBeforeRender();
}
dispose() {
this.geometry.dispose();
this.material.dispose();
}
onBeforeRender() {
this.position.copy( this.lightProbe.position );
this.scale.set( 1, 1, 1 ).multiplyScalar( this.size );
this.material.uniforms.intensity.value = this.lightProbe.intensity;
}
}
export { LightProbeHelper };
|