Ready Player Me Avatar texture/lightning rendering in ThreeJS and Matterport - three.js

I try to import a Ready Player Me GLB avatar into a Matterport scene (in ThreeJS).
It works but the avatar is very flat (left picture) compared to the rendering into RPM (right picture) or basic GLTF Viewer. I don't understand what I missed ? Pseudo code :
const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('https://api.readyplayer.me/v1/avatars/63580183b445da7aa57b9ce3.glb',
(gltf) => {
this.mesh = gltf.scene;
const light = new THREE.AmbientLight( 0xFFFFFF, 1 );
light.castShadow = true
this.mesh.add( light );
...
}, undefined);
On the WebGL part I have access to Matterport renderer :
(renderer, THREE, effectComposer) => {
renderer.outputEncoding = THREE.sRGBEncoding
renderer.toneMapping = THREE.ACESFilmicToneMapping
}
Is it related to Antialias ? Or a paramter or lighting that flatten hair and hands ? Or is it related to texture ?
Thanks !
EDIT 11/12/2022:
Thanks to #Mugen87, I find how to use the EquirectangularShader from GLTFLoader sample. This code works with Matterport context.
let pmremGenerator = new THREE.PMREMGenerator( this.context.renderer );
pmremGenerator.compileEquirectangularShader();
let envMap = pmremGenerator.fromScene( new THREE.RoomEnvironment() ).texture;
this.context.scene.environment = envMap;

Instead of using a single instance of AmbientLight, apply a more advanced type of environmental lighting to your scene. Especially if you already enabled tone mapping, consider to use a HDR environment map. The basic GLTFLoader example of three.js is a good code template. The most important part is:
new RGBELoader()
.load( 'textures/equirectangular/royal_esplanade_1k.hdr', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = texture;
// more scene setup
} );
Applying an environment map to Scene.environment ensures all PBR materials in the scene are going to use it.

Related

THREEJS - GLB Import & Mapping Image Texture

I'm trying to map an Image onto my GLB import, however the GLB is just showing up as black. Not really sure where I'm going wrong here.
let textureLoader= new THREE.TextureLoader();
let texture = textureLoader.load("images/pexels-luis-quintero-2471234.jpeg");
texture.flipY = true;
gltfLoader.load( file.path, (gltf) => {
gltf.scene.traverse( (child, key) => {
if(child.isMesh){
child.material = new THREE.MeshBasicMaterial();
let material = new THREE.SpriteMaterial( { map: texture } );
let sprite = new THREE.Sprite( material );
child.material.map = sprite;
}
});
** Added the texture to :-
child.material.map = texture
However the image does not fit to the dimensions of the GLB
An instance of THREE.Sprite is a 3D object similar to THREE.Mesh. You can't assign a sprite to the map property of a material. Do this:
child.material = new THREE.MeshBasicMaterial();
child.material.map = texture;
Besides, if you add a manually loaded color texture to a glTF asset, make sure to add:
texture.encoding = THREE.sRGBEncoding;

Scene-wide envmap for HDR lighting in three.js

I want to try and use an HDR image for my lighting.
I have tried doing
var envmap = new THREE.TextureLoader().load( "./assets/wooden_lounge_1k.hdr" );
scene.environment = envmap;
but all the objects in my scene are black in color.
I have seen some demos but they usually set the envmap property in the material for a single object, but I want to have the HDR lighting to be applied on all objects in the scene.
How would I do this?
thanks!
I found a JSFIDDLE website that had some code that would help me. It used the RGBELoader, but it had some extra stuff.
What I did:
function setLighting(){
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'https://threejs.org/examples/textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
var envMap = pmremGenerator.fromEquirectangular( texture ).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
})
var pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
}
var envmap = new THREE.TextureLoader().load( "./assets/wooden_lounge_1k.hdr" );
You have to load HDR textures with THREE.RGBELoader (and not with THREE.TextureLoader). I suggest you study the following official example for more information:
https://threejs.org/examples/webgl_loader_texture_hdr
Enter THREE.RGBELoader
Instead of THREE.TextureLoader
I think you should paste this:
var envmap = new THREE.RGBELoader().load( "./assets/wooden_lounge_1k.hdr" );
scene.environment = envmap;
I hope it works

