EnvMap generated with CubeCamera looks magnified

Hi everyone,

I’m using the material property “refractionRatio” to refract some parts of a 3D model through other parts of the same that are transparent.

So far so good, but I see a problem, it gets too much magnified when it gets refracted.
How can I reduce the size of it?

Expected

Got so far

Here the code I’m using to make the mesh refract the model

// Create cube render target
  const cubeRenderTarget = new WebGLCubeRenderTarget(2048, {
    format: RGBFormat,
    generateMipmaps: true,
    minFilter: LinearMipmapLinearFilter
  });
  cubeRenderTarget.texture.mapping = CubeRefractionMapping;

  // Create cube camera
  const cubeCamera = new CubeCamera(1, 100, cubeRenderTarget);
  cubeCamera.position.copy(mesh.position);
  scene.add(cubeCamera);

  // Update texture material
  mesh.material.envMap = cubeRenderTarget.texture;
  mesh.material.refractionRatio = 1;
  mesh.material.needsUpdate = true;

I also update the cubeCamera on every render

cubeCamera.update(renderer, scene);

Note: I have tried with Phong and Physical materials.

Hope you can help me

Thanks!
Javier

either remove your refraction mapping or experiment with refractionRatio
image


also try THREE.FrontSide or THREE.BackSide
1 Like

hi @seanwasere,

Thanks for sharing the working example, I find it super useful to experiment with.

I tried removing the refraction ratio mapping, and this is how it looks. It looks pretty close, but it doesn’t have any refraction, just transparency.

Here I have turned on transparency and refraction just to see how off the refraction effect is.

refractionRation=0.9


refractionRatio=1

Might it be the problem the distance between the position of the cube camera and the target? I’m setting the camera position right in the center of the model.
I think the problem could be solved if there is a way to scale down the texture set as envMap, I tried with texture.repeat() without luck.

Here some screenshots showing how the example looks with different refraction ratio



Following your example, what I’d like to achieve is to get almost invisible balls, just a bit of refraction, like the latest screenshot but without magnifying the background.

Thanks for your help

Maybe that’s the clue, the camera position should be in the center of the lens, or at its focal point.
A working example with a gui that can change the position of the camera would be good to try.
Then you’d would also need a second cubecamera for the other lens.

Definitely improves the refraction alignment when moving the cube camera to one of the lenses position.

Here some screenshots, (the green box shows the cube camera position )

Screen Shot 2020-09-10 at 13.59.46

It still looks magnified, if I modify the refractionRatio it only changes the refraction angle but it doesn’t show a smaller refracted image.

I was very curious about this that I had to create my own
https://sbcode.net/extra_html/glasses.html
Anyway I have another idea I will try.

1 Like

Glad to see you could replicate the magnified texture.
Do you think is possible in some way to scale down the envMap texture? literally make the image smaller

Did you try to put the cubeCamera at the same position as the camera you use for rendering ? You can hide the glasses and glass frames from the cubeCamera with layers, to keep only the two stems in the resulting envmap. This way I suppose the glass material with refractionRatio will show a distorted image of the glasses stems from the point of view of the camera, which is what you want to achieve.

3 Likes

@felixmariotto that was the trick! It started to look accurate right after keeping in sync the cube camera position with the orbit camera.

Thanks for sharing the possible solution and recommend the use of layers, I’ll try to use them as an alternative to hide and show meshes on every cubeCamera.update call.

Here how it looks after making the cubeCamera follow the camera position.

In case somebody else runs into the same problem, here the final code.

// Create cube render target
  const cubeRenderTarget = new WebGLCubeRenderTarget(2048, {
    format: RGBFormat,
    generateMipmaps: true,
    minFilter: LinearMipmapLinearFilter
  });
  cubeRenderTarget.texture.mapping = CubeRefractionMapping;

  // Create cube camera
  const cubeCamera = new CubeCamera(1, 1000, cubeRenderTarget);
  cubeCamera.position.copy(camera.position);
  scene.add(cubeCamera);

  // Update texture material
  mesh.material.envMap = cubeRenderTarget.texture;
  mesh.material.refractionRatio = 0.98;
  mesh.material.needsUpdate = true;

I also update the cubeCamera on every render

cubeCamera.position.copy(camera.position);
// consider hide meshes that shouldn't be part of the refraction
cubeCamera.update(renderer, scene);
// restore meshes visibility 

Note: consider the use of layers to define which meshes should be visible as part of the refraction.
See @felixmariotto’s EnvMap generated with CubeCamera looks magnified comment

1 Like