Make GLTF model reflective?

I’ve incorporated the robot from the webgl_animation_skinning_morph.html example into my ThreeJS world. I would like to make it reflective like the cirucular mirror surface I added, which you can see embedded in the floor behind the robot;


:
Are there some properties I can set or some other trick I can do to make the robot’s textures partially reflective? By partially I mean I want to see the worlds reflections in the robots textures, but at a lower opacity than a true mirror texture, like the way a recently waxed car reflects things.

Is this possible? Or am I stuck having to find a GLTF artist and paying them to modify the original GLTF model, assuming this is possible at all?

I did in the past have a GLTF model with reflecting textures in a different ThreeJS scene I created. But the GLTF model required that an HDRI image to be loaded to see any reflections. If I loaded that GLTF model into a world without and HDRI image, there were no reflections at all I don’t want to add an HDRI image to my new world so that is not an option. I’m hoping I can do this with my current world configuration.

What is the “circular mirror surface” you added, above? That’s not just a three.js material on a cylinder, I assume?

glTF models load with THREE.MeshStandardMaterial under most circumstances. This is a realtime PBR material, and increasing material.metalness and decreasing material.roughness will result in a material that reflects incoming light. In the most cases, an environment map (loaded from an HDRI image) is used to provide the light that is reflected.

There are some other options, though. You can generate the environment map without an external HDRI image, by placing a THREE.CubeCamera in your scene at the location of the character, rendering a cubemap, and applying that cubemap as the character’s environment map. There are also post-processing options like screen-space reflections. Both techniques are more expensive than a static environment map.

1 Like

Hi Don,

You can generate the environment map without an external HDRI image, by placing a THREE.CubeCamera in your scene at the location of the character, rendering a cubemap, and applying that cubemap as the character’s environment map. There are also post-processing options like screen-space reflections. Both techniques are more expensive than a static environment map.

Do you have links to any samples that show how to do this? Also, by “expensive”, do you mean memory, CPU/GPU speed, or both? And do you mean “expensive” as in it will slow my world down so much I probably won’t keep it if I tried it? Or just a little extra load time and a slight bump in CPU/GPU usage at run-time? Better asked, will it tick off the user who visits my world because performance or resource consumption will be so heavy?

Here is the code that makes the mirror:

function addCircularMirror(position3D, rotation3D,  theRadius=20, numSegments=128, theColor=0x777777) {
    let geometry, material;

    geometry = new THREE.CircleGeometry( theRadius, numSegments );
    theGroundMirror = new THREE.Reflector( geometry, {
        clipBias: 0.003,
        textureWidth: window.innerWidth * window.devicePixelRatio,
        textureHeight: window.innerHeight * window.devicePixelRatio,
        color: theColor
    } );

    theGroundMirror.position.x = position3D.x;
    theGroundMirror.position.y = position3D.y;
    theGroundMirror.position.z = position3D.z;
    theGroundMirror.rotateX( rotation3D.x );
    theGroundMirror.rotateY( rotation3D.y );
    theGroundMirror.rotateZ( rotation3D.z );

    g_ThreeJsScene.add( theGroundMirror );
}

It all depends. On resolution, the number of environment maps you’re generating, whether you need those environment maps to reflect moving objects, etc. You don’t have to update the environment maps on every frame necessarily, especially if you don’t plan to reflect moving objects. If you are trying to track environment maps for dozens or hundreds of objects it will cost much more. The resolution of the environment map is configurable, lowres maps are quite cheap and highres maps are more expensive.

There’s an example in the documentation:

THREE.CubeCamera documentation

Ideally you would probably run that output through THREE.PMREMGenerator as well, but I don’t know of an example for this part.

1 Like

Thanks. Does an HDRI have to be “visible” to provide the reflective elements? I’m wondering if there is some way I can incorporate an HDRI image into my current world, but without it occluding any of the objects/lighting in my current world (so in essence it is invisible to the user), yet still provide reflective elements for the PBR textures. If that’s a stupid question just ignore it please.

envmap is probably not what you want, at least it would not look realistic. realism is when you see the two screens shining onto the robots shoulders and some green coming off from the bottom.

the library that does that: GitHub - 0beqz/screen-space-reflections: Implements Screen Space Reflections in three.js

some results so you get an idea (don’t worry the lib above is vanilla):

btw a cubecamera can work, too. and if you don’t render it all the time but once so the texture is static it won’t have a performance impact. having used this often in the past imo it won’t often look right and the reflections won’t be accurate.

1 Like

Thanks. Does an HDRI have to be “visible” to provide the reflective elements?

It does not need to be visible. If you set material.envMap or scene.environment the HDRI will be used for reflections. Unless you also provide an image for scene.background, the HDRI will not be visible in the scene except for as a source of light and reflections.

envmap is probably not what you want, at least it would not look realistic…

I don’t know if I’d choose SSR to show reflections on a complex character. This seems like a pretty good fit for an environment map generated by a CubeCamera. It’s a common technique — see reflection probes in Unity and reflection cubemaps in Blender. You can scale this up to have lots of small CubeCameras in the scene.

SSR works great for reflections off horizontal surfaces, because most of what’s reflected is inherently on the screen, in front of the camera. But reflections from a complex character don’t work like that, and the cubecamera is more flexible in what can reflect, and integrates with the PBR properties of the material better. SSR does not scale down (in terms of performance) on mobile devices as well either.

1 Like

this one i think does scale, it excludes most of the screen. i’ve ran it now on really old mobile phones i had around and it’s surprisingly fast. a cubemap on the other hand isn’t really ideal either, doesn’t it render the scene 6 times per frame? but either way, i agree, in the end its about cutting corners and using what’s best. i’d have used cubemap env as well until recently, though i probably would choose ssr now in more and more cases.