Просмотр исходного кода

Examples: More inspector usage. (#31984)

* revision

* update examples

* Update Performance.js

* add example

* Update ReflectorNode.js
sunag 4 месяцев назад
Родитель
Сommit
11b9f4104f

+ 9 - 3
examples/jsm/inspector/RendererInspector.js

@@ -87,6 +87,12 @@ export class RendererInspector extends InspectorBase {
 
 	}
 
+	getParent() {
+
+		return this.currentRender || this.getFrame();
+
+	}
+
 	begin() {
 
 		this.currentFrame = this._createFrame();
@@ -313,7 +319,7 @@ export class RendererInspector extends InspectorBase {
 
 		const currentCompute = new ComputeStats( uid, computeNode );
 		currentCompute.timestamp = performance.now();
-		currentCompute.parent = this.currentRender;
+		currentCompute.parent = this.currentCompute || this.getParent();
 
 		frame.computes.push( currentCompute );
 
@@ -340,7 +346,7 @@ export class RendererInspector extends InspectorBase {
 		const currentCompute = this.currentCompute;
 		currentCompute.cpu = performance.now() - currentCompute.timestamp;
 
-		this.currentCompute = null;
+		this.currentCompute = currentCompute.parent.isComputeStats ? currentCompute.parent : null;
 
 	}
 
@@ -352,7 +358,7 @@ export class RendererInspector extends InspectorBase {
 
 		const currentRender = new RenderStats( uid, scene, camera, renderTarget );
 		currentRender.timestamp = performance.now();
-		currentRender.parent = this.currentRender;
+		currentRender.parent = this.getParent();
 
 		frame.renders.push( currentRender );
 

+ 9 - 1
examples/jsm/inspector/tabs/Performance.js

@@ -129,7 +129,15 @@ class Performance extends Tab {
 
 		}
 
-		setText( item.data[ 0 ], item.userData.name );
+		let name = item.userData.name;
+
+		if ( stats.isComputeStats ) {
+
+			name += ' [ Compute ]';
+
+		}
+
+		setText( item.data[ 0 ], name );
 		setText( item.data[ 1 ], data.cpu.toFixed( 2 ) );
 		setText( item.data[ 2 ], stats.gpuNotAvailable === true ? '-' : data.gpu.toFixed( 2 ) );
 		setText( item.data[ 3 ], data.total.toFixed( 2 ) );

+ 18 - 10
examples/webgpu_compute_cloth.html

@@ -4,12 +4,18 @@
 		<title>three.js webgpu - compute cloth</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
+
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - compute cloth<br />
-			Simple cloth simulation with a verlet system running in compute shaders
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Compute Cloth</span>
+			</div>
+
+			<small>Simple cloth simulation with a verlet system running in compute shaders.</small>
 		</div>
 
 		<script type="importmap">
@@ -29,7 +35,8 @@
 
 			import { Fn, If, Return, instancedArray, instanceIndex, uniform, select, attribute, uint, Loop, float, transformNormalToView, cross, triNoise3D, time } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 			import WebGPU from 'three/addons/capabilities/WebGPU.js';
@@ -87,6 +94,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.toneMapping = THREE.NeutralToneMapping;
 				renderer.toneMappingExposure = 1;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -110,7 +118,7 @@
 
 				setupCloth();
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( stiffnessUniform, 'value', 0.1, 0.5, 0.01 ).name( 'stiffness' );
 				gui.add( params, 'wireframe' );
 				gui.add( params, 'sphere' );
@@ -317,7 +325,7 @@
 					const force = dist.sub( restLength ).mul( stiffnessUniform ).mul( delta ).mul( 0.5 ).div( dist );
 					springForceBuffer.element( instanceIndex ).assign( force );
 
-				} )().compute( springCount );
+				} )().compute( springCount ).setName( 'Spring Forces' );
 
 				// 2. computeVertexForces:
 				// This shader accumulates the force for each vertex.
@@ -381,7 +389,7 @@
 					vertexForceBuffer.element( instanceIndex ).assign( force );
 					vertexPositionBuffer.element( instanceIndex ).addAssign( force );
 
-				} )().compute( vertexCount );
+				} )().compute( vertexCount ).setName( 'Vertex Forces' );
 
 			}
 
@@ -569,12 +577,12 @@
 					timestamp += timePerStep;
 					timeSinceLastStep -= timePerStep;
 					updateSphere();
-					await renderer.computeAsync( computeSpringForces );
-					await renderer.computeAsync( computeVertexForces );
+					renderer.compute( computeSpringForces );
+					renderer.compute( computeVertexForces );
 
 				}
 
