Enable Sketchfab-like lighting and shadows

Faced a problem. Loading model https://sketchfab.com/3d-models/nissan-z-proto-db9a5f7ae9d84a0fb01cac96afe3e69c I would like to make the shadows and light exactly the same as in the form of the model itself. But it turns out not quite what I would like https://ibb.co/pnvWqRk

I attach the sources https://dropmefiles.com/aJsF8
Thank you in advance.

I’ve played with your code around a bit and this is the result:

Updated code (plugin.js):

const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xa0a0a0 );
scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );

const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 7, 3, 7 );

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();

const doc = document.querySelector( '.main' );
doc.appendChild( renderer.domElement );

window.addEventListener( 'resize', function () {

	const width = window.innerWidth;
	const height = window.innerHeight;
	renderer.setSize( width, height );
	camera.aspect = width / height;
	camera.updateProjectionMatrix();

} );

const controls = new THREE.OrbitControls( camera, renderer.domElement );

const hlight = new THREE.AmbientLight( 0x404040, 1 );
scene.add( hlight );

const directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
directionalLight.castShadow = true;
directionalLight.shadow.camera.top = 4;
directionalLight.shadow.camera.bottom = - 4;
directionalLight.shadow.camera.left = - 4;
directionalLight.shadow.camera.right = 4;
directionalLight.shadow.camera.near = 0.1;
directionalLight.shadow.camera.far = 40;
directionalLight.shadow.camera.far = 40;
directionalLight.shadow.bias = - 0.002;
directionalLight.position.set( 0, 20, 20 );
scene.add( directionalLight );

//scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );

// ground

const mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 100, 100 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );

// car

new THREE.RGBELoader()
	.setDataType( THREE.UnsignedByteType )
	.setPath( 'img/' )
	.load( 'pedestrian_overpass_1k.hdr', function ( texture ) {

		const envMap = pmremGenerator.fromEquirectangular( texture ).texture;

		scene.environment = envMap;

		texture.dispose();
		pmremGenerator.dispose();

		var loader = new THREE.GLTFLoader();
		loader.load( 'img/nissan/scene.gltf', handle_load );

	} );


let car;

function handle_load( gltf ) {

	car = gltf.scene;
	car.position.y = 1.1;

	car.traverse( function ( child ) {

		if ( child.isMesh ) {

			child.castShadow = true;
			child.receiveShadow = true;

		}

	} );

	scene.add( car );

	animate();

}

const animate = function () {

	requestAnimationFrame( animate );

	renderer.render( scene, camera );

};
  • It’s a must for such models to apply a HDR environment map for best PBR results. Check out the usage of PMREMGenerator. You also might want to switch the HDR environment map to achieve a different lighting.
  • You have to configure a sRGB and tone mapping workflow. Check the rendering setting for this.
  • Honor the device pixel ratio to render in the highest possible resolution. Also enable antialiasing.
  • The example code uses now your directional light as a shadow casting light. To do this, you have to enable shadows at your renderer and configure shadow casting and receiving objects.
  • If you copy the code into your project, you have to add RGBELoader to your index.html. The HDR texture pedestrian_overpass_1k.hdr is from here.
  • You do not necessarily need an animation loop for this scene since it is static. Consider to use on-demand rendering.
9 Likes

thanks for the answer. I will try.

This was very educational for me. Thank you for the question and the answer!

4 Likes

This is like a boiler plate for me. It sets you in the right path with minimal effort. Thanks @Mugen87 for posting plugin.js

1 Like