You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					316 lines
				
				7.5 KiB
			
		
		
			
		
	
	
					316 lines
				
				7.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								<!DOCTYPE html>
							 | 
						||
| 
								 | 
							
								<html lang="en">
							 | 
						||
| 
								 | 
							
									<head>
							 | 
						||
| 
								 | 
							
										<title>three.js WebGL 2 - Uniform Buffer Objects</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">
							 | 
						||
| 
								 | 
							
									</head>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									<body>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<div id="info">
							 | 
						||
| 
								 | 
							
											<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Uniform Buffer Objects
							 | 
						||
| 
								 | 
							
										</div>
							 | 
						||
| 
								 | 
							
										<div id="container"></div>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script id="vertexShader1" type="x-shader/x-vertex">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform ViewData {
							 | 
						||
| 
								 | 
							
												mat4 projectionMatrix;
							 | 
						||
| 
								 | 
							
												mat4 viewMatrix;
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform mat4 modelMatrix;
							 | 
						||
| 
								 | 
							
											uniform mat3 normalMatrix;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											in vec3 position;
							 | 
						||
| 
								 | 
							
											in vec3 normal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											out vec3 vPositionEye;
							 | 
						||
| 
								 | 
							
											out vec3 vNormalEye;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											void main()	{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vec4 vertexPositionEye = viewMatrix * modelMatrix * vec4( position, 1.0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vPositionEye = vertexPositionEye.xyz;
							 | 
						||
| 
								 | 
							
												vNormalEye = normalMatrix * normal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												gl_Position = projectionMatrix * vertexPositionEye;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script id="fragmentShader1" type="x-shader/x-fragment">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											precision highp float;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform LightingData {
							 | 
						||
| 
								 | 
							
												vec3 position;
							 | 
						||
| 
								 | 
							
												vec3 ambientColor;
							 | 
						||
| 
								 | 
							
												vec3 diffuseColor;
							 | 
						||
| 
								 | 
							
												vec3 specularColor;
							 | 
						||
| 
								 | 
							
												float shininess;
							 | 
						||
| 
								 | 
							
											} Light;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform vec3 color;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											in vec3 vPositionEye;
							 | 
						||
| 
								 | 
							
											in vec3 vNormalEye;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											out vec4 fragColor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											void main()	{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// a very basic lighting equation (Phong reflection model) for testing
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vec3 l = normalize( Light.position - vPositionEye );
							 | 
						||
| 
								 | 
							
												vec3 n = normalize( vNormalEye );
							 | 
						||
| 
								 | 
							
												vec3 e = - normalize( vPositionEye );
							 | 
						||
| 
								 | 
							
												vec3 r = normalize( reflect( - l, n ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												float diffuseLightWeighting = max( dot( n, l ), 0.0 );
							 | 
						||
| 
								 | 
							
												float specularLightWeighting = max( dot( r, e ), 0.0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												specularLightWeighting = pow( specularLightWeighting, Light.shininess );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vec3 lightWeighting = Light.ambientColor +
							 | 
						||
| 
								 | 
							
													Light.diffuseColor * diffuseLightWeighting +
							 | 
						||
| 
								 | 
							
													Light.specularColor * specularLightWeighting;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												fragColor = vec4( color.rgb * lightWeighting.rgb, 1.0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script id="vertexShader2" type="x-shader/x-vertex">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform ViewData {
							 | 
						||
| 
								 | 
							
												mat4 projectionMatrix;
							 | 
						||
| 
								 | 
							
												mat4 viewMatrix;
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform mat4 modelMatrix;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											in vec3 position;
							 | 
						||
| 
								 | 
							
											in vec2 uv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											out vec2 vUv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											void main()	{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												vUv = uv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script id="fragmentShader2" type="x-shader/x-fragment">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											precision highp float;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											uniform sampler2D diffuseMap;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											in vec2 vUv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											out vec4 fragColor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											void main()	{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												fragColor = texture( diffuseMap, vUv );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<!-- Import maps polyfill -->
							 | 
						||
| 
								 | 
							
										<!-- Remove this when import maps will be widely supported -->
							 | 
						||
| 
								 | 
							
										<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script type="importmap">
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												"imports": {
							 | 
						||
| 
								 | 
							
													"three": "../build/three.module.js",
							 | 
						||
| 
								 | 
							
													"three/addons/": "./jsm/"
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										<script type="module">
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											import * as THREE from 'three';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											import WebGL from 'three/addons/capabilities/WebGL.js';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											let camera, scene, renderer, clock;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											init();
							 | 
						||
| 
								 | 
							
											animate();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											function init() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if ( WebGL.isWebGL2Available() === false ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													document.body.appendChild( WebGL.getWebGL2ErrorMessage() );
							 | 
						||
| 
								 | 
							
													return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const container = document.getElementById( 'container' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 100 );
							 | 
						||
| 
								 | 
							
												camera.position.set( 0, 0, 25 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												scene = new THREE.Scene();
							 | 
						||
| 
								 | 
							
												camera.lookAt( scene.position );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												clock = new THREE.Clock();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// geometry
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const geometry1 = new THREE.TetrahedronGeometry();
							 | 
						||
| 
								 | 
							
												const geometry2 = new THREE.BoxGeometry();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// texture
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const texture = new THREE.TextureLoader().load( 'textures/crate.gif' );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// uniforms groups
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// Camera and lighting related data are perfect examples of using UBOs since you have to store these
							 | 
						||
| 
								 | 
							
												// data just once. They can be shared across all shader programs.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const cameraUniformsGroup = new THREE.UniformsGroup();
							 | 
						||
| 
								 | 
							
												cameraUniformsGroup.setName( 'ViewData' );
							 | 
						||
| 
								 | 
							
												cameraUniformsGroup.add( new THREE.Uniform( camera.projectionMatrix ) ); // projection matrix
							 | 
						||
| 
								 | 
							
												cameraUniformsGroup.add( new THREE.Uniform( camera.matrixWorldInverse ) ); // view matrix
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const lightingUniformsGroup = new THREE.UniformsGroup();
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.setName( 'LightingData' );
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.add( new THREE.Uniform( new THREE.Vector3( 0, 0, 10 ) ) ); // light position
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.add( new THREE.Uniform( new THREE.Color( 0x333333 ) ) ); // ambient color
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.add( new THREE.Uniform( new THREE.Color( 0xaaaaaa ) ) ); // diffuse color
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.add( new THREE.Uniform( new THREE.Color( 0xcccccc ) ) ); // specular color
							 | 
						||
| 
								 | 
							
												lightingUniformsGroup.add( new THREE.Uniform( 64 ) ); // shininess
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// materials
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const material1 = new THREE.RawShaderMaterial( {
							 | 
						||
| 
								 | 
							
													uniforms: {
							 | 
						||
| 
								 | 
							
														modelMatrix: { value: null },
							 | 
						||
| 
								 | 
							
														normalMatrix: { value: null },
							 | 
						||
| 
								 | 
							
														color: { value: null }
							 | 
						||
| 
								 | 
							
													},
							 | 
						||
| 
								 | 
							
													vertexShader: document.getElementById( 'vertexShader1' ).textContent,
							 | 
						||
| 
								 | 
							
													fragmentShader: document.getElementById( 'fragmentShader1' ).textContent,
							 | 
						||
| 
								 | 
							
													glslVersion: THREE.GLSL3
							 | 
						||
| 
								 | 
							
												} );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const material2 = new THREE.RawShaderMaterial( {
							 | 
						||
| 
								 | 
							
													uniforms: {
							 | 
						||
| 
								 | 
							
														modelMatrix: { value: null },
							 | 
						||
| 
								 | 
							
														diffuseMap: { value: null },
							 | 
						||
| 
								 | 
							
													},
							 | 
						||
| 
								 | 
							
													vertexShader: document.getElementById( 'vertexShader2' ).textContent,
							 | 
						||
| 
								 | 
							
													fragmentShader: document.getElementById( 'fragmentShader2' ).textContent,
							 | 
						||
| 
								 | 
							
													glslVersion: THREE.GLSL3
							 | 
						||
| 
								 | 
							
												} );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												// meshes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												for ( let i = 0; i < 200; i ++ ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													let mesh;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if ( i % 2 === 0 ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														mesh = new THREE.Mesh( geometry1, material1.clone() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														mesh.material.uniformsGroups = [ cameraUniformsGroup, lightingUniformsGroup ];
							 | 
						||
| 
								 | 
							
														mesh.material.uniforms.modelMatrix.value = mesh.matrixWorld;
							 | 
						||
| 
								 | 
							
														mesh.material.uniforms.normalMatrix.value = mesh.normalMatrix;
							 | 
						||
| 
								 | 
							
														mesh.material.uniforms.color.value = new THREE.Color( 0xffffff * Math.random() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														mesh = new THREE.Mesh( geometry2, material2.clone() );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														mesh.material.uniformsGroups = [ cameraUniformsGroup ];
							 | 
						||
| 
								 | 
							
														mesh.material.uniforms.modelMatrix.value = mesh.matrixWorld;
							 | 
						||
| 
								 | 
							
														mesh.material.uniforms.diffuseMap.value = texture;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													scene.add( mesh );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													const s = 1 + Math.random() * 0.5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													mesh.scale.x = s;
							 | 
						||
| 
								 | 
							
													mesh.scale.y = s;
							 | 
						||
| 
								 | 
							
													mesh.scale.z = s;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													mesh.rotation.x = Math.random() * Math.PI;
							 | 
						||
| 
								 | 
							
													mesh.rotation.y = Math.random() * Math.PI;
							 | 
						||
| 
								 | 
							
													mesh.rotation.z = Math.random() * Math.PI;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													mesh.position.x = Math.random() * 40 - 20;
							 | 
						||
| 
								 | 
							
													mesh.position.y = Math.random() * 40 - 20;
							 | 
						||
| 
								 | 
							
													mesh.position.z = Math.random() * 20 - 10;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												renderer = new THREE.WebGLRenderer( { antialias: true } );
							 | 
						||
| 
								 | 
							
												renderer.setPixelRatio( window.devicePixelRatio );
							 | 
						||
| 
								 | 
							
												renderer.setSize( window.innerWidth, window.innerHeight );
							 | 
						||
| 
								 | 
							
												container.appendChild( renderer.domElement );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												window.addEventListener( 'resize', onWindowResize, false );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											function onWindowResize() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												camera.aspect = window.innerWidth / window.innerHeight;
							 | 
						||
| 
								 | 
							
												camera.updateProjectionMatrix();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												renderer.setSize( window.innerWidth, window.innerHeight );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											function animate() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												requestAnimationFrame( animate );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												const delta = clock.getDelta();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												scene.traverse( function ( child ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													if ( child.isMesh ) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
														child.rotation.x += delta * 0.5;
							 | 
						||
| 
								 | 
							
														child.rotation.y += delta * 0.3;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												} );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												renderer.render( scene, camera );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										</script>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									</body>
							 | 
						||
| 
								 | 
							
								</html>
							 |