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.
		
		
		
		
		
			
		
			
				
					
					
						
							272 lines
						
					
					
						
							6.6 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							272 lines
						
					
					
						
							6.6 KiB
						
					
					
				| <!DOCTYPE html> | |
| <html lang="en"> | |
| 	<head> | |
| 		<title>three.js webgl - Multiple Render Targets</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"> | |
| 
 | |
| 		<!-- Write to G-Buffer --> | |
| 		<script id="gbuffer-vert" type="x-shader/x-vertex"> | |
| 			in vec3 position; | |
| 			in vec3 normal; | |
| 			in vec2 uv; | |
| 
 | |
| 			out vec3 vNormal; | |
| 			out vec2 vUv; | |
| 
 | |
| 			uniform mat4 modelViewMatrix; | |
| 			uniform mat4 projectionMatrix; | |
| 			uniform mat3 normalMatrix; | |
| 
 | |
| 			void main() { | |
| 
 | |
| 				vUv = uv; | |
| 
 | |
| 				// get smooth normals | |
| 				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); | |
| 
 | |
| 				vec3 transformedNormal = normalMatrix * normal; | |
| 				vNormal = normalize( transformedNormal ); | |
| 
 | |
| 				gl_Position = projectionMatrix * mvPosition; | |
| 
 | |
| 			} | |
| 		</script> | |
| 		<script id="gbuffer-frag" type="x-shader/x-fragment"> | |
| 			precision highp float; | |
| 			precision highp int; | |
| 
 | |
| 			layout(location = 0) out vec4 gColor; | |
| 			layout(location = 1) out vec4 gNormal; | |
| 
 | |
| 			uniform sampler2D tDiffuse; | |
| 			uniform vec2 repeat; | |
| 
 | |
| 			in vec3 vNormal; | |
| 			in vec2 vUv; | |
| 
 | |
| 			void main() { | |
| 
 | |
| 				// write color to G-Buffer | |
| 				gColor = texture( tDiffuse, vUv * repeat ); | |
| 
 | |
| 				// write normals to G-Buffer | |
| 				gNormal = vec4( normalize( vNormal ), 0.0 ); | |
| 
 | |
| 			} | |
| 		</script> | |
| 
 | |
| 		<!-- Read G-Buffer and render to screen --> | |
| 		<script id="render-vert" type="x-shader/x-vertex"> | |
| 			in vec3 position; | |
| 			in vec2 uv; | |
| 
 | |
| 			out vec2 vUv; | |
| 
 | |
| 			uniform mat4 modelViewMatrix; | |
| 			uniform mat4 projectionMatrix; | |
| 
 | |
| 			void main() { | |
| 
 | |
| 				vUv = uv; | |
| 				gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); | |
| 
 | |
| 			} | |
| 		</script> | |
| 		<script id="render-frag" type="x-shader/x-fragment"> | |
| 			precision highp float; | |
| 			precision highp int; | |
| 
 | |
| 			layout(location = 0) out vec4 pc_FragColor; | |
| 
 | |
| 			in vec2 vUv; | |
| 
 | |
| 			uniform sampler2D tDiffuse; | |
| 			uniform sampler2D tNormal; | |
| 
 | |
| 			void main() { | |
| 
 | |
| 				vec3 diffuse = texture( tDiffuse, vUv ).rgb; | |
| 				vec3 normal = texture( tNormal, vUv ).rgb; | |
| 
 | |
| 				pc_FragColor.rgb = mix( diffuse, normal, step( 0.5, vUv.x ) ); | |
| 				pc_FragColor.a = 1.0; | |
| 
 | |
| 			} | |
| 		</script> | |
| 
 | |
| 	</head> | |
| 	<body> | |
| 		<div id="info"> | |
| 			<a href="http://threejs.org" target="_blank">threejs</a> webgl - Multiple RenderTargets | |
| 		</div> | |
| 
 | |
| 		<!-- 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'; | |
| 			import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; | |
| 			import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; | |
| 
 | |
| 			let camera, scene, renderer, controls; | |
| 			let renderTarget; | |
| 			let postScene, postCamera; | |
| 
 | |
| 			const parameters = { | |
| 				samples: 4, | |
| 				wireframe: false | |
| 			}; | |
| 
 | |
| 			const gui = new GUI(); | |
| 			gui.add( parameters, 'samples', 0, 4 ).step( 1 ); | |
| 			gui.add( parameters, 'wireframe' ); | |
| 			gui.onChange( render ); | |
| 
 | |
| 			init(); | |
| 
 | |
