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;
Related
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.
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 ?
I've got a textured model in three.js and I want to be able to swap out the texture defined in the .gltf file when the page loads. I've looked here for inspiration.
"images": [
{
"uri": "flat_baseColor.png"
},
// etc
So to update the texture I do
var images = [
"./textures/01.jpg",
// "./textures/01.jpg",
];
var texture = new THREE.TextureLoader().load( images[0] );
var my_material = new THREE.MeshBasicMaterial({map: texture});
// load the model
var loader = new GLTFLoader().setPath( 'models/gltf/' ); // trex
loader.load( 'creature_posed.gltf', function ( gltf )
{
gltf.scene.traverse( function ( child )
{
if ( child.isMesh )
{
// The textures go for a double flip, I have no idea why
// Texture compensation
texture.flipX = false;
texture.flipY = false;
child.material = my_material;
texture.needsUpdate = true;
}
} );
var model = gltf.scene;
Only the texture is considerably pale. :(
I've tested it against itself, so it's not the texture). What have a missed out?
When loading textures you'll need to pay attention to colorspace: if the texture has color data (like .map or .emissiveMap) it's probably sRGB.
texture.encoding = THREE.sRGBEncoding;
See GLTFLoader docs and color management in three.js. This assumes that renderer.outputEncoding = THREE.sRGBEncoding as well.
three.js r113
I am trying to apply a texture to my 3D model with Three JS.
I tried a lot of ways from the Three JS Examples but for any reasons nothing is working.
Here is how I apply the texture to my model:
//LOADING TEXTURE
var textureLoader = new THREE.TextureLoader();
var diffuse = textureLoader.load( "models/Carbon.png" );
diffuse.encoding = THREE.sRGBEncoding;
diffuse.wrapS = THREE.RepeatWrapping;
diffuse.wrapT = THREE.RepeatWrapping;
diffuse.repeat.x = 1;
diffuse.repeat.y = 1;
var normalMap = textureLoader.load( "models/Carbon_Normal.png" );
normalMap.wrapS = THREE.RepeatWrapping;
normalMap.wrapT = THREE.RepeatWrapping;
var material = new THREE.MeshPhysicalMaterial({
roughness: 0.5,
clearcoat: 1.0,
clearcoatRoughness: 0.1,
map: diffuse,
normalMap: normalMap
});
// LOADING MODEL
var loader = new THREE.GLTFLoader();
loader.load("models/stairs.gltf", function(gltf){
model = gltf.scene
model.traverse((newModel) => {
if (newModel.isMesh){
newModel.material = material;
newModel.castShadow = true;
newModel.receiveShadow = true;
}
});
scene.add(model);
});
I appreciate any help!
When loading a texture for a glTF model, you have to set Texture.flipY to false to satisfy the uv convention of glTF.
diffuse.flipY = false;
normalMap.flipY = false;
Besides, you always have to ensure that your model has texture coordinates. You can do this by checking if the geometries of your meshes have an uv attribute. If this attribute is missing, I suggest you generate texture coordinates in a DCC tool like Blender.
three.js R112
I am trying to recreate Sketchfab's "ambient environment" feature in threejs.
see sketchfab background settings
I want my model in threejs to show a traditional environment map (360 picture of a location), but I want the scene to show a blurred, ambient image as the environement.
I tried loading two cubetextures and applying one to the envMap of the model, and the other to the scene.background:
var loader = new THREE.TextureLoader();
loader.load( "../../image/download/img1.jpg", function ( texture ) {
texture.encoding = THREE.sRGBEncoding;
texture.anisotropy = maxAnisotropy;
var cubemapGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 512 } );
var cubeMapTexture = cubemapGenerator.update( renderer );
var pmremGenerator = new THREE.PMREMGenerator( cubeMapTexture );
pmremGenerator.update( renderer );
var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
pmremCubeUVPacker.update( renderer );
envMapCubeRenderTarget = pmremCubeUVPacker.CubeUVRenderTarget;
var envMap = envMapCubeRenderTarget ? envMapCubeRenderTarget.texture : null;
texture.dispose();
pmremGenerator.dispose();
pmremCubeUVPacker.dispose();
object.material.envMap = envMap
var loader2 = new THREE.TextureLoader();
loader2.load( "../../image/download/img2.jpg", function ( texture ) {
texture.encoding = THREE.sRGBEncoding;
texture.anisotropy = maxAnisotropy;
var cubemapGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 512 } );
envMapBackground = cubemapGenerator.renderTarget;
scene.background = envMapBackground; //old = texture
scene.background.anisotropy = maxAnisotropy;
});
});
When I try to use two cubemaps, my scene just renders a blank background...