Three.js : Gltf object adding material to look better - three.js

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.

Related

Ready Player Me Avatar texture/lightning rendering in ThreeJS and Matterport

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.

glb mesh disappears on rotation threejs

I've dug around looking for a solve for this - but couldn't find the answer on here. I have a gltf/glb model loading into three js as such:
createScene: function() {
this.renderer = new Three.WebGLRenderer({
antialias: true,
alpha: true
});
let container = document.getElementById('container');
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setClearColor(new Three.Color('#fff'));
this.renderer.setClearAlpha( 0 );
//this.render.shadowMap.type = Three.PCFSoftShadowMap;
container.appendChild(this.renderer.domElement);
},
createCamera: function() {
this.camera = new Three.PerspectiveCamera(6, container.clientWidth/container.clientHeight, 1, 1000);
this.camera.position.set(0, 0, 40);
},
createShape: function() {
let me = this;
const loader = new GLTFLoader();
loader.load( 'model/fbf3.glb', function ( gltf ) {
me.bottle = gltf.scene
me.scene.add( gltf.scene );
gltf.scene.traverse(function(obj) { obj.frustumCulled = false; });
me.pivot = new Three.Group();
me.pivot.position.set( 0.0, 0.0, 0 );
me.bottle.add( me.pivot );
console.log(gltf.scene);
console.log(gltf.scene.children[1]);
//me.pivot.add( me.bottle );
me.animate();
}, undefined, function ( error ) {
console.error( error );
});
},
I found a post that said to loop through the scene and be sure to add frustumCulled to false - so that's added in ( and when I log the child, that objects frustumCulled is set to false ). In order to have a label on my object easy to map and also take on a different material/glossiness i've created another object in the group that is just slightly in front of my other object on the yaxis. When it is facing the camera, it works well - however, it is when the object rotates is where it disappears. Working:
Rotate enough, and gone:
Is there a setting in threejs that I need to add to be sure the render order is correct? Or is it something wrong with my object set up in Blender? Ideally I wouldn't have to UV wrap the whole bottle as one object and add the label to the bottle texture because I want the label to have less specularity ( that a word? ). Any help would be appreciated.
Solved - the tutorial is slightly old ( 2+years ) and now Blender ( the latest version 2.9+ ) has the Principled BSDF Shader baked in. Instead of using the glTF-Blender-Exporter-Master pbr appended shaders from the listed tutorial - I instead used the Principled BSDF Shader - linked my material to it's Base Color and linked that to the Material Output ( all in the node/now Shader Editor. No issues anymore.

three js: how to mix two scenes (one with bloom)

I have one Renderer object and two scene objects. One scene contains the objects that should not be processed by the unrealbloom post-processing pass and the other scene contains all “glowing” objects.
Now I thought I could do:
const THREED_Composer = new THREE.EffectComposer( THREED_Renderer );
const THREED_RenderPass = new THREE.RenderPass( THREED_Scene, THREED_Camera );
const THREED_RenderPassGlow = new THREE.RenderPass(
THREED_SceneGlow, THREED_Camera );
const THREED_BloomPass = new THREE.UnrealBloomPass(
new THREE.Vector2(window.innerWidth, window.innerHeight), 0.5, 0.5, 0.4);
//THREED_BloomPass.renderToScreen = false; ???
THREED_Composer.addPass( THREED_RenderPassGlow );
THREED_Composer.addPass( THREED_BloomPass );
THREED_Composer.addPass( THREED_RenderPass );
The intention was to first render the glowing objects and then render the non-glowing objects over them. I want the non-glowing objects to be able to obscure the glowing objects.
My animate function looks like this:
function animate()
{
if(GLOBAL_FocusLost)
return;
requestAnimationFrame(animate);
update();
THREED_Composer.render();
}
Ultimate goal:
I want to have glowing monolith in the midst of a room that can be obscured by all other objects.
I tried to read my way through the documentation but I think that I do not understand it enough.
Cheers. Any help is very much appreciated!

unable to apply three.js texture to JSON model imported from blender

I am trying to apply a texture to a simple 3-d cube model exported from Blender 2.78b (as a matter of fact, the default blender cube). I exported the model in the standard three.js JSON format. I realize that I should be able to apply a texture in Blender on top of the geometry, but I want to "style" the blender model in three.js at runtime. Thus I am only interested in using blender to provide the geometry for my mesh.
I have created a plunker illustrating the situation.
I load in a blender model as blenderGeom, and then apply a MeshBasicMaterial with map set to a brick texture (unfortunately, I have to load the texture as Base64, since plunker doesn't allow you to upload images). I then apply the exact same material/texture to a native three.js BoxGeometry nonBlenderCubeGeom:
function loadModel() {
console.log('now in loadModel');
var promise = new Promise( (resolve, reject) => {
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
'cube.json', (blenderGeom, materials) => {
console.log(`loadModel: now loading cube: geomery=${geometry}`);
let cubeMaterial = new THREE.MeshBasicMaterial({
color: 0xff8080,
wireframe: false,
map: brickTexture
})
nonBlenderCubeGeom = new THREE.BoxGeometry(50, 50, 50);
blenderCubeGeom = blenderGeom;
blenderCube = new THREE.Mesh(blenderGeom, cubeMaterial); //no work
blenderCube.position.x = -20;
nonBlenderCube = new THREE.Mesh(nonBlenderCubeGeom, cubeMaterial); //work
nonBlenderCube.position.x = 20;
blenderCube.scale.set(10, 10, 10);
scene.add(blenderCube);
scene.add(nonBlenderCube);
As you can see from running the plunker, only the native three.js object on the right is textured, and the blender model on the left is not:
Am I doing something wrong? Is it simply a restriction that you can only texture a model in Blender?
Three.js r84. Blender 2.78b. I'm assuming this on three.js side, but I'm opening it up to blender as well.
Many Thanks.

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

Resources