Three JS - GLTF model is dark - three.js

I have succeeded to load my model into ThreeJS using GLTFLoader but my model is dark. I tried uploading it to glTF Viewer and BabylonJS and it works perfectly there. Here is my javascript code:
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 )
const controls = new THREE.OrbitControls( camera )
const light = new THREE.AmbientLight( 0x404040 ); // soft white light
const renderer = new THREE.WebGLRenderer()
renderer.setSize( window.innerWidth, window.innerHeight )
renderer.setClearColor( 0xffffff )
document.body.appendChild( renderer.domElement )
// Instantiate a loader
const loader = new THREE.GLTFLoader();
// Load a glTF resource
loader.load(
// resource URL
'untitled2.gltf',
// called when the resource is loaded
function ( gltf ) {
scene.add( gltf.scene )
gltf.animations // Array<THREE.AnimationClip>
gltf.scene // THREE.Scene
gltf.scenes // Array<THREE.Scene>
gltf.cameras // Array<THREE.Camera>
gltf.asset // Object
}
// loading and error function
)
camera.position.y = 1
camera.position.z = 2
// Vertical
controls.minPolarAngle = 1; // radians
controls.maxPolarAngle = 1; // radians
//Horizontal
controls.minAzimuthAngle = - Infinity; // radians
controls.maxAzimuthAngle = Infinity; // radians
scene.add( light );
const animate = function () {
requestAnimationFrame( animate )
renderer.render( scene, camera )
}
animate()
I tried adding ambient lighting because according to the documentation it is supposed to act as global illumination and changing the background color.
Here is when I upload the model to babylonJS:
Here is when I upload the model to glTF viewer:
And here is when I load it to ThreeJS (it's dark):

Solved it finally! The solution was that I needed to add intensity to the ambient light.

Related

Three.js: is using a RenderTarget as a mesh the most direct way put a scene back into a WebGLRenderer after an EffectComposer?

I'm attempting to use the Magnify-3d package after using an EffectComposer to apply a bokeh effect to a scene. Magnify-3D takes in a renderer, so I cannot simply pass in the EffectComposer after applying passes.
The intended result would work like a microscope, with the ability to independently adjust the plane of focus by adjusting the BokehPass effect, and the magnification using Magnify-3d.
The only way I've gotten this to work so far has been like so:
Create a temporary scene containing actual scene I want to render.
Create an EffectComposer that applies BokehPass and renders the temporary scene to renderTarget.
Create a PlaneBufferGeometry and a mesh that maps renderTarget.texture (the output of the temporary scene) to the plane, and add this to a new scene.
Render the new scene that effectively is just a camera staring at a mesh of the original scene.
Pass the renderer into magnify3d, which creates a lens effect around the scene I want to render.
This seems to work OK (though there appears to be some fuzziness and distortion of the original scene I'm still working out), but I began to wonder -- is this really the best way to use something rendered to a RenderTarget? Is there a more direct way than effectively taking a picture of a picture that I can use to take the output of an EffectComposer, feed it back into a renderer so my final scene is rendered in a WebGLRenderer, and pass it into a library? Any other way I can think to do this, the EffectComposer would not be able to run (since Magnify3d takes in a renderer, not an EffectComposer and I need to run the EffectComposer before passing it into a renderer).
Here's a screenshot of the final result
Here's some code below:
// create initial scene
const renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
const rtScene = new THREE.Scene();
const rtCamera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
// add a sample cube to the new scene and move the camera back
const geometry = new THREE.BoxGeometry( 10, 10, 1 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
rtScene.add(cube);
rtCamera.position.z = 500;
// initialize renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
document.body.appendChild( renderer.domElement );
// initialize EffectComposer and apply BokehEffect.
// Note that composer renders its output to RenderTarget.
const composer = new EffectComposer( renderer, renderTarget );
composer.renderToScreen = false;
const renderPass = new RenderPass( rtScene, rtCamera );
composer.addPass( renderPass );
const bokehValues = {
focus: 500,
aperture: .00025,
maxblur: 1,
width: window.innerWidth,
height: window.innerHeight
}
export const bokehPass = new BokehPass( rtScene, rtCamera, bokehValues);
composer.addPass( bokehPass );
// create final scene to render before passing to Magnify3D
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000000000 );
const scene = new THREE.Scene();
camera.position.z = 100;
// make a plane geometry, a mesh that maps renderTarget.texture, and add it to the scene
const planeGeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
const planeMaterial = new THREE.MeshBasicMaterial( { map: renderTarget.texture } );
const plane = new THREE.Mesh( planeGeometry, planeMaterial );
scene.add( plane );
function animate() {
// first render temporary scene
renderer.setClearColor( 0xffffff, 1 );
composer.render(); // now composer has rendered to renderTarget
renderer.setClearColor( 0x141414, 1 ); // create a black background for outside of microscope
renderer.render( scene, camera ); // render final scene with meshed plane
// Finally use Magnify3D to render final scene with microscope
magnify3d.render({
renderer: renderer,
pos: {
x: window.innerWidth/2,
y: window.innerHeight/2
},
renderSceneCB: (target) => {
if (target) {
renderer.setRenderTarget(target);
} else {
renderer.setRenderTarget(null);
}
renderer.render(scene, camera);
},
radius: window.innerWidth/5,
exp: 150,
zoom: state.magnification,
});
requestAnimationFrame( animate );
}

Not able to see the roughness on the non-metallic parts of the model, it looks correct in don mccurdy gltf viewer. What am I missing?

I have a model with some parts of it being metallic and others non-metallic. I have applied the environment map to get the correct reflections from the metallic parts of the model but the non metallic parts look equally reflective.
What should I do to make the non-metallic parts to appear less reflective and more rough as they are created. The model looks perfect in the Don Muccurdy’s gltf-viewer.
Please tell me what parameters do I need to change to get it right?
First is my rendered model and Second is the gltf viewer rendered model.
var rgbeLoader=new THREE.RGBELoader().setType( THREE.UnsignedByteType )
.setPath( 'textures/equirectangular/' )
.load( 'pedestrian_overpass_2k.hdr', function ( texture ) {
cubeGenerator = new THREE.EquirectangularToCubeGenerator( texture, { resolution: 1024 } );
cubeGenerator.update( renderer );
pmremGenerator = new THREE.PMREMGenerator( cubeGenerator.renderTarget.texture );
pmremGenerator.update( renderer );
pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
pmremCubeUVPacker.update( renderer );
envMap = pmremCubeUVPacker.CubeUVRenderTarget.texture;
var loader = new THREE.GLTFLoader();
loader.load( 'tfsProject4.glb', function ( gltf ) {
scene.add(gltf.scene);
gltf.scene.traverse((e)=>{
e.material.envMap=envMap;
});
});
The following code is called from a function after loading all the assets including the model shown.
const scene = new THREE.Scene();
modalCamera = new THREE.PerspectiveCamera( 75, modalCanHolder.width() /
modalCanHolder.height(), 0.001, 100 );
var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
scene.add( light );
var light = new THREE.AmbientLight( 0x808080 );
scene.add( light );
var directionalLight = new THREE.DirectionalLight( 0xffffff, .3 );
directionalLight.position.set(0,10,10)
scene.add( directionalLight );
modalRenderer = new THREE.WebGLRenderer({antialias: true, alpha:true});
modalRenderer.gammaOutput = true;
modalRenderer.gammaFactor = 2.2;
modalRenderer.physicallyCorrectLights=true;
modalRenderer.outputEncoding = THREE.sRGBEncoding;
modalRenderer.physicallyCorrectLights = true;
modalRenderer.setSize( modalCanHolder.width(), modalCanHolder.height() );
modalRenderer.setPixelRatio( window.devicePixelRatio );
modalCanHolder.append( modalRenderer.domElement );
modalRenderer.domElement.id = 'modalCanvas';
cubeGenerator.update( modalRenderer );
pmremGenerator.update( modalRenderer );
pmremCubeUVPacker.update( modalRenderer );
var controls = new THREE.OrbitControls( modalCamera, modalRenderer.domElement );
var prod=products[id];
scene.add(prod);
controls.update();
const animate = function () {
subAnimation=requestAnimationFrame( animate );
controls.update();
modalRenderer.render( scene, modalCamera );
};
animate();
Please help me get the rendering right.

Centering pivot point in three.js with OrbitControls autorotate

I'm loading a .glb model into three.js, and while I have it rotating automatically using OrbitControls, I'm not able to see how to change the pivot point so the rotating model is centered.
I've seen a lot of questions on setting boxes or pivot points with rotation, but not with OrbitControls and autorotate. Is there a way for me to center the imported model using autorotate as per my code below?
var scene = new THREE.Scene();
// Load Camera Perspective
var camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 8000 );
camera.position.set( 200, 100, 0 );
// Load a Renderer
var renderer = new THREE.WebGLRenderer({ alpha: false });
renderer.setClearColor( 0xC5C5C3 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Load the Orbitcontroller
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set( 60, 20, 100 );
controls.update();
controls.autoRotate = true;
controls.minDistance = 700;
controls.maxDistance = 2000;
//controls.update();
// Load Light
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 0, 1, 1 ).normalize();
scene.add( directionalLight );
// glTf 2.0 Loader
var loader = new THREE.GLTFLoader();
loader.load( 'BTR.glb', function ( gltf ) {
var object = gltf.scene;
gltf.scene.scale.set( 1, 1, 1 );
gltf.scene.position.x = 0; //Position (x = right+ left-)
gltf.scene.position.y = 0; //Position (y = up+, down-)
gltf.scene.position.z = 0; //Position (z = front +, back-)
scene.add( gltf.scene );
});
function animate() {
// required if controls.enableDamping or controls.autoRotate are set to true
controls.update();
render();
requestAnimationFrame( animate );
}
function render() {
renderer.render( scene, camera );
}
render();
animate();
I think this issue can be solved by setting Controls.target (the focus point) to the center point of your glTF asset. You should be able to do this like so:
var aabb = new THREE.Box3().setFromObject( gltf.scene );
aabb.getCenter( controls.target );
controls.update();
three.js R107
Correct way to set target.
var aabb = new THREE.Box3().setFromObject( gltf.scene );
controls.target.set(aabb.getCenter());
controls.update();
it should take (aab.getCenter()), as it returns a vector3 with 3 axis values. But I found this didn't work for me, so I used the following
let aabb = new THREE.Box3().setFromObject( gltf.scene );
let aabbc = aabb.getCenter()
controls.target.set(aabbc.x, aabbc.y, aabbc.z);
controls.update();
just separating into 3 values, if you ever get stuck just console.log(whateveryourstuckwith) and read through the methods and variables and stuff, really helped me understand Three.js more

Threejs animation issue

Trying to load a STL model into a canavas with Threejs is giving me an error every time the animate function is runned;
Uncaught TypeError: Cannot read property 'render' of undefined
at animate (
I know the STL file is good it worked before.
Here is my code;
// Globals
var scene, camera, light, renderer;
init();
animate();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
//Scene Lighting
scene.add( new THREE.AmbientLight( 0x000000 ) );
//Renderer
var renderer = new THREE.WebGLRenderer({canvas: document.getElementById('modelCan'), antialias:true});
renderer.setClearColor(0xfffffff);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize( window.innerWidth/3, window.innerHeight/3 );
//Camera
var camera = new THREE.PerspectiveCamera(1000, window.innerWidth/window.innerHeight, 1, 10000);
scene.add(camera);
//Camera Lightning
var light = new THREE.PointLight( 0xffffff, 1);
camera.add( light );
var loader = new THREE.STLLoader();
loader.load( 'Sac_Fuel_Tank.stl', function ( geometry ) {
var material = new THREE.MeshLambertMaterial( { color: 0x286617,
wireframe: true
} );
var mesh = new THREE.Mesh( geometry, material );
mesh.rotation.x = Math.PI / 2;
mesh.position.set(20,10,-10);
// mesh.rotation.z = Math.PI;
scene.add( mesh );
} );
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function animate() {
// Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimationFrame(animate);
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
So what am I doinng wrong?
You have to remove the var keyword when creating the renderer. Just do:
renderer = new THREE.WebGLRenderer( { canvas: document.getElementById('modelCan'), antialias:true } );

ThreeJS - GLTF loaded but not appearing

I loaded a GLTF in ThreeJS, and I see in the console GLTFLoader: 37.4208984375ms, but it's not showing up in the scene, and I don't understand why. Also, I used some boilerplate from the ThreeJS website. Here's what the code looks like:
var camera, scene, renderer;
var geometry, material, mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.set(20,0,20);
scene = new THREE.Scene();
// Instantiate a loader
var loader = new THREE.GLTFLoader();
// Load a glTF resource
loader.load( 'Box.gltf', function ( gltf ) {
scene.add( gltf.scene );
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Scene
gltf.scenes; // Array<THREE.Scene>
gltf.cameras; // Array<THREE.Camera>
} );
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
So what am I doing wrong here? Am I missing something?
Two problems:
Your camera is inside your model. Move it farther away.
You call render() only once, long before your model is added to the scene. Call render in a requestAnimationFrame, which is in every Three.js example.

Resources