-				await renderer.renderAsync( scene, camera );
+				renderer.render( scene, camera );
 
 			}
 

+ 12 - 13
examples/webgpu_compute_geometry.html

@@ -4,12 +4,18 @@
 		<title>three.js webgpu - compute geometry</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js webgpu</a> - compute geometry
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Compute Geometry</span>
+			</div>
+
+			<small>Jelly deformation with compute shaders. Move pointer to interact.</small>
 		</div>
 
 		<script type="importmap">
@@ -32,13 +38,10 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
-
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
 			let camera, scene, renderer;
 			let raycaster, pointer;
-			let stats;
 
 			let mesh;
 
@@ -117,7 +120,7 @@
 
 					currentPosition.addAssign( currentSpeed );
 
-				} )().compute( count );
+				} )().compute( count ).setName( 'Update Jelly' );
 
 				// initialize the storage buffer with the base position
 
@@ -172,21 +175,19 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				const controls = new OrbitControls( camera, renderer.domElement );
 				controls.minDistance = .7;
 				controls.maxDistance = 2;
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 				gui.add( elasticity, 'value', 0, .5 ).name( 'elasticity' );
 				gui.add( damping, 'value', .9, .98 ).name( 'damping' );
 				gui.add( brushSize, 'value', .1, .5 ).name( 'brush size' );
 				gui.add( brushStrength, 'value', .1, .3 ).name( 'brush strength' );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				window.addEventListener( 'resize', onWindowResize );
 				window.addEventListener( 'pointermove', onPointerMove );
 
@@ -226,8 +227,6 @@
 
 			async function animate() {
 
-				stats.update();
-
 				renderer.render( scene, camera );
 
 			}

+ 21 - 58
examples/webgpu_compute_particles.html

@@ -1,27 +1,20 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Compute Particles</title>
+		<title>three.js webgpu - compute particles</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Compute - 500k Particles
-			<div id="timestamps" style="
-				position: absolute;
-				top: 60px;
-				left: 0;
-				padding: 10px;
-				background: rgba( 0, 0, 0, 0.5 );
-				color: #fff;
-				font-family: monospace;
-				font-size: 12px;
-				line-height: 1.5;
-				pointer-events: none;
-				text-align: left;
-			"></div>
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Compute Particles</span>
+			</div>
+
+			<small>500k Particles.</small>
 		</div>
 
 		<script type="importmap">
@@ -41,10 +34,9 @@
 			import { Fn, If, uniform, float, uv, vec3, hash, shapeCircle,
 				instancedArray, instanceIndex } from 'three/tsl';
 
-			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 			const particleCount = 200000;
 
@@ -56,13 +48,11 @@
 			const clickPosition = uniform( new THREE.Vector3() );
 
 			let camera, scene, renderer;
-			let controls, stats;
+			let controls;
 			let computeParticles;
 
 			let isOrbitControlsActive;
 
-			const timestamps = document.getElementById( 'timestamps' );
-
 			init();
 
 			function init() {
@@ -100,7 +90,7 @@
 					color.x = hash( instanceIndex );
 					color.y = hash( instanceIndex.add( 2 ) );
 
-				} )().compute( particleCount );
+				} )().compute( particleCount ).setName( 'Init Particles' );
 
 				//
 
@@ -130,7 +120,7 @@
 
 				} );
 
-				computeParticles = computeUpdate().compute( particleCount );
+				computeParticles = computeUpdate().compute( particleCount ).setName( 'Update Particles' );
 
 				// create particles
 
@@ -163,15 +153,13 @@
 
 				//
 
-				renderer = new THREE.WebGPURenderer( { antialias: true, trackTimestamp: true } );
+				renderer = new THREE.WebGPURenderer( { antialias: true } );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
-
 				//
 
 				renderer.computeAsync( computeInit );
@@ -192,7 +180,7 @@
 
 					velocity.assign( velocity.add( direction.mul( relativePower ) ) );
 
-				} )().compute( particleCount );
+				} )().compute( particleCount ).setName( 'Hit Particles' );
 
 				//
 
@@ -256,7 +244,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				gui.add( gravity, 'value', - .0098, 0, 0.0001 ).name( 'gravity' );
 				gui.add( bounce, 'value', .1, 1, 0.01 ).name( 'bounce' );
@@ -276,37 +264,12 @@
 
 			}
 