| 			function init() { | |
| 
 | |
| 				if ( WebGL.isWebGL2Available() === false ) { | |
| 
 | |
| 					document.body.appendChild( WebGL.getWebGL2ErrorMessage() ); | |
| 					return; | |
| 
 | |
| 				} | |
| 
 | |
| 				renderer = new THREE.WebGLRenderer(); | |
| 				renderer.setPixelRatio( window.devicePixelRatio ); | |
| 				renderer.setSize( window.innerWidth, window.innerHeight ); | |
| 				document.body.appendChild( renderer.domElement ); | |
| 
 | |
| 				// Create a multi render target with Float buffers | |
|  | |
| 				renderTarget = new THREE.WebGLMultipleRenderTargets( | |
| 					window.innerWidth * window.devicePixelRatio, | |
| 					window.innerHeight * window.devicePixelRatio, | |
| 					2 | |
| 				); | |
| 
 | |
| 				for ( let i = 0, il = renderTarget.texture.length; i < il; i ++ ) { | |
| 
 | |
| 					renderTarget.texture[ i ].minFilter = THREE.NearestFilter; | |
| 					renderTarget.texture[ i ].magFilter = THREE.NearestFilter; | |
| 
 | |
| 				} | |
| 
 | |
| 				// Name our G-Buffer attachments for debugging | |
|  | |
| 				renderTarget.texture[ 0 ].name = 'diffuse'; | |
| 				renderTarget.texture[ 1 ].name = 'normal'; | |
| 
 | |
| 				// Scene setup | |
|  | |
| 				scene = new THREE.Scene(); | |
| 				scene.background = new THREE.Color( 0x222222 ); | |
| 
 | |
| 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 50 ); | |
| 				camera.position.z = 4; | |
| 
 | |
| 				const loader = new THREE.TextureLoader(); | |
| 
 | |
| 				const diffuse = loader.load( 'textures/hardwood2_diffuse.jpg', render ); | |
| 				diffuse.wrapS = THREE.RepeatWrapping; | |
| 				diffuse.wrapT = THREE.RepeatWrapping; | |
| 
 | |
| 				scene.add( new THREE.Mesh( | |
| 					new THREE.TorusKnotGeometry( 1, 0.3, 128, 32 ), | |
| 					new THREE.RawShaderMaterial( { | |
| 						vertexShader: document.querySelector( '#gbuffer-vert' ).textContent.trim(), | |
| 						fragmentShader: document.querySelector( '#gbuffer-frag' ).textContent.trim(), | |
| 						uniforms: { | |
| 							tDiffuse: { value: diffuse }, | |
| 							repeat: { value: new THREE.Vector2( 5, 0.5 ) } | |
| 						}, | |
| 						glslVersion: THREE.GLSL3 | |
| 					} ) | |
| 				) ); | |
| 
 | |
| 				// PostProcessing setup | |
|  | |
| 				postScene = new THREE.Scene(); | |
| 				postCamera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); | |
| 
 | |
| 				postScene.add( new THREE.Mesh( | |
| 					new THREE.PlaneGeometry( 2, 2 ), | |
| 					new THREE.RawShaderMaterial( { | |
| 						vertexShader: document.querySelector( '#render-vert' ).textContent.trim(), | |
| 						fragmentShader: document.querySelector( '#render-frag' ).textContent.trim(), | |
| 						uniforms: { | |
| 							tDiffuse: { value: renderTarget.texture[ 0 ] }, | |
| 							tNormal: { value: renderTarget.texture[ 1 ] }, | |
| 						}, | |
| 						glslVersion: THREE.GLSL3 | |
| 					} ) | |
| 				) ); | |
| 
 | |
| 				// Controls | |
|  | |
| 				controls = new OrbitControls( camera, renderer.domElement ); | |
| 				controls.addEventListener( 'change', render ); | |
| 				//controls.enableZoom = false; | |
|  | |
| 				window.addEventListener( 'resize', onWindowResize ); | |
| 
 | |
| 			} | |
| 
 | |
| 			function onWindowResize() { | |
| 
 | |
| 				camera.aspect = window.innerWidth / window.innerHeight; | |
| 				camera.updateProjectionMatrix(); | |
| 
 | |
| 				renderer.setSize( window.innerWidth, window.innerHeight ); | |
| 
 | |
| 				const dpr = renderer.getPixelRatio(); | |
| 				renderTarget.setSize( window.innerWidth * dpr, window.innerHeight * dpr ); | |
| 
 | |
| 				render(); | |
| 
 | |
| 			} | |
| 
 | |
| 			function render() { | |
| 
 | |
| 				renderTarget.samples = parameters.samples; | |
| 
 | |
| 				scene.traverse( function ( child ) { | |
| 
 | |
| 					if ( child.material !== undefined ) { | |
| 
 | |
| 						child.material.wireframe = parameters.wireframe; | |
| 
 | |
| 					} | |
| 
 | |
| 				} ); | |
| 
 | |
| 				// render scene into target | |
| 				renderer.setRenderTarget( renderTarget ); | |
| 				renderer.render( scene, camera ); | |
| 
 | |
| 				// render post FX | |
| 				renderer.setRenderTarget( null ); | |
| 				renderer.render( postScene, postCamera ); | |
| 
 | |
| 			} | |
| 
 | |
| 		</script> | |
| 
 | |
| 	</body> | |
| </html>
 | |
| 
 |