Browse Source

another example

Garrett Johnson 5 năm trước cách đây
mục cha
commit
b2ce08d983
2 tập tin đã thay đổi với 366 bổ sung0 xóa
  1. 25 0
      example/materialUpdate.html
  2. 341 0
      example/materialUpdate.js

+ 25 - 0
example/materialUpdate.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <style>
+            * {
+                margin: 0;
+                padding: 0;
+            }
+
+            html {
+                overflow: hidden;
+				font-family: Arial, Helvetica, sans-serif;
+				user-select: none;
+            }
+
+			canvas {
+				image-rendering: pixelated;
+				outline: none;
+			}
+        </style>
+    </head>
+    <body>
+        <script src="./materialUpdate.js"></script>
+    </body>
+</html>

+ 341 - 0
example/materialUpdate.js

@@ -0,0 +1,341 @@
+import { TilesRenderer } from '../src/index.js';
+import {
+	Scene,
+	DirectionalLight,
+	AmbientLight,
+	WebGLRenderer,
+	PerspectiveCamera,
+	Box3,
+	OrthographicCamera,
+	sRGBEncoding,
+	Group,
+	ShaderMaterial,
+	MeshStandardMaterial,
+	PCFSoftShadowMap,
+} from 'three';
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
+import * as dat from 'three/examples/jsm/libs/dat.gui.module.js';
+import Stats from 'three/examples/jsm/libs/stats.module.js';
+
+let camera, controls, scene, renderer, tiles, orthoCamera;
+let offsetParent, box, dirLight;
+let stats;
+
+const DEFAULT = 0;
+const GRADIENT = 1;
+const TOPOGRAPHIC_LINES = 2;
+const LIGHTING = 3;
+const params = {
+
+	'material': DEFAULT,
+	'orthographic': false,
+
+};
+
+const gradientShader = {
+	vertexShader: /* glsl */`
+		varying vec3 wPosition;
+		void main() {
+
+			#include <begin_vertex>
+			#include <project_vertex>
+			wPosition = ( modelMatrix * vec4( transformed, 1.0 ) ).xyz;
+
+		}
+	`,
+	fragmentShader: /* glsl */`
+		varying vec3 wPosition;
+		void main() {
+
+			float minVal = - 30.0;
+			float maxVal = 30.0;
+
+			float val = ( wPosition.y - minVal ) / ( maxVal - minVal );
+
+			vec4 color1 = vec4( 0.149, 0.196, 0.219, 1.0 ) * 0.5;
+			vec4 color2 = vec4( 1.0 );
+
+			gl_FragColor = mix( color1, color2, val );
+
+		}
+	`,
+
+};
+
+const topoShader = {
+	extensions: {
+		derivatives: true,
+	},
+	vertexShader: /* glsl */`
+		varying vec3 wPosition;
+		varying vec3 vViewPosition;
+		void main() {
+
+			#include <begin_vertex>
+			#include <project_vertex>
+			wPosition = ( modelMatrix * vec4( transformed, 1.0 ) ).xyz;
+			vViewPosition = - mvPosition.xyz;
+
+		}
+	`,
+	fragmentShader: /* glsl */`
+		varying vec3 wPosition;
+		varying vec3 vViewPosition;
+		void main() {
+
+			// lighting
+			vec3 fdx = vec3( dFdx( wPosition.x ), dFdx( wPosition.y ), dFdx( wPosition.z ) );
+			vec3 fdy = vec3( dFdy( wPosition.x ), dFdy( wPosition.y ), dFdy( wPosition.z ) );
+			vec3 worldNormal = normalize( cross( fdx, fdy ) );
+
+			float lighting =
+				0.4 +
+				clamp( dot( worldNormal, vec3( 1.0, 1.0, 1.0 ) ), 0.0, 1.0 ) * 0.5 +
+				clamp( dot( worldNormal, vec3( - 1.0, 1.0, - 1.0 ) ), 0.0, 1.0 ) * 0.3;
+
+			// thickness scale
+			float upwardness = dot( worldNormal, vec3( 0.0, 1.0, 0.0 ) );
+			float yInv = saturate( 1.0 - abs( upwardness ) );
+			float thicknessScale = pow( yInv, 0.4 );
+			thicknessScale *= 0.25 + 0.5 * ( vViewPosition.z + 1.0 ) / 2.0;
+
+			// thickness
+			float thickness = 0.01 * thicknessScale;
+			float thickness2 = thickness / 2.0;
+			float m = mod( wPosition.y, 3.0 );
+
+			// soften edge
+			float center = thickness2;
+			float dist = clamp( abs( m - thickness2 ) / thickness2, 0.0, 1.0 );
+
+			vec4 topoColor = vec4( 0.149, 0.196, 0.219, 1.0 ) * 0.5;
+			gl_FragColor = mix( topoColor * lighting, vec4( lighting ), dist );
+
+		}
+	`,
+
+};
+
+init();
+animate();
+
+function updateMaterial( scene ) {
+
+	const materialIndex = parseFloat( params.material );
+	scene.traverse( c => {
+
+		if ( c.isMesh ) {
+
+			c.material.dispose();
+			switch( materialIndex ) {
+
+				case DEFAULT:
+					c.material = c.originalMaterial;
+					c.material.side = 2;
+					c.receiveShadow = false;
+					c.castShadow = false;
+					break;
+				case GRADIENT:
+					c.material = new ShaderMaterial( gradientShader );
+					c.material.side = 2;
+					c.receiveShadow = false;
+					c.castShadow = false;
+					break;
+				case TOPOGRAPHIC_LINES:
+					c.material = new ShaderMaterial( topoShader );
+					c.material.side = 2;
+					c.material.flatShading = true;
+					c.receiveShadow = false;
+					c.castShadow = false;
+					break;
+				case LIGHTING:
+					c.material = new MeshStandardMaterial();
+					c.material.side = 2;
+					c.receiveShadow = true;
+					c.castShadow = true;
+
+			}
+
+
+		}
+
+	} );
+
+}
+
+function onLoadModel( scene ) {
+
+	scene.traverse( c => {
+
+		if ( c.isMesh ) {
+
+			c.originalMaterial = c.material;
+
+		}
+
+	} );
+
+	updateMaterial( scene );
+
+}
+
+function init() {
+
+	scene = new Scene();
+
+	// primary camera view
+	renderer = new WebGLRenderer( { antialias: true } );
+	renderer.setPixelRatio( window.devicePixelRatio );
+	renderer.setSize( window.innerWidth, window.innerHeight );
+	renderer.setClearColor( 0x151c1f );
+	renderer.shadowMap.enabled = true;
+	renderer.shadowMap.type = PCFSoftShadowMap;
+	renderer.outputEncoding = sRGBEncoding;
+
+	document.body.appendChild( renderer.domElement );
+
+	camera = new PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 4000 );
+	camera.position.set( 400, 400, 400 );
+
+	orthoCamera = new OrthographicCamera();
+
+	// controls
+	controls = new OrbitControls( camera, renderer.domElement );
+	controls.screenSpacePanning = false;
+	controls.minDistance = 1;
+	controls.maxDistance = 2000;
+
+	// lights
+	dirLight = new DirectionalLight( 0xffffff, 1.25 );
+	dirLight.position.set( 1, 2, 3 ).multiplyScalar( 40 );
+	dirLight.castShadow = true;
+	dirLight.shadow.bias = - 0.01;
+	dirLight.shadow.mapSize.setScalar( 2048 );
+
+	const shadowCam = dirLight.shadow.camera;
+	shadowCam.left = - 200;
+	shadowCam.bottom = - 200;
+	shadowCam.right = 200;
+	shadowCam.top = 200;
+	shadowCam.updateProjectionMatrix();
+
+	scene.add( dirLight );
+
+	const ambLight = new AmbientLight( 0xffffff, 0.05 );
+	scene.add( ambLight );
+
+	box = new Box3();
+
+	offsetParent = new Group();
+	scene.add( offsetParent );
+
+	// tiles
+	const url = window.location.hash.replace( /^#/, '' ) || '../data/tileset.json';
+	tiles = new TilesRenderer( url );
+	tiles.errorTarget = 2;
+	tiles.onLoadModel = onLoadModel;
+	offsetParent.add( tiles.group );
+
+
+	onWindowResize();
+	window.addEventListener( 'resize', onWindowResize, false );
+
+	// GUI
+	const gui = new dat.GUI();
+	gui.width = 300;
+	gui.add( params, 'orthographic' );
+	gui.add( params, 'material', { DEFAULT, GRADIENT, TOPOGRAPHIC_LINES, LIGHTING } )
+		.onChange( () => {
+
+			tiles.forEachLoadedModel( updateMaterial )
+
+		} );
+	gui.open();
+
+	// Stats
+	stats = new Stats();
+	stats.showPanel( 0 );
+	document.body.appendChild( stats.dom );
+
+}
+
+function onWindowResize() {
+
+	camera.aspect = window.innerWidth / window.innerHeight;
+	renderer.setPixelRatio( window.devicePixelRatio );
+	renderer.setSize( window.innerWidth, window.innerHeight );
+	camera.updateProjectionMatrix();
+
+	updateOrthoCamera();
+
+}
+
+function updateOrthoCamera() {
+
+	orthoCamera.position.copy( camera.position );
+	orthoCamera.rotation.copy( camera.rotation );
+
+	const scale = camera.position.distanceTo( controls.target ) / 2.0;
+	let aspect = window.innerWidth / window.innerHeight;
+	orthoCamera.left = - aspect * scale;
+	orthoCamera.right = aspect * scale;
+	orthoCamera.bottom = - scale;
+	orthoCamera.top = scale;
+	orthoCamera.near = camera.near;
+	orthoCamera.far = camera.far;
+	orthoCamera.updateProjectionMatrix();
+
+}
+
+function animate() {
+
+	requestAnimationFrame( animate );
+
+	if ( params.orthographic ) {
+
+		tiles.deleteCamera( camera );
+		tiles.setCamera( orthoCamera );
+		tiles.setResolutionFromRenderer( orthoCamera, renderer );
+
+	} else {
+
+		tiles.deleteCamera( orthoCamera );
+		tiles.setCamera( camera );
+		tiles.setResolutionFromRenderer( camera, renderer );
+
+	}
+
+	offsetParent.rotation.set( 0, 0, 0 );
+	if ( params.up === '-Z' ) {
+
+		offsetParent.rotation.x = Math.PI / 2;
+
+	}
+	offsetParent.updateMatrixWorld( true );
+
+	// update tiles center
+	if ( tiles.getBounds( box ) ) {
+
+		box.getCenter( tiles.group.position );
+		tiles.group.position.multiplyScalar( - 1 );
+
+	}
+
+	// update tiles
+	window.tiles = tiles;
+	camera.updateMatrixWorld();
+	orthoCamera.updateMatrixWorld();
+	tiles.update();
+
+	render();
+	stats.update();
+
+}
+
+function render() {
+
+	updateOrthoCamera();
+
+	renderer.render( scene, params.orthographic ? orthoCamera : camera );
+
+}