-			async function animate() {
-
-				stats.update();
+			function animate() {
 
 				controls.update();
 
-				await renderer.computeAsync( computeParticles );
-				renderer.resolveTimestampsAsync( THREE.TimestampQuery.COMPUTE );
-
-				await renderer.renderAsync( scene, camera );
-				renderer.resolveTimestampsAsync( THREE.TimestampQuery.RENDER );
-
-				// throttle the logging
-
-				if ( renderer.hasFeature( 'timestamp-query' ) ) {
-
-					if ( renderer.info.render.calls % 5 === 0 ) {
-
-						timestamps.innerHTML = `
-
-							Compute ${renderer.info.compute.frameCalls} pass in ${renderer.info.compute.timestamp.toFixed( 6 )}ms<br>
-							Draw ${renderer.info.render.drawCalls} pass in ${renderer.info.render.timestamp.toFixed( 6 )}ms`;
-
-					}
-
-				} else {
-
-					timestamps.innerHTML = 'Timestamp queries not supported';
-
-				}
-
+				renderer.compute( computeParticles );
+				renderer.render( scene, camera );
 
 			}
 

+ 25 - 13
examples/webgpu_compute_particles_fluid.html

@@ -4,13 +4,18 @@
 		<title>three.js webgpu - compute fluid particles</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - fluid particles<br />
-			MLS-MPM particle simulation running in compute shaders
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Fluid Particles</span>
+			</div>
+
+			<small>MLS-MPM particle simulation running in compute shaders.</small>
 		</div>
 
 		<script type="importmap">
@@ -30,7 +35,8 @@
 
 			import { Fn, If, Return, instancedArray, instanceIndex, uniform, attribute, uint, float, clamp, struct, atomicStore, int, ivec3, array, vec3, atomicAdd, Loop, atomicLoad, max, pow, mat3, vec4, cross, step } from 'three/tsl';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 			import { HDRLoader } from 'three/addons/loaders/HDRLoader.js';
 			import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
@@ -60,8 +66,6 @@
 
 			}
 
-			const gui = new GUI();
-
 			const params = {
 				particleCount: 8192 * 4,
 			};
@@ -75,6 +79,7 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.toneMapping = THREE.ACESFilmicToneMapping;
 				renderer.toneMappingExposure = 1.35;
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				scene = new THREE.Scene();
@@ -99,6 +104,8 @@
 
 				setupParticles();
 
+				const gui = renderer.inspector.createParameters( 'Settings' );
+
 				gui.add( params, 'particleCount', 4096, maxParticles, 4096 ).onChange( value => {
 
 					p2g1Kernel.count = value;
@@ -203,7 +210,7 @@
 					atomicStore( cellBuffer.element( instanceIndex ).get( 'z' ), 0 );
 					atomicStore( cellBuffer.element( instanceIndex ).get( 'mass' ), 0 );
 			
-				} )().compute( cellCount );
+				} )().compute( cellCount ).setName( 'clearGridKernel' );
 
 				p2g1Kernel = Fn( () => {
 
@@ -251,7 +258,7 @@
 			
 					} );
 			
-				} )().compute( params.particleCount );
+				} )().compute( params.particleCount ).setName( 'p2g1Kernel' );
 
 				p2g2Kernel = Fn( () => {
 
@@ -322,7 +329,7 @@
 			
 					} );
 			
-				} )().compute( params.particleCount );
+				} )().compute( params.particleCount ).setName( 'p2g2Kernel' );
 
 				updateGridKernel = Fn( () => {
 
@@ -364,7 +371,7 @@
 
 					cellBufferFloat.element( instanceIndex ).assign( vec4( vx, vy, vz, mass ) );
 			
-				} )().compute( cellCount );
+				} )().compute( cellCount ).setName( 'updateGridKernel' );
 
 
 				const clampToRoundedBox = ( pos, box, radius ) => {
@@ -470,7 +477,7 @@
 					particleBuffer.element( instanceIndex ).get( 'position' ).assign( particlePosition );
 					particleBuffer.element( instanceIndex ).get( 'velocity' ).assign( particleVelocity );
 			
-				} )().compute( params.particleCount );
+				} )().compute( params.particleCount ).setName( 'g2pKernel' );
 
 			}
 
@@ -554,9 +561,14 @@
 
 				prevMouseCoord.copy( mouseCoord );
 
-				await renderer.computeAsync( [ clearGridKernel, p2g1Kernel, p2g2Kernel, updateGridKernel, g2pKernel ] );
+				//renderer.compute( [ clearGridKernel, p2g1Kernel, p2g2Kernel, updateGridKernel, g2pKernel ] );
+				renderer.compute( clearGridKernel );
+				renderer.compute( p2g1Kernel );
+				renderer.compute( p2g2Kernel );
+				renderer.compute( updateGridKernel );
+				renderer.compute( g2pKernel );
 