THREE.JS : Change material color behind PNG texture ? Assign 2 materials to a mesh imported from GLTF model?

I am trying to change the color of my 3D model "behind" the png texture I set (which includes transparency).
I have done a lot of researches, and i finally found an example with a cube which actually works, but I can't understand how to make that with my gltf 3D model (not a BoxGeometry).
METHOD :
Define an array of two materials,
first one is my png texture with transparency = true;
second one is a basic material with its plain color (the color i will be able to change later...)
var materialBack = new THREE.MeshBasicMaterial({color: 0xfadce6});
var materialTxt = new THREE.MeshBasicMaterial({map: mytexture,transparent: true});
var materials = [materialBack, materialTxt];
It works perfect with a cube :
var geometry = new THREE.BoxBufferGeometry();
geometry.clearGroups();
geometry.addGroup( 0, Infinity, 0 );
geometry.addGroup( 0, Infinity, 1 );
var cube = new THREE.Mesh( geometry, materials );
Problem : I can't figure out how to do the same when my model is actually an imported GLTF, and not a "BoxBufferGeometry". It looks like we can't assign an array to o.material :
var loader = new THREE.GLTFLoader();
loader.load(mymodel.glb, function(gltf) {
gltf.scene.traverse((o) => {
if (o.isMesh) {
o.material = materials;
}
scene.add(gltf.scene);
});
I also tried to extract geometry from gltf, then create a new mesh, but without success :
var loader = new THREE.GLTFLoader();
loader.load(mymodel.glb, function(gltf) {
var geometry = gltf.scene.getObjectByName("name").geometry;
mymesh = new THREE.Mesh(geometry,materials);
scene.add(mymesh);
});
Can someone please help ?

Three.js : Gltf object adding material to look better

I'm actually trying to add some materials to my Gltf objects in three js r113, but I don't know how to use correctly material parameters and the light as I see my object in three js viewer. This is What I get in Firefox
and this is what I'm dreaming about
.
I guess this is the value I need to apply to my code
This is how I add my gltf and how I try to add materials :
// Load a glTF resource of FENCE
gltfLoader.load( 'Fence.gltf', function ( gltf ) {
fenceModel = gltf.scene;
// fenceModel.traverse(function (child) {
// if (child.isMesh) {
// child.material = new THREE.MeshLambertMaterial({
// color: 0xc07341, //light Brown
// reflectivity: 0,
// dithering: true
// });
// }
// });
});
var ambientlight = new THREE.AmbientLight(0xffffff, 0.5 );
scene.add( ambientlight );
Actually my floor is only a gltf file with no materials.
Maybe I need to add some shadow porperties to my floor and then I could see the fence shadow ?
I need some help to understand how to do a better light effect on object.
Thank you, sorry for my english I'm using translator to help me.
Ps: My gltf object contain texture in it.

ThreeJs add Texture to a GLTF object surface

I am trying to apply an image dynamically on a gltf loaded mesh.
The code to load the model looks like:
const gltfLoader = new GLTFLoader();
const url = 'resources/models/mesh.gltf';
gltfLoader.load(url, (gltf) => {
const root = gltf.scene;
scene.add(root);
})
When looking from top the element looks like a rounded rect:
When inspecting the imported mesh I can see that the BufferGeometry has a count of 18.000 points:
Everything works fine however if I apply the texture like this:
const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
root.children[0].material = material;
The image is not visible but the mesh is now colored in 1 color.
Is it possible to apply the image just on the top face of the rect?
Hard to tell what the problem is without seeing the resulting image. However, I would just assign a new texture like this: root.children[0].material.map = texture instead of creating a whole new material, since you don't want to lose all the material attributes that came in the GLTF.
Additionally, MeshBasicMaterial always looks flat because it is not affected by lights.

Resources