My online presence
Below is my implementation and slight modification of the perlin noise based shader described on this excellent tutorial.
You create a custom shader by declaring a THREE.ShaderMaterial
and initialize it with the
following properties:
material = new THREE.ShaderMaterial( {
uniforms: {
tExplosion: { type: "t", value: THREE.ImageUtils.loadTexture( '/assets/img/explosion.png' ) },
time: { type: "f", value: 0.0 },
weight: { type: "f", value: 10.0 }
},
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
The vertex shader here displaces each vertex along the pre-deformation normal scaled by a factor defined by the value of the perlin noise at that point. It uses the uv coordinates of the polygon to map the perlin space to the sphere surface.
// insert contents of https://github.com/ashima/webgl-noise/blob/master/src/classicnoise3D.glsl
varying vec2 vUv;
varying vec3 vReflect;
varying vec3 pos;
varying float ao;
uniform float time;
uniform float weight;
varying float d;
float stripes( float x, float f) {
float PI = 3.14159265358979323846264;
float t = .5 + .5 * sin( f * 2.0 * PI * x);
return t * t - .5;
}
float turbulence( vec3 p ) {
float w = 100.0;
float t = -.5;
for (float f = 1.0 ; f <= 10.0 ; f++ ){
float power = pow( 2.0, f );
t += abs( pnoise( vec3( power * p ), vec3( 10.0, 10.0, 10.0 ) ) / power );
}
return t;
}
void main() {
vUv = uv;
vec4 mPosition = modelMatrix * vec4( position, 1.0 );
vec3 nWorld = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );
vReflect = normalize( reflect( normalize( mPosition.xyz - cameraPosition ), nWorld ) );
pos = position;
// float noise = .3 * pnoise( 8.0 * vec3( normal ) );
float noise = 10.0 * -.10 * turbulence( .5 * normal + time );
// float noise = - stripes( normal.x + 2.0 * turbulence( normal ), 1.6 );
float displacement = - weight * noise;
displacement += 5.0 * pnoise( 0.05 * position + vec3( 2.0 * time ), vec3( 100.0 ) );
ao = noise;
vec3 newPosition = position + normal * vec3( displacement );
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
Do some more funky math, honestly I found all this a little hard to follow.
varying vec2 vUv;
uniform sampler2D tExplosion;
varying vec3 vReflect;
varying vec3 pos;
varying float ao;
varying float d;
float PI = 3.14159265358979323846264;
float random(vec3 scale,float seed){return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);}
void main() {
vec2 uv = vec2( 0, 1.3 * ao + .01 * random(vec3(12.9898,78.233,151.7182),0.0) );
uv = clamp( uv, vec2( 0. ), vec2( 1. ) );
vec3 color = texture2D( tExplosion, uv ).rgb;
gl_FragColor = vec4( color.rgb, 1.0 );
}