-				await renderer.renderAsync( scene, camera );
+				renderer.render( scene, camera );
 
 			}
 

+ 17 - 14
examples/webgpu_compute_particles_rain.html

@@ -1,14 +1,20 @@
 <html lang="en">
 	<head>
-		<title>three.js - WebGPU - Compute Particles Rain</title>
+		<title>three.js webgpu - compute particles rain</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - GPU Compute Rain
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Compute Rain</span>
+			</div>
+
+			<small>Compatible with native lights and shadows using post-processing pass.</small>
 		</div>
 
 		<script type="importmap">
@@ -27,11 +33,9 @@
 			import * as THREE from 'three/webgpu';
 			import { Fn, texture, uv, uint, instancedArray, positionWorld, billboarding, time, hash, deltaTime, vec2, instanceIndex, positionGeometry, If } from 'three/tsl';
 
-			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
-
-			import Stats from 'three/addons/libs/stats.module.js';
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
 
-			import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
+			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
 			import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js';
 
@@ -39,7 +43,7 @@
 			const instanceCount = maxParticleCount / 2;
 
 			let camera, scene, renderer;
-			let controls, stats;
+			let controls;
 			let computeParticles;
 			let monkey;
 			let clock;
@@ -181,7 +185,7 @@
 
 				} );
 
-				computeParticles = computeUpdate().compute( maxParticleCount );
+				computeParticles = computeUpdate().compute( maxParticleCount ).setName( 'Particles' );
 
 				// rain
 
@@ -284,9 +288,8 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
-				stats = new Stats();
-				document.body.appendChild( stats.dom );
 
 				//
 
@@ -305,7 +308,7 @@
 
 				// gui
 
-				const gui = new GUI();
+				const gui = renderer.inspector.createParameters( 'Settings' );
 
 				// use lerp to smooth the movement
 				collisionBoxPosUI = new THREE.Vector3().copy( collisionBox.position );
@@ -330,8 +333,6 @@
 
 			function animate() {
 
-				stats.update();
-
 				const delta = clock.getDelta();
 
 				if ( monkey ) {
@@ -347,6 +348,7 @@
 				// position
 
 				scene.overrideMaterial = collisionPosMaterial;
+				scene.name = 'Collision Scene';
 				renderer.setRenderTarget( collisionPosRT );
 				renderer.render( scene, collisionCamera );
 
@@ -357,6 +359,7 @@
 				// result
 
 				scene.overrideMaterial = null;
+				scene.name = 'Scene';
 				renderer.setRenderTarget( null );
 				renderer.render( scene, camera );
 

+ 13 - 4
examples/webgpu_mirror.html

@@ -4,12 +4,18 @@
 		<title>three.js webgpu - mirror</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<link type="text/css" rel="stylesheet" href="main.css">
+		<link type="text/css" rel="stylesheet" href="example.css">
 	</head>
 	<body>
 
 		<div id="info">
-			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgpu - mirror
+			<a href="https://threejs.org/" target="_blank" rel="noopener" class="logo-link"></a>
+
+			<div class="title-wrapper">
+				<a href="https://threejs.org/" target="_blank" rel="noopener">three.js</a><span>Mirror</span>
+			</div>
+
+			<small>Mirror reflections using procedural effects.</small>
 		</div>
 
 		<script type="importmap">
@@ -30,6 +36,8 @@
 
 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 
+			import { Inspector } from 'three/addons/inspector/Inspector.js';
+
 			let camera, scene, renderer;
 
 			let cameraControls;
@@ -91,8 +99,8 @@
 
 				// reflectors / mirrors
 
-				const groundReflector = reflector();
-				const verticalReflector = reflector();
+				const groundReflector = reflector().toInspector( 'Ground Reflector' );
+				const verticalReflector = reflector().toInspector( 'Vertical Reflector' );
 
 				const groundNormalScale = - 0.08;
 				const verticalNormalScale = 0.1;
@@ -176,6 +184,7 @@
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setAnimationLoop( animate );
+				renderer.inspector = new Inspector();
 				document.body.appendChild( renderer.domElement );
 
 				// controls

+ 6 - 0
src/nodes/utils/ReflectorNode.js

@@ -560,8 +560,14 @@ class ReflectorBaseNode extends Node {
 
 		} else {
 
+			const previousName = scene.name;
+
+			scene.name = ( scene.name || 'Scene' ) + ' [ Reflector ]'; // TODO: Add bounce index
+
 			renderer.render( scene, virtualCamera );
 
+			scene.name = previousName;
+
 			this.hasOutput = true;
 
 		}

粤ICP备19079148号