ThreeJs的學習:自定義着色器程序

着色器語言GLSL ES和相關的WebGL API、

OpenGL ES Shader相關API —— GLSL 語法

<!DOCTYPE html>
<html lang="en">
<head>
	<title>three.js webgl - indexed instancing (single box), dynamic updates</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
	<style>
		a {color: #08f;}

	</style>
</head>
<body>

	<div id="container"></div>
	<script src="js/three.js"></script>
	<script src="js/WebGL.js"></script>
	<script id="vertexShader" type="x-shader/x-vertex">
	    // 頂點着色器(vertexShader)
		precision highp float;

		uniform mat4 modelViewMatrix;
		uniform mat4 projectionMatrix;

		attribute vec3 jinold_position;
		attribute vec3 jinold_offset;
		attribute vec2 jinold_uv;
		attribute vec4 jinold_orientation;

		varying vec2 vUv;

		// http://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/

		vec3 applyQuaternionToVector( vec4 q, vec3 v ){

			return v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );

		}

		void main() {

			vec3 vPosition = applyQuaternionToVector( jinold_orientation, jinold_position );

			vUv = jinold_uv;

			gl_Position = projectionMatrix * modelViewMatrix * vec4( jinold_offset + vPosition, 1.0 );

		}
	</script>

	<script id="fragmentShader" type="x-shader/x-fragment">
	    // 片段着色器(fragmentShader)
		precision highp float;

		uniform sampler2D map;

		varying vec2 vUv;

		void main() {

			gl_FragColor = texture2D( map, vUv );

		}
	</script>

	<script>

		if ( WEBGL.isWebGLAvailable() === false ) {

			document.body.appendChild( WEBGL.getWebGLErrorMessage() );

		}

		var container;
		var camera, scene, renderer, mesh;
		var offsetAttribute, orientationAttribute;


		init();
		animate();

		function init() {

			container = document.getElementById( 'container' );

			camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );

			scene = new THREE.Scene();
			scene.background = new THREE.Color( 0x101010 );

			// geometry

			var shuliang = 30;

			var bufferGeometry = new THREE.BoxBufferGeometry( 2, 2, 2 );

			var geometry = new THREE.InstancedBufferGeometry();
			geometry.index = bufferGeometry.index;
			// geometry.attributes.position = bufferGeometry.attributes.position;
			/* UV 數據
			   前面的學習中瞭解到每個原始正方形平面由兩個三角形組成,
			   所以每一面都有兩組UV數據,每一組對應一個三角形
			 x, y, z, w
			 0, 1, 1, 1, // 面1-1 UV
			 0, 0, 1, 0, // 面1-2 UV

			 0, 1, 1, 1, // 面2-1 UV
			 0, 0, 1, 0, // 面2-2 UV

			 0, 1, 1, 1, // 面3-1 UV
			 0, 0, 1, 0, // 面3-2 UV

			 0, 1, 1, 1, // 面4-1 UV
			 0, 0, 1, 0, // 面4-2 UV

			 0, 1, 1, 1, // 面5-1 UV
			 0, 0, 1, 0, // 面5-2 UV

			 0, 1, 1, 1, // 面6-1 UV
			 0, 0, 1, 0  // 面6-2 UV
			 */
			// geometry.attributes.uv = bufferGeometry.attributes.uv;

			// Box位置
			var offsets = getOffsets();
			
			// Box轉向角度
			var orientations = getOrientations();

			offsetAttribute = new THREE.InstancedBufferAttribute( new Float32Array( offsets ), 3 );
			orientationAttribute = new THREE.InstancedBufferAttribute( new Float32Array( orientations ), 4 ).setDynamic( true );
			geometry.addAttribute( 'position', bufferGeometry.attributes.position ); // position又是Threejs的關鍵詞,需要保留
			geometry.addAttribute( 'jinold_position', bufferGeometry.attributes.position );
			geometry.addAttribute( 'jinold_uv', bufferGeometry.attributes.uv );
			geometry.addAttribute( 'jinold_offset', offsetAttribute );
			geometry.addAttribute( 'jinold_orientation', orientationAttribute );

			// material
			var material = new THREE.RawShaderMaterial( {

				uniforms: {
					map: { value: new THREE.TextureLoader().load( 'textures/brick_diffuse.jpg' ) }
				},
				vertexShader: document.getElementById( 'vertexShader' ).textContent,
				fragmentShader: document.getElementById( 'fragmentShader' ).textContent

			} );

			mesh = new THREE.Mesh( geometry, material );
			scene.add( mesh );
			
			/*
			var geometry = new THREE.BoxBufferGeometry(1, 1, 1); // 創建一個長方體,用來定義物體的形狀
			var material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); // 創建一個材質,用來定義物體的顏色
			var mesh = new THREE.Mesh(geometry, material); // 使用形狀和素材,來定義物體
			scene.add(mesh);
			*/
			renderer = new THREE.WebGLRenderer();
			renderer.setPixelRatio( window.devicePixelRatio );
			renderer.setSize( window.innerWidth, window.innerHeight );
			container.appendChild( renderer.domElement );

			window.addEventListener( 'resize', onWindowResize, false );

		}
		function getOffsets() {
			var offsets = [];
			var x, y, z;
			/*
			 * vector
			 */
			var vector = new THREE.Vector4();
			

			x = 0;
			y = 0;
			z = -5;
			vector.set( x, y, z, 0 ).normalize();
			//vector.multiplyScalar( 5 ); // move out at least 5 units from center in current direction
			/*
			 * 從當前方向的中心向外移動至少5個單位
			 * multiplyScalar越大,物體離中心點越遠,物體看起來越來越小
			 */
			vector.multiplyScalar( 1 );
			
			offsets.push( x + vector.x, y + vector.y, z + vector.z );
			
			return offsets
		}
		function getOrientations() {
			var x, y, z, w;
			var orientations = [];

			/*
			 * vector
			 */
			var vector = new THREE.Vector4();
			
			// orientations
			x = Math.random();
			y = Math.random();
			z = Math.random();
			w = Math.random();
			
			
			vector.set( x, y, z, w ).normalize();

			orientations.push( vector.x, vector.y, vector.z, vector.w );
			return orientations
		}
		function onWindowResize( event ) {

			camera.aspect = window.innerWidth / window.innerHeight;
			// 更新相機投影矩陣,必須在參數發生變化後調用。
			camera.updateProjectionMatrix();

			renderer.setSize( window.innerWidth, window.innerHeight );

		}
		
		function animate() {

			requestAnimationFrame( animate );

			render();

		}

		function render() {

			renderer.render( scene, camera );

		}

	</script>

</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章