Last active
April 28, 2024 17:55
-
-
Save jackismissing/f8ef913fd5bdf05284624c63f78d1e68 to your computer and use it in GitHub Desktop.
Threejs MeshMatcapMaterial normals displacement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const matcapTexture = new THREE.TextureLoader().load(matcap); | |
const material = new THREE.MeshMatcapMaterial({ | |
color: 0xFFFFFF, | |
matcap: matcapTexture | |
}); | |
const uniforms = { | |
uTime: { value: 0 } | |
}; | |
const mesh = new THREE.Mesh( | |
new THREE.SphereBufferGeometry(4.2, 100, 100), | |
material | |
); | |
material.onBeforeCompile = (shader) => { | |
for (const key in uniforms) { | |
shader.uniforms[key] = uniforms[key]; | |
} | |
shader.fragmentShader = shader.fragmentShader.replace( | |
'void main() {', | |
[ | |
'vec3 orthogonal(vec3 v) {', | |
' return normalize(abs(v.x) > abs(v.z) ? vec3(-v.y, v.x, 0.0) : vec3(0.0, -v.z, v.y));', | |
'}', | |
'//', | |
'// Description : Array and textureless GLSL 2D/3D/4D simplex ', | |
'// noise functions.', | |
'// Author : Ian McEwan, Ashima Arts.', | |
'// Maintainer : stegu', | |
'// Lastmod : 20201014 (stegu)', | |
'// License : Copyright (C) 2011 Ashima Arts. All rights reserved.', | |
'// Distributed under the MIT License. See LICENSE file.', | |
'// https://github.com/ashima/webgl-noise', | |
'// https://github.com/stegu/webgl-noise', | |
'// ', | |
'vec3 mod289(vec3 x) {', | |
'return x - floor(x * (1.0 / 289.0)) * 289.0;', | |
'}', | |
'vec4 mod289(vec4 x) {', | |
'return x - floor(x * (1.0 / 289.0)) * 289.0;', | |
'}', | |
'vec4 permute(vec4 x) {', | |
'return mod289(((x*34.0)+1.0)*x);', | |
'}', | |
'vec4 taylorInvSqrt(vec4 r)', | |
'{', | |
'return 1.79284291400159 - 0.85373472095314 * r;', | |
'}', | |
'float snoise(vec3 v, vec3 gradient)', | |
'{', | |
'const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;', | |
'const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);', | |
'// First corner', | |
'vec3 i = floor(v + dot(v, C.yyy) );', | |
'vec3 x0 = v - i + dot(i, C.xxx) ;', | |
'// Other corners', | |
'vec3 g = step(x0.yzx, x0.xyz);', | |
'vec3 l = 1.0 - g;', | |
'vec3 i1 = min( g.xyz, l.zxy );', | |
'vec3 i2 = max( g.xyz, l.zxy );', | |
'// x0 = x0 - 0.0 + 0.0 * C.xxx;', | |
'// x1 = x0 - i1 + 1.0 * C.xxx;', | |
'// x2 = x0 - i2 + 2.0 * C.xxx;', | |
'// x3 = x0 - 1.0 + 3.0 * C.xxx;', | |
'vec3 x1 = x0 - i1 + C.xxx;', | |
'vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y', | |
'vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y', | |
'// Permutations', | |
'i = mod289(i); ', | |
'vec4 p = permute( permute( permute( ', | |
'i.z + vec4(0.0, i1.z, i2.z, 1.0 ))', | |
'+ i.y + vec4(0.0, i1.y, i2.y, 1.0 )) ', | |
'+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));', | |
'// Gradients: 7x7 points over a square, mapped onto an octahedron.', | |
'// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)', | |
'float n_ = 0.142857142857; // 1.0/7.0', | |
'vec3 ns = n_ * D.wyz - D.xzx;', | |
'vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)', | |
'vec4 x_ = floor(j * ns.z);', | |
'vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)', | |
'vec4 x = x_ *ns.x + ns.yyyy;', | |
'vec4 y = y_ *ns.x + ns.yyyy;', | |
'vec4 h = 1.0 - abs(x) - abs(y);', | |
'vec4 b0 = vec4( x.xy, y.xy );', | |
'vec4 b1 = vec4( x.zw, y.zw );', | |
'//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;', | |
'//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;', | |
'vec4 s0 = floor(b0)*2.0 + 1.0;', | |
'vec4 s1 = floor(b1)*2.0 + 1.0;', | |
'vec4 sh = -step(h, vec4(0.0));', | |
'vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;', | |
'vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;', | |
'vec3 p0 = vec3(a0.xy,h.x);', | |
'vec3 p1 = vec3(a0.zw,h.y);', | |
'vec3 p2 = vec3(a1.xy,h.z);', | |
'vec3 p3 = vec3(a1.zw,h.w);', | |
'//Normalise gradients', | |
'vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));', | |
'p0 *= norm.x;', | |
'p1 *= norm.y;', | |
'p2 *= norm.z;', | |
'p3 *= norm.w;', | |
'// Mix final noise value', | |
'vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);', | |
'vec4 m2 = m * m;', | |
'vec4 m4 = m2 * m2;', | |
'vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3));', | |
'// Determine noise gradient', | |
'vec4 temp = m2 * m * pdotx;', | |
'gradient = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3);', | |
'gradient += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3;', | |
'gradient *= 105.0;', | |
'return 105.0 * dot(m4, pdotx);', | |
'}', | |
' uniform float uTime;', | |
' float displace(vec3 point) {', | |
' float noise = snoise(vec3(.1 * point.x + 0.5 * uTime, 0.1 * point.y + 131. + 0.5 * uTime, .7 * point.z + 0.5 * uTime), vec3(uTime));', | |
' return noise;', | |
' }', | |
'void main() {' | |
].join('\n') | |
); | |
shader.fragmentShader = shader.fragmentShader.replace( | |
'vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;', | |
[ | |
'#include <normal_fragment_maps>', | |
'vec3 displacedPosition = vViewPosition + normalize(normal) * displace(vViewPosition);', | |
'vec3 displacedNormal = normalize(normal);', | |
'float offset = (2. / 512.);', | |
'vec3 tangent = orthogonal(normal);', | |
'vec3 bitangent = normalize(cross(normal, tangent));', | |
'vec3 neighbour1 = vViewPosition + tangent * offset;', | |
'vec3 neighbour2 = vViewPosition + bitangent * offset;', | |
'vec3 displacedNeighbour1 = neighbour1 + normal * displace(neighbour1);', | |
'vec3 displacedNeighbour2 = neighbour2 + normal * displace(neighbour2);', | |
'vec3 displacedTangent = displacedNeighbour1 - displacedPosition;', | |
'vec3 displacedBitangent = displacedNeighbour2 - displacedPosition;', | |
'displacedNormal = normalize(cross(displacedTangent, displacedBitangent));', | |
'vec2 uv = vec2( dot( x, displacedNormal ), dot( y, displacedNormal ) ) * 0.495 + 0.5;' | |
].join('\n') | |
); | |
shader.fragmentShader = shader.fragmentShader.replace( | |
'gl_FragColor = vec4( outgoingLight, diffuseColor.a );', | |
[ | |
'vec3 color = 1.0 * vec3(outgoingLight) + vec3(.1);', | |
'gl_FragColor = vec4( color, diffuseColor.a );' | |
].join('\n') | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment