I’m trying to make a scene contains 3 or 4 frosted disc glass,they can refraction each other in diffrent viewPosition.
At first I used MeshBasicMaterial,then in material.onBeforeCompile I added some blur & chromatic aberration effect.It looks like this
What I actually want to use is MeshPhysicsMaterial,I pasted the same code,then I noticed I need make a new uniform input for refractionMap(which generated by using WebGLCubeRenderTarget & CubeCamera). but things get weird,it only works for the 1st custom object in scene.reafraction texture in other objects appears to missing texture.it looks like the cubemap only loaded 3 or 4 faces,the others are missing.
the imgur gif link here,as u can see,some faces are missing,also when the viewposition changed to the specified position,the display of cubemap would become wrong.
can anyone tell me how to fix this? This twitter feed also illustrates the problem
the cubeMap&cubeRenderTarget’s code
cubeRenderTarget = new THREE.WebGLCubeRenderTarget( renderSize, {
generateMipmaps: true,
minFilter:THREE.NearestMipmapLinearFilter,
magFilter:THREE.NearestMipmapLinearFilter,
} );
cubeRenderTarget.texture.mapping = THREE.CubeRefractionMapping
the material’s code
refractMaterial = new THREE.MeshPhysicalMaterial({
transmission: options.transmission,
thickness: options.thickness,
roughness:options.roughness,
envMap: bgTexture,
envMapIntensity: options.envMapIntensity,
clearcoat: options.clearcoat,
clearcoatRoughness: options.clearcoatRoughness,
normalScale: new THREE.Vector2(options.normalScale),
normalMap: normalMapTexture,
clearcoatNormalMap: normalMapTexture,
clearcoatNormalScale: new THREE.Vector2(options.clearcoatNormalScale),
})
refractMaterial.onBeforeCompile = shader => {
shader.uniforms.refractionMap = { value: cubeRenderTarget.texture };
shader.uniforms.refractionFactor = { value: 0.985 };
shader.fragmentShader = prefixFrag + shader.fragmentShader;
shader.fragmentShader = shader.fragmentShader.replace(`#include <output_fragment>`,`
//#include <envmap_fragment>
vec3 cameraToFrag = normalize( vWorldPosition - cameraPosition );
vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
vec3 reflectVec = refract( cameraToFrag, worldNormal, refractionFactor ); //refractionRatio
//vec3 reflectVec = vReflect;
//vec4 envColor = textureCube( refractionMap, reflectVec,0. );
// modified by orig frag shader
float lodLvl = 0.0;
float flipEnvMap = 1.0;
vec3 dir = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
// iteration this in blur
vec4 envColor = textureLod( refractionMap, dir,lodLvl); //textureCube
// ## chromatic aberration
vec4 refractedColor = vec4( 1.0 );
refractedColor.r = textureLod( refractionMap, vec3( flipEnvMap * vRefract[0].x, vRefract[0].yz ), lodLvl ).r;
refractedColor.g = textureLod( refractionMap, vec3( flipEnvMap * vRefract[1].x, vRefract[1].yz ), lodLvl ).g;
refractedColor.b = textureLod( refractionMap, vec3( flipEnvMap * vRefract[2].x, vRefract[2].yz ), lodLvl ).b;
// ## blur para
float blurRadius = 0.015;
int SAMPLING_RATE = 16;
float bloomV = 1.;
float r = blurRadius;
vec3 vss = dir;
int maxS = SAMPLING_RATE;
vec3 c = envColor.rgb;
vec3 rv;
vec3 offset;
float w, tw = 0.0;
// ## chromatic aberration
vec3 d = refractedColor.rgb;
vec3 rw0,rw1,rw2;
float x0, tx0,x1,tx1,x2,tx2 = 0.0;
// implement
//.----------------
//| RANDOM SAMPLING - look up texture maxS^2 times in a radius r around v
for (int i=0; i<maxS*maxS; i++)
{
offset = randVec3(i) * r;
// ## blur
rv = vss + offset;
tw = length(rv); // account for sampling distance
c += textureLod(refractionMap, rv,lodLvl).rgb * tw;
w += tw*bloomV; // values less than 1 like 0.85 fake bloom of bright areas
// could be handy for specularity
// ## chromatic aberration
rw0 = vec3( flipEnvMap * vRefract[0].x, vRefract[0].yz ) + offset;
rw1 = vec3( flipEnvMap * vRefract[1].x, vRefract[1].yz ) + offset;
rw2 = vec3( flipEnvMap * vRefract[2].x, vRefract[2].yz ) + offset;
tx0 = length(rw0);
tx1 = length(rw1);
tx2 = length(rw2);
vec4 resetColor = vec4(1.);
resetColor.r = textureLod( refractionMap, rw0, lodLvl ).r;
resetColor.g = textureLod( refractionMap, rw1, lodLvl ).g;
resetColor.b = textureLod( refractionMap, rw2, lodLvl ).b;
d += resetColor.rgb * vec3(tx0,tx1,tx2);
x0 += tx0*bloomV;
x1 += tx1*bloomV;
x2 += tx2*bloomV;
}
envColor.rgb = c/(w+1.0);
// ## chromatic aberration
refractedColor.rgb = vec3(d.x/(x0+1.),d.y/(x1+1.),d.z/(x2+1.));
envColor = mix( refractedColor, envColor, clamp( vReflectionFactor, 0.0, 1.0 ) );
float specularStrength = 1.0;
float reflectivity = 0.95;
#ifdef ENVMAP_BLENDING_MULTIPLY
outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );
#elif defined( ENVMAP_BLENDING_MIX )
outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );
#elif defined( ENVMAP_BLENDING_ADD )
outgoingLight += envColor.xyz * specularStrength * reflectivity;
#endif
outgoingLight = mix( outgoingLight, envColor.xyz, 0.95 );
#ifdef OPAQUE
diffuseColor.a = 1.0;
#endif
#ifdef USE_TRANSMISSION
diffuseColor.a *= transmissionAlpha + 0.1;
#endif
gl_FragColor = vec4( outgoingLight, envColor.a ); //vec4( outgoingLight, diffuseColor.a );
`)
shader.vertexShader = prefixVert + shader.vertexShader;
shader.vertexShader = shader.vertexShader.replace(`#include <fog_vertex>`,`
vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );
vReflect = refract( cameraToVertex, worldNormal, refractionFactor ); //refractionRatio
float mRefractionRatio = 1.02;
float mFresnelBias = 0.1;
float mFresnelPower = 2.0;
float mFresnelScale = 1.0;
vRefract[0] = refract( normalize( cameraToVertex ), worldNormal, mRefractionRatio );
vRefract[1] = refract( normalize( cameraToVertex ), worldNormal, mRefractionRatio * 0.99 );
vRefract[2] = refract( normalize( cameraToVertex ), worldNormal, mRefractionRatio * 0.98 );
vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( cameraToVertex ), worldNormal ), mFresnelPower );
#include <fog_vertex>
`)
refractMaterial.userData.shader = shader;
here is what I do in render() function for two objects
refractSphere.visible = false;
cubeCamera.position.copy( camera.position );
cubeCamera.update( renderer, scene );
if ( refractSphere.material.userData.shader ) {
refractSphere.material.userData.shader.uniforms.refractionMap.value = cubeRenderTarget.texture;
}
refractSphere2.visible = false;
cubeCamera2.position.copy( camera.position );
cubeCamera2.update( renderer, scene );
if ( refractSphere2.material.userData.shader ) {
refractSphere2.material.userData.shader.uniforms.refractionMap.value = cubeRenderTarget2.texture;
}
refractSphere.visible = true;
refractSphere2.visible = true;


