I am trying to get this to work with Threejs but I am getting no texture reflection.
This is what I got so far.
import * as THREE from 'three'
class MeshRefractionMaterial extends THREE.MeshPhysicalMaterial {
uniforms: any;
constructor(args: any) {
super(args)
this.uniforms = {
...{
clearcoat: {value: 0.1, min: 0.1, max: 1},
clearcoatRoughness: {value: 0, min: 0, max: 1},
uRefractPower: {value: 0.3},
uRefractNormal: {value: 0.85},
uSceneTex: {value: null},
uTransparent: {value: 0.5},
uNoise: {value: 0.03},
uColor: {value: new THREE.Color('black')},
uSat: {value: 0.0},
uIntensity: {value: 1.0},
winResolution: {value: new THREE.Vector2(1024, 1024)},
roughness: {value: 0.0},
transmission: {value: 1.0},
thickness: {value: 3.0},
},
...{
...args
}
};
this.onBeforeCompile = (shader) => {
shader.uniforms = {
...shader.uniforms,
...this.uniforms
}
shader.fragmentShader = shader.fragmentShader.replace(
'outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;',
''
)
shader.fragmentShader =
`uniform float uTransparent;
uniform vec2 winResolution;
uniform float uRefractPower;
uniform float uRefractNormal;
uniform float uNoise;
uniform float uSat;
uniform float uIntensity;
uniform vec3 uColor;
uniform sampler2D uSceneTex;
float random(vec2 p) {
return fract(sin(dot(p.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
vec3 sat(vec3 rgb, float adjustment) {
const vec3 W = vec3(0.2125, 0.7154, 0.0721);
vec3 intensity = vec3(dot(rgb, W));
return mix(intensity, rgb, adjustment);
}
` + shader.fragmentShader
shader.fragmentShader = shader.fragmentShader.replace(
'#include <output_fragment>',
`vec2 uv = gl_FragCoord.xy / winResolution.xy;
vec2 refractNormal = vNormal.xy * (vNormal.z * uRefractNormal);
vec3 refractCol = vec3( 0.0 );
float slide;
vec2 refractUvR;
vec2 refractUvG;
vec2 refractUvB;
#pragma unroll_loop_start
for ( int i = 0; i < 16; i ++ ) {
slide = float(UNROLLED_LOOP_INDEX) / float(16) * 0.1 + random(uv) * uNoise;
refractUvR = uv - refractNormal * ( uRefractPower + slide * 1.0 ) * uTransparent;
refractUvG = uv - refractNormal * ( uRefractPower + slide * 2.0 ) * uTransparent;
refractUvB = uv - refractNormal * ( uRefractPower + slide * 3.0 ) * uTransparent;
refractCol.r += texture2D( uSceneTex, refractUvR ).r;
refractCol.g += texture2D( uSceneTex, refractUvG ).g;
refractCol.b += texture2D( uSceneTex, refractUvB ).b;
refractCol = sat(refractCol, uSat);
}
#pragma unroll_loop_end
refractCol /= float( 16 );
outgoingLight = mix(outgoingLight * refractCol * uIntensity, uColor, 0.25) * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;
#include <output_fragment>`
)
}
Object.keys(this.uniforms).forEach((name) => {
return Object.defineProperty(this, name, {
get: () => this.uniforms[name].value,
set: (v) => (this.uniforms[name].value = v)
})
}
)
}
}
export {MeshRefractionMaterial};
The Material:
const mat = new MeshRefractionMaterial({
uSceneTex: {value: this.envmap},
});
Envmap:
let pmrem = new PMREMGenerator(this.renderer);
pmrem.compileEquirectangularShader();
let envmapTexture = await new RGBELoader().loadAsync("assets/test.hdr");
let rt = pmrem.fromEquirectangular(envmapTexture);
this.envmap = rt.texture;