app icon indicating copy to clipboard operation
app copied to clipboard

Logarithmic depth buffer for avatars?

Open pigloo opened this issue 2 years ago • 9 comments

In very large scale scenes it is apparent that the scene uses logarithmic depth buffers but the avatar does not, is it possible to update avatars to use the logarithmic depth buffer too?

Move the player 1,000,000 units from the center to see this effect clearly.

Screenshot from 2022-08-04 22-57-40

pigloo avatar Aug 04 '22 22:08 pigloo

This probably wouldn't be related to depth buffers, but rather float accuracy of rendering with large distance offsets in the matrix chain.

The fix might be to either clean up the matrix math, or perform intelligent rebasing of objects to a local frame of reference when they get far from their origin.

avaer avatar Aug 08 '22 22:08 avaer

An alternative way I've seen to reproduce this is to let your avatar fall into the void for a few minutes.

avaer avatar Aug 08 '22 22:08 avaer

https://github.com/webaverse/app/blob/1ca437fc7bb618d951f04294541fa23cfd6db117/constants.js#L122

Change initialPosY to -1e5 to reproduce the problem.

jakezira avatar Aug 08 '22 22:08 jakezira

perform intelligent rebasing of objects to a local frame of reference when they get far from their origin.

I will try to create another intermediate object for avatar, which is translated to the bone root position, so that all character bone transformation can be done on origin position.

jakezira avatar Aug 08 '22 23:08 jakezira

Reason

This is three bug. Filed the same problem on THREE.js issue list here: https://github.com/mrdoob/three.js/issues/24479

Environment

Code

This is the simple example from three-vrm: https://pixiv.github.io/three-vrm/packages/three-vrm/examples/debug.html Added midObj to set the offset.

<!DOCTYPE html>

<html>
	<head>
		<meta charset="utf-8" />
		<title>three-vrm example</title>
		<meta
			name="viewport"
			content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
		/>
		<style>
			body {
				margin: 0;
			}
			canvas {
				display: block;
			}
		</style>
	</head>

	<body>
		<script src="https://unpkg.com/[email protected]/build/three.js"></script>
		<script src="https://unpkg.com/[email protected]/examples/js/loaders/GLTFLoader.js"></script>
		<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>
		<script src="./lib/three-vrm.js"></script>
		<script>
			// renderer
			const renderer = new THREE.WebGLRenderer();
			renderer.setSize( window.innerWidth, window.innerHeight );
			renderer.setPixelRatio( window.devicePixelRatio );
			document.body.appendChild( renderer.domElement );

			const offset = 100000.0;

			// camera
			const camera = new THREE.PerspectiveCamera( 30.0, window.innerWidth / window.innerHeight, 0.1, 30 );
			camera.position.set( 0.0, offset, 5.0 );

			// camera controls
			const controls = new THREE.OrbitControls( camera, renderer.domElement );
			controls.screenSpacePanning = true;
			controls.target.set( 0.0, offset, 0.0 );
			controls.update();

			// scene
			const scene = new THREE.Scene();

			// light
			const light = new THREE.DirectionalLight( 0xffffff );
			light.position.set( 1.0, 1.0, 1.0 ).normalize();
			scene.add( light );

			// gltf and vrm
			const loader = new THREE.GLTFLoader();
			loader.crossOrigin = 'anonymous';
			loader.load(

				// URL of the VRM you want to load
				'./models/scilly_drophunter_v31.6_Guilty.vrm',

				// called when the resource is loaded
				( gltf ) => {

					// generate VRM instance from gltf
					THREE.VRMDebug.from( gltf ).then( ( vrm ) => {

						const midObj = new THREE.Object3D();
						scene.add( midObj );
						midObj.add( vrm.scene );

						midObj.position.copy(new THREE.Vector3( 0, offset, 0 ));
						
						vrm.humanoid.getBoneNode( THREE.VRMSchema.HumanoidBoneName.Hips ).rotation.y = Math.PI;
						vrm.springBoneManager.reset();

					} );

				},

				// called while loading is progressing
				( progress ) => console.log( 'Loading model...', 100.0 * ( progress.loaded / progress.total ), '%' ),

				// called when loading has errors
				( error ) => console.error( error )

			);

			// helpers
			const gridHelper = new THREE.GridHelper( 10, 10 );
			scene.add( gridHelper );

			const axesHelper = new THREE.AxesHelper( 5 );
			scene.add( axesHelper );

			function animate() {

				requestAnimationFrame( animate );

				renderer.render( scene, camera );
			}

			animate();
		</script>
	</body>
</html>

Test 1: offset=0 ==> Correct

image

Test 2: offset=100000 ==> Bad rendering

image

jakezira avatar Aug 09 '22 21:08 jakezira

Fixed

  • https://github.com/webaverse/app/pull/3600
  • https://github.com/webaverse/three/pull/23

Screenshot

Jumping below y < -100000 image

Environment

  • Pull above two branches.

Test

Tested on

  • Animation of avatar
  • Animation of npc
  • When avatar's falling far below y < -100000
  • Wear weapons, helmets
  • Sit on vehicle
  • Tested on street.scn and shadows.scn

jakezira avatar Aug 11 '22 14:08 jakezira

Test (Additional)

Tested on

  • When npc's falling far below y < -100000
  • When weapons, helmets are below y < -100000
  • Unwear weapons, helmets after wear

image

jakezira avatar Aug 11 '22 15:08 jakezira

Test (Additional)

Tested on

  • 2 avatars (scilly, ann)
    • These two have different skeleton hierarchy
  • Animation (moving, falling)
  • Wear/unwear gears
    • Weapon is rigid, helm is skinned mesh
    • Need to test on 2 avatars
  • Falling, on each avatars, with each gears

jakezira avatar Aug 11 '22 22:08 jakezira

mobs could be affected by this, but couldn't test yet. I will work on it when https://github.com/webaverse/app/pull/3385 is merged.

jakezira avatar Aug 12 '22 20:08 jakezira