рдЬрдм рдЖрдк рдПрдХ 3D рдСрдмреНрдЬреЗрдХреНрдЯ рд░реЗрдВрдбрд░ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╣рдореЗрд╢рд╛ рдЗрд╕рдореЗрдВ рдХреБрдЫ рд╕рд╛рдордЧреНрд░реА рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рддрд╛рдХрд┐ рдпрд╣ рджрд┐рдЦрд╛рдИ рджреЗ рдФрд░ рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдЖрдк рдЪрд╛рд╣рддреЗ рд╣реИрдВ; рдпрджрд┐ рдЖрдк рд╡рд┐рд╢реЗрд╖ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдореЗрдВ рдпрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ WebGL рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдРрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреЛрдИ рдмрд╛рдд рдирд╣реАрдВред
рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕рд╛рдордЧреНрд░рд┐рдпреЛрдВ рдХреЛ рддреАрди.js рдЬреИрд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЙрдкрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд┐рдореНрдпреБрд▓реЗрдЯреЗрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдКрдБрдЧрд╛ рдХрд┐ рддреАрди рдЪрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЧреНрд▓рд╛рд╕ рдХреА рддрд░рд╣ рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП - рдЖрдкрдиреЗ рдпрд╣ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдпрд╛ - рддреАрди.jsред
рдЪрд░рдг 1: рд╕реЗрдЯрдЕрдк рдФрд░ рд╕рд╛рдордиреЗ рдкреНрд░рддрд┐рдмрд┐рдВрдм
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореИрдВ рд╣реАрд░реЗ рдХреА рдЬреНрдпрд╛рдорд┐рддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдЖрдк рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдШрди рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдЖрдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдПрдХ рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝рд░, рдПрдХ рджреГрд╢реНрдп, рдПрдХ рдХреИрдорд░рд╛ рдФрд░ рдЬреНрдпрд╛рдорд┐рддрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдорд╛рд░реА рд╕рддрд╣ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рд╛рдордЧреНрд░реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдкрд╛рда рдХрд╛ рдореБрдЦреНрдп рдЙрджреНрджреЗрд╢реНрдп рд╣реЛрдЧрд╛ред рддреЛ, рдЪрд▓рд┐рдП рдПрдХ рдирдИ SharedMaterial рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╢реАрд░реНрд╖ рдФрд░ рдЦрдВрдб рд╢реЗрдб рдХреЗ рд╕рд╛рде рдмрдирд╛рддреЗ рд╣реИрдВред
рдЖрдкрдХреА рдЕрдкреЗрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╡рд┐рдкрд░реАрдд, рд╣рдорд╛рд░реА рд╕рд╛рдордЧреНрд░реА рдкрд╛рд░рджрд░реНрд╢реА рдирд╣реАрдВ рд╣реЛрдЧреА, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдо рд╣реАрд░реЗ рдХреЗ рдкреАрдЫреЗ рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЗрд╕реЗ рд╡рд┐рдХреГрдд рдХрд░реЗрдВрдЧреЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдмрдирд╛рд╡рдЯ рдореЗрдВ рджреГрд╢реНрдп (рд╣реАрд░реЗ рдХреЗ рдмрд┐рдирд╛) рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдиреА рд╣реЛрдЧреАред рдореИрдВ рдПрдХ рд╡рд┐рдорд╛рди рдХреЛ рдПрдХ рдСрд░реНрдереЛрдЧреЛрдирд▓ рдХреИрдорд░реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреВрд░реЗ рджрд╛рдпрд░реЗ рдХрд╛ рдЖрдХрд╛рд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЖрдк рдЕрдиреНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рджреГрд╢реНрдп рднреА рдкреНрд░рд╕реНрддреБрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдереНрд░реА.рдЬреЗрдПрд╕ рдореЗрдВ рд╣реАрд░реЗ рдХреА рдкреГрд╖реНрдарднреВрдорд┐ рдХреА рд╕рддрд╣ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдкрд░рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред
this.orthoCamera = new THREE.OrthographicCamera( width / - 2,width / 2, height / 2, height / - 2, 1, 1000 ); // 1 (0 ) this.orthoCamera.layers.set(1); const tex = await loadTexture('texture.jpg'); this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(), new THREE.MeshBasicMaterial({map: tex})); this.quad.scale.set(width, height, 1); // 1 this.quad.layers.set(1); this.scene.add(this.quad);
рд╣рдорд╛рд░рд╛ рджреГрд╢реНрдп рдЪрдХреНрд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
this.envFBO = new THREE.WebGLRenderTarget(width, height); this.renderer.autoClear = false; render() { requestAnimationFrame( this.render ); this.renderer.clear(); // fbo this.renderer.setRenderTarget(this.envFbo); this.renderer.render( this.scene, this.orthoCamera ); // this.renderer.setRenderTarget(null); this.renderer.render( this.scene, this.orthoCamera ); this.renderer.clearDepth(); // this.renderer.render( this.scene, this.camera ); };
рдорд╣рд╛рди, рд╕рд┐рджреНрдзрд╛рдВрдд рдореЗрдВ рдереЛрдбрд╝рд╛ рднреНрд░рдордг рдХреЗ рд▓рд┐рдП рд╕рдордпред рдХрд╛рдВрдЪ рдЬреИрд╕реА рдкрд╛рд░рджрд░реНрд╢реА рд╕рд╛рдордЧреНрд░реА рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдкреНрд░рдХрд╛рд╢ рдХреЛ рдЕрдкрд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рдХрд╛рд╢ рд╣рд╡рд╛ рдХреЗ рдмрдЬрд╛рдп рдХрд╛рдВрдЪ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдзрд┐рдХ рдзреАрд░реЗ-рдзреАрд░реЗ рдЧреБрдЬрд░рддрд╛ рд╣реИ, рдФрд░ рдЬрдм рдкреНрд░рдХрд╛рд╢ рдХрд┐рд░рдг рдПрдХ рдХреЛрдг рдкрд░ рдРрд╕реА рд╡рд╕реНрддреБ рд╕реЗ рдЯрдХрд░рд╛рддреА рд╣реИ, рддреЛ рдЧрддрд┐ рдореЗрдВ рдЕрдВрддрд░ рдкреНрд░рдХрд╛рд╢ рдХреЛ рджрд┐рд╢рд╛ рдмрджрд▓рдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рджрд┐рд╢рд╛ рдореЗрдВ рдпрд╣ рдкрд░рд┐рд╡рд░реНрддрди рдЕрдкрд╡рд░реНрддрди рджреНрд╡рд╛рд░рд╛ рдЕрднрд┐рдкреНрд░реЗрдд рд╣реИред

рдХреЛрдб рдореЗрдВ рдЗрд╕реЗ рджреЛрд╣рд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЯрдХрдЯрдХреА рджрд┐рд╢рд╛ рд╡реЗрдХреНрдЯрд░ рдФрд░ рд╕рддрд╣ рдХреЗ рдмреАрдЪ рдХреЗ рдХреЛрдг рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдЬрд╛рдирдирд╛ рд╣реЛрдЧрд╛ред рдЖрдЗрдП рдЗрди рд╡реИрдХреНрдЯрд░реЛрдВ рдХреЛ рдЧрд┐рдирдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЯреЗрдХрд░ рд╢реЗрдб рдХреЛ рдмрджрд▓реЗрдВред
varying vec3 eyeVector; varying vec3 worldNormal; void main() { vec4 worldPosition = modelMatrix * vec4( position, 1.0); eyeVector = normalize(worldPos.xyz - cameraPosition); worldNormal = normalize( modelViewMatrix * vec4(normal, 0.0)).xyz; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }
рдЯреБрдХрдбрд╝реЗ рдЯреБрдХрдбрд╝реЗ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдореЗрдВ, рд╣рдо рдЕрдм eyeVector
рдФрд░ worldNormal
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ worldNormal
рдореЗрдВ worldNormal
рдореЗрдВ рдкрд╣рд▓реЗ рджреЛ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИрдВред рддреАрд╕рд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдкрд╡рд░реНрддрдХ рд╕реВрдЪрдХрд╛рдВрдХреЛрдВ рдХрд╛ рдЕрдиреБрдкрд╛рдд рд╣реИ, рдпрд╛рдиреА рд╣рдорд╛рд░реЗ рдШрдиреЗ рдорд╛рдзреНрдпрдо / рдЧреНрд▓рд╛рд╕ рдХрд╛ рдЕрдкрд╡рд░реНрддрдХ рд╕реВрдЪрдХрд╛рдВрдХ (IOR)ред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ 1.0 / 1.5 рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдЗрд╕ рдорд╛рди рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд╛рдиреА рдХрд╛ рдЕрдкрд╡рд░реНрддрдирд╛рдВрдХ 1.33 рд╣реИ, рдФрд░ рд╡рд╣ рд╣реАрд░рд╛ 2.42 рдХрд╛ рд╣реИред
uniform sampler2D envMap; uniform vec2 resolution; varying vec3 worldNormal; varying vec3 viewDirection; void main() { // get screen coordinates vec2 uv = gl_FragCoord.xy / resolution; vec3 normal = worldNormal; // calculate refraction and add to the screen coordinates vec3 refracted = refract(eyeVector, normal, 1.0/ior); uv += refracted.xy; // sample the background texture vec4 tex = texture2D(envMap, uv); vec4 output = tex; gl_FragColor = vec4(output.rgb, 1.0); }
https://codesandbox.io/embed/multi-side-refraction-step-13-pzxf9?fontsize=14&hidenavigation=1&theme=dark
рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛! рд╣рдордиреЗ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдПрдХ shader рд▓рд┐рдЦрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣реАрд░рд╛ рдореБрд╢реНрдХрд┐рд▓ рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИ ... рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдХреНрдпреЛрдВрдХрд┐ рд╣рдордиреЗ рдХрд╛рдВрдЪ рдХреА рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ред рд╕рднреА рдкреНрд░рдХрд╛рд╢ рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд╣реАрдВ рдЧреБрдЬрд░реЗрдВрдЧреЗ рдФрд░ рдЕрдкрд╡рд░реНрддрд┐рдд рд╣реЛрдВрдЧреЗ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рднрд╛рдЧ рдкрд░рд┐рд▓рдХреНрд╖рд┐рдд рд╣реЛрдЧрд╛ред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЗрд╕реЗ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рдП!
рдЪрд░рдг 2: рдкреНрд░рддрд┐рдмрд┐рдВрдм рдФрд░ рдлреНрд░реЗрд╕реНрдиреЗрд▓ рд╕рдореАрдХрд░рдг
рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдкрд╛рда рдореЗрдВ рд╣рдо рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХреЗ рд▓рд┐рдП рдЕрдкрд╡рд░реНрддрди рдХреА рдЧрдгрдирд╛ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдЕрдкрд╡рд░реНрддрдХ рдкреНрд░рдХрд╛рд╢ рдХреЗ рд▓рд┐рдП рд╕рдлреЗрдж рд░рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╣рдо рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ: рдЖрдк рдХреИрд╕реЗ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХрдм рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдХрд░рдирд╛ рд╣реИ, рдФрд░ рдХрдм рдЦрдВрдбрди рдХрд░рдирд╛ рд╣реИ? рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдпрд╣ рд╕рд╛рдордЧреНрд░реА рдХреЗ рдЕрдкрд╡рд░реНрддрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ: рдЬрдм рдШрдЯрдирд╛ рд╡реЗрдХреНрдЯрд░ рдФрд░ рд╕рддрд╣ рдХреЗ рдмреАрдЪ рдХрд╛ рдХреЛрдг рдереНрд░реЗрд╕рд╣реЛрд▓реНрдб рдорд╛рди рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдкреНрд░рдХрд╛рд╢ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рд╣реЛрдЧрд╛ред

рдЦрдВрдбрд┐рдд рдЫрд╛рдпрд╛ рдореЗрдВ, рд╣рдо рдкрд░рд╛рд╡рд░реНрддрд┐рдд рдФрд░ рдкрд░рд╛рд╡рд░реНрддрд┐рдд рдХрд┐рд░рдгреЛрдВ рдХреЗ рдмреАрдЪ рдХреЗ рдЕрдиреБрдкрд╛рдд рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлреНрд░реЗрд╕реНрдиреЗрд▓ рд╕рдореАрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, glsl рдореЗрдВ рдпрд╣ рд╕рдореАрдХрд░рдг рдирд╣реАрдВ рд╣реИ, рдЖрдк рдЗрд╕реЗ рдпрд╣рд╛рдБ рд╕реЗ рдХреЙрдкреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
float Fresnel(vec3 eyeVector, vec3 worldNormal) { return pow( 1.0 + dot( eyeVector, worldNormal), 3.0 ); }
рд╣рдо рдмрд╕ рдкрд░рд┐рдХрд▓рд┐рдд рд╕рдлреЗрдж рд░рдВрдЧ рдХреЗ рд╕рд╛рде рдЕрдкрд╡рд░реНрддрд┐рдд рдХрд┐рд░рдг рдХреА рдмрдирд╛рд╡рдЯ рдХреЗ рд░рдВрдЧ рдХрд╛ рдорд┐рд╢реНрд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕ рдЕрдиреБрдкрд╛рдд рдХреА рд╣рдо рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВред
uniform sampler2D envMap; uniform vec2 resolution; varying vec3 worldNormal; varying vec3 viewDirection; float Fresnel(vec3 eyeVector, vec3 worldNormal) { return pow( 1.0 + dot( eyeVector, worldNormal), 3.0 ); } void main() { // get screen coordinates vec2 uv = gl_FragCoord.xy / resolution; vec3 normal = worldNormal; // calculate refraction and add to the screen coordinates vec3 refracted = refract(eyeVector, normal, 1.0/ior); uv += refracted.xy; // sample the background texture vec4 tex = texture2D(envMap, uv); vec4 output = tex; // calculate the Fresnel ratio float f = Fresnel(eyeVector, normal); // mix the refraction color and reflection color output.rgb = mix(output.rgb, vec3(1.0), f); gl_FragColor = vec4(output.rgb, 1.0); }
https://codesandbox.io/embed/multi-side-refraction-step-23-3vdty?fontsize=14&hidenavigation=1&theme=dark
рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд▓рдЧ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдФрд░ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИ ... рдмрд┐рд▓реНрдХреБрд▓, рд╣рдо рдкрд╛рд░рджрд░реНрд╢реА рд╡рд╕реНрддреБ рдХреА рдкреАрда рдирд╣реАрдВ рджреЗрдЦрддреЗ рд╣реИрдВред рдЪрд▓реЛ рдЗрд╕реЗ рдареАрдХ рдХрд░реЛ!
рдЪрд░рдг 3: рдмрд╣реБрдкрдХреНрд╖реАрдп рдЕрдкрд╡рд░реНрддрди
рд╣рдо рдЬреЛ рдХреБрдЫ рдкрд╣рд▓реЗ рд╣реА рдЕрдкрд╡рд░реНрддрди рдФрд░ рдкреНрд░рддрд┐рдмрд┐рдВрдмреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рди рдЪреБрдХреЗ рд╣реИрдВ, рдЙрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП, рдпрд╣ рд╕рдордЭрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд╢ рдЗрд╕реЗ рдЫреЛрдбрд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХрдИ рдмрд╛рд░ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЗ рдЕрдВрджрд░ рдЖрдЧреЗ-рдкреАрдЫреЗ рдЪрд▓ рд╕рдХрддрд╛ рд╣реИред
рдПрдХ рднреМрддрд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рд╕рд╣реА рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╣рд░ рдХрд┐рд░рдг рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдХреЗ рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдРрд╕реА рдЧрдгрдирд╛ рдмрд╣реБрдд рднрд╛рд░реА рд╣реИред рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдореИрдВ рдЖрдкрдХреЛ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреИрд╕реЗ рдХрдо рд╕реЗ рдХрдо рд╣реАрд░реЗ рдХреЗ рдЫрд┐рдкреЗ рд╣реБрдП рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдиреНрдирд┐рдХрдЯрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рд╣рдореЗрдВ рдПрдХ рдЯреБрдХрдбрд╝реЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдирдЪрд┐рддреНрд░ рдФрд░ рд╕рд╛рдордиреЗ рдФрд░ рдкреАрдЫреЗ рдХреЗ рдЪреЗрд╣рд░реЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдЪреВрдВрдХрд┐ рд╣рдо рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рджреЛрдиреЛрдВ рдкрдХреНрд╖реЛрдВ рдХреА рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдкрд╣рд▓реЗ рд╣рдореЗрдВ рдкреАрдЫреЗ рдХреЗ рдХрд┐рдирд╛рд░реЛрдВ рдХреЛ рдмрдирд╛рд╡рдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдкрд╣рд▓реЗ рдЪрд░рдг рдореЗрдВ рдПрдХ рдирдпрд╛ ShaderMaterial
рдмрдирд╛рдПрдБ, рд▓реЗрдХрд┐рди рдЕрдм рд╣рдо gl_FragColor
рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдирдЪрд┐рддреНрд░ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВрдЧреЗред
varying vec3 worldNormal; void main() { gl_FragColor = vec4(worldNormal, 1.0); }
рдЕрдЧрд▓рд╛, рд╣рдо рд╡рд┐рдЬрд╝реБрдЕрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдЪрдХреНрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреАрдЫреЗ рдХреЗ рдЪреЗрд╣рд░реЗ рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
this.backfaceFbo = new THREE.WebGLRenderTarget(width, height); ... render() { requestAnimationFrame( this.render ); this.renderer.clear(); // render background to fbo this.renderer.setRenderTarget(this.envFbo); this.renderer.render( this.scene, this.orthoCamera ); // render diamond back faces to fbo this.mesh.material = this.backfaceMaterial; this.renderer.setRenderTarget(this.backfaceFbo); this.renderer.clearDepth(); this.renderer.render( this.scene, this.camera ); // render background to screen this.renderer.setRenderTarget(null); this.renderer.render( this.scene, this.orthoCamera ); this.renderer.clearDepth(); // render diamond with refraction material to screen this.mesh.material = this.refractionMaterial; this.renderer.render( this.scene, this.camera ); };
рдЕрдм рд╣рдо рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдорд╛рдирджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдмрдирд╛рд╡рдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
vec3 backfaceNormal = texture2D(backfaceMap, uv).rgb;
рдФрд░ рдЕрдВрдд рдореЗрдВ, рдЖрдЧреЗ рдФрд░ рдкреАрдЫреЗ рдХреЗ рдЪреЗрд╣рд░реЗ рдХреЗ рдорд╛рдирджрдВрдб рд╕рдВрдЧрдд рд╣реИрдВред
float a = 0.33; vec3 normal = worldNormal * (1.0 - a) - backfaceNormal * a;
рдЗрд╕ рд╕рдореАрдХрд░рдг рдореЗрдВ, рдПрдХ рдЕрджрд┐рд╢ рд░рд╛рд╢рд┐ рд╣реИ рдЬреЛ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЕрдиреБрдЧрд╛рдореА рдХрд┐рдирд╛рд░реЛрдВ рдХреЗ рдХрд┐рддрдиреЗ рдорд╛рдирджрдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред
https://codesandbox.io/embed/multi-side-refraction-step-33-ljnqj?fontsize=14&hidenavigation=1&theme=dark
рдпрд╣ рдирд┐рдХрд▓рд╛! рд╣реАрд░реЗ рдХреЗ рд╕рднреА рдкрдХреНрд╖ рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдФрд░ рдЕрдкрд╡рд░реНрддрди рдХреА рдорджрдж рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рд╣рдордиреЗ рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдЬреЛрдбрд╝рд╛ред
рдкреНрд░рддрд┐рдмрдВрдз
рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рд╣реА рд╕рдордЭрд╛рдпрд╛ рд╣реИ, рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд░реВрдк рд╕реЗ рдкрд╛рд░рджрд░реНрд╢реА рд╕рд╛рдордЧреНрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдмрд╣реБрдд рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдПрдХ рджреВрд╕рд░реЗ рдХреЗ рд╕рд╛рдордиреЗ рдХрдИ рдХрд╛рдВрдЪ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рдирд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдкреГрд╖реНрдарднреВрдорд┐ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рд╡рд╕реНрддреБрдУрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕реЗ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рдФрд░ рдЕрдВрдд рдореЗрдВ, рджреГрд╢реНрдпрддрд╛ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЬреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдореИрдВрдиреЗ рдпрд╣рд╛рдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдП рд╣реИрдВ рд╡реЗ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рд╕реНрдХреНрд░реАрди рдХреА рд╕реАрдорд╛рдУрдВ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдХреНрдпреЛрдВрдХрд┐ рдХрд┐рд░рдгреЗрдВ рдЙрди рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЙрд▓рдЯ рд╕рдХрддреА рд╣реИрдВ рдЬреЛ рд╡рд┐рдорд╛рди рдХреА рд╕реАрдорд╛рдУрдВ рд╕реЗ рдкрд░реЗ рдЬрд╛рддреА рд╣реИрдВ, рдФрд░ рд╣рдо рдЗрди рдорд╛рдорд▓реЛрдВ рдХреЛ рдПрдХ рдмрдирд╛рд╡рдЯ рдореЗрдВ рджреГрд╢реНрдп рдХреЗ рд╕рд╛рде рдкрдХрдбрд╝рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред
рдмреЗрд╢рдХ, рдЗрди рд╕реАрдорд╛рдУрдВ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдЬрд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдирдореЗрдВ рд╕реЗ рд╕рднреА рдорд╣рд╛рди WebGL рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реЛрдВрдЧреЗред
рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХрд╛ рдЖрдирдВрдж рд▓рд┐рдпрд╛ рд╣реИ рдФрд░ рдХреБрдЫ рдирдпрд╛ рд╕реАрдЦрд╛ рд╣реИред рдореБрдЭреЗ рдЖрд╢реНрдЪрд░реНрдп рд╣реИ рдХрд┐ рдЕрдм рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░реЗрдВрдЧреЗ! рдореБрдЭреЗ рдЯреНрд╡рд┐рдЯрд░ рдкрд░ рдмрддрд╛рдПрдВред рдФрд░ рдмреЗрдЭрд┐рдЭрдХ рдореБрдЭрд╕реЗ рд╣рд░ рдмрд╛рдд рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреВрдЫрддреЗ рд╣реИрдВ!