UNPKG

6.18 kBJavaScriptView Raw
1import * as THREE from 'three';
2import { shaderMaterial } from '../core/shaderMaterial.js';
3import { shaderStructs, shaderIntersectFunction, MeshBVHUniformStruct } from 'three-mesh-bvh';
4
5// Author: N8Programs
6const MeshRefractionMaterial = shaderMaterial({
7 envMap: null,
8 bounces: 3,
9 ior: 2.4,
10 correctMips: true,
11 aberrationStrength: 0.01,
12 fresnel: 0,
13 bvh: new MeshBVHUniformStruct(),
14 color: new THREE.Color('white'),
15 resolution: new THREE.Vector2()
16},
17/*glsl*/
18`
19 varying vec3 vWorldPosition;
20 varying vec3 vNormal;
21 varying mat4 projectionMatrixInv;
22 varying mat4 viewMatrixInv;
23 varying vec3 viewDirection;
24 varying mat4 vInstanceMatrix;
25
26 void main() {
27 vec4 transformedNormal = vec4(normal, 0.0);
28 vec4 transformedPosition = vec4(position, 1.0);
29 #ifdef USE_INSTANCING
30 vInstanceMatrix = instanceMatrix;
31 transformedNormal = instanceMatrix * transformedNormal;
32 transformedPosition = instanceMatrix * transformedPosition;
33 #else
34 vInstanceMatrix = mat4(1.0);
35 #endif
36
37 projectionMatrixInv = inverse(projectionMatrix);
38 viewMatrixInv = inverse(viewMatrix);
39
40 vWorldPosition = (modelMatrix * transformedPosition).xyz;
41 vNormal = (viewMatrixInv * vec4(normalMatrix * transformedNormal.xyz, 0.0)).xyz;
42 viewDirection = normalize(vWorldPosition - cameraPosition);
43 gl_Position = projectionMatrix * viewMatrix * modelMatrix * transformedPosition;
44 }`,
45/*glsl*/
46`
47 #define ENVMAP_TYPE_CUBE_UV
48 precision highp isampler2D;
49 precision highp usampler2D;
50 varying vec3 vWorldPosition;
51 varying vec3 vNormal;
52
53 #ifdef ENVMAP_TYPE_CUBEM
54 uniform samplerCube envMap;
55 #else
56 uniform sampler2D envMap;
57 #endif
58
59 uniform float bounces;
60 ${shaderStructs}
61 ${shaderIntersectFunction}
62 uniform BVH bvh;
63 uniform float ior;
64 uniform vec3 color;
65 uniform bool correctMips;
66 uniform vec2 resolution;
67 uniform float fresnel;
68 uniform mat4 modelMatrix;
69
70 uniform float aberrationStrength;
71 varying mat4 projectionMatrixInv;
72 varying mat4 viewMatrixInv;
73 varying vec3 viewDirection;
74 varying mat4 vInstanceMatrix;
75
76 float fresnelFunc(vec3 viewDirection, vec3 worldNormal) {
77 return pow( 1.0 + dot( viewDirection, worldNormal), 10.0 );
78 }
79
80 vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 normal, float ior, mat4 modelMatrixInverse) {
81 vec3 rayOrigin = ro;
82 vec3 rayDirection = rd;
83 rayDirection = refract(rayDirection, normal, 1.0 / ior);
84 rayOrigin = vWorldPosition + rayDirection * 0.001;
85 rayOrigin = (modelMatrixInverse * vec4(rayOrigin, 1.0)).xyz;
86 rayDirection = normalize((modelMatrixInverse * vec4(rayDirection, 0.0)).xyz);
87 for(float i = 0.0; i < bounces; i++) {
88 uvec4 faceIndices = uvec4( 0u );
89 vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
90 vec3 barycoord = vec3( 0.0 );
91 float side = 1.0;
92 float dist = 0.0;
93 bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
94 vec3 hitPos = rayOrigin + rayDirection * max(dist - 0.001, 0.0);
95 vec3 tempDir = refract(rayDirection, faceNormal, ior);
96 if (length(tempDir) != 0.0) {
97 rayDirection = tempDir;
98 break;
99 }
100 rayDirection = reflect(rayDirection, faceNormal);
101 rayOrigin = hitPos + rayDirection * 0.01;
102 }
103 rayDirection = normalize((modelMatrix * vec4(rayDirection, 0.0)).xyz);
104 return rayDirection;
105 }
106
107 #include <common>
108 #include <cube_uv_reflection_fragment>
109
110 #ifdef ENVMAP_TYPE_CUBEM
111 vec4 textureGradient(samplerCube envMap, vec3 rayDirection, vec3 directionCamPerfect) {
112 return textureGrad(envMap, rayDirection, dFdx(correctMips ? directionCamPerfect: rayDirection), dFdy(correctMips ? directionCamPerfect: rayDirection));
113 }
114 #else
115 vec4 textureGradient(sampler2D envMap, vec3 rayDirection, vec3 directionCamPerfect) {
116 vec2 uvv = equirectUv( rayDirection );
117 vec2 smoothUv = equirectUv( directionCamPerfect );
118 return textureGrad(envMap, uvv, dFdx(correctMips ? smoothUv : uvv), dFdy(correctMips ? smoothUv : uvv));
119 }
120 #endif
121
122 void main() {
123 mat4 modelMatrixInverse = inverse(modelMatrix * vInstanceMatrix);
124 vec2 uv = gl_FragCoord.xy / resolution;
125 vec3 directionCamPerfect = (projectionMatrixInv * vec4(uv * 2.0 - 1.0, 0.0, 1.0)).xyz;
126 directionCamPerfect = (viewMatrixInv * vec4(directionCamPerfect, 0.0)).xyz;
127 directionCamPerfect = normalize(directionCamPerfect);
128 vec3 normal = vNormal;
129 vec3 rayOrigin = cameraPosition;
130 vec3 rayDirection = normalize(vWorldPosition - cameraPosition);
131 vec3 finalColor;
132 #ifdef CHROMATIC_ABERRATIONS
133 vec3 rayDirectionG = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), modelMatrixInverse);
134 #ifdef FAST_CHROMA
135 vec3 rayDirectionR = normalize(rayDirectionG + 1.0 * vec3(aberrationStrength / 2.0));
136 vec3 rayDirectionB = normalize(rayDirectionG - 1.0 * vec3(aberrationStrength / 2.0));
137 #else
138 vec3 rayDirectionR = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 - aberrationStrength), 1.0), modelMatrixInverse);
139 vec3 rayDirectionB = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior * (1.0 + aberrationStrength), 1.0), modelMatrixInverse);
140 #endif
141 float finalColorR = textureGradient(envMap, rayDirectionR, directionCamPerfect).r;
142 float finalColorG = textureGradient(envMap, rayDirectionG, directionCamPerfect).g;
143 float finalColorB = textureGradient(envMap, rayDirectionB, directionCamPerfect).b;
144 finalColor = vec3(finalColorR, finalColorG, finalColorB) * color;
145 #else
146 rayDirection = totalInternalReflection(rayOrigin, rayDirection, normal, max(ior, 1.0), modelMatrixInverse);
147 finalColor = textureGradient(envMap, rayDirection, directionCamPerfect).rgb;
148 finalColor *= color;
149 #endif
150 float nFresnel = fresnelFunc(viewDirection, normal) * fresnel;
151 gl_FragColor = vec4(mix(finalColor, vec3(1.0), nFresnel), 1.0);
152 #include <tonemapping_fragment>
153 #include <encodings_fragment>
154 }`);
155
156export { MeshRefractionMaterial };