Browse Source

Added deferred shading example with morph animation.

Started with extraction of deferred shading code snippets into more reusable components.
alteredq 13 năm trước cách đây
mục cha
commit
05e363b4a8

+ 4 - 4
build/three.js

@@ -10813,7 +10813,7 @@ THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, f
 	this.name = '';
 
 	this.image = image;
-	this.mipmaps = null;
+	this.mipmaps = [];
 
 	this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping();
 
@@ -10850,7 +10850,7 @@ THREE.Texture.prototype = {
 		if ( texture === undefined ) texture = new THREE.Texture();
 
 		texture.image = this.image;
-		texture.mipmaps = this.mipmaps;
+		texture.mipmaps = this.mipmaps.slice(0);
 
 		texture.mapping = this.mapping;
 
@@ -22253,7 +22253,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				// if there are no manual mipmaps
 				// set 0 level mipmap and then use GL to generate other mipmap levels
 
-				if ( mipmaps && isImagePowerOfTwo ) {
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
@@ -22288,7 +22288,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				// if there are no manual mipmaps
 				// set 0 level mipmap and then use GL to generate other mipmap levels
 
-				if ( mipmaps && isImagePowerOfTwo ) {
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 9 - 9
build/three.min.js


+ 434 - 0
examples/js/ShaderDeferred.js

@@ -0,0 +1,434 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author MPanknin / http://www.redplant.de/
+ *
+ */
+
+
+THREE.ShaderDeferred = {
+
+	"clipDepth" : {
+
+		uniforms: { },
+
+		fragmentShader : [
+
+			"varying vec4 clipPos;",
+
+			"void main() {",
+
+				"gl_FragColor = vec4( clipPos.z / clipPos.w, 1.0, 1.0, 1.0 );",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec4 clipPos;",
+
+			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+
+			"void main() {",
+
+				THREE.ShaderChunk[ "morphtarget_vertex" ],
+				THREE.ShaderChunk[ "default_vertex" ],
+
+				"clipPos = gl_Position;",
+
+			"}"
+
+		].join("\n")
+
+	},
+
+	"normals" : {
+
+		uniforms: { },
+
+		fragmentShader : [
+
+			"varying vec3 normalView;",
+
+			"void main() {",
+
+				"gl_FragColor = vec4( vec3( normalView * 0.5 + 0.5 ), 1.0 );",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec3 normalView;",
+
+			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+
+			"void main() {",
+
+				THREE.ShaderChunk[ "morphnormal_vertex" ],
+				THREE.ShaderChunk[ "morphtarget_vertex" ],
+				THREE.ShaderChunk[ "default_vertex" ],
+
+				"vec3 objectNormal;",
+
+				"#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )",
+
+					"objectNormal = morphedNormal;",
+
+				"#endif",
+
+				"#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )",
+
+					"objectNormal = normal;",
+
+				"#endif",
+
+				"normalView = normalize( normalMatrix * objectNormal );",
+
+			"}"
+
+		].join("\n")
+
+	},
+
+	"bump" : {
+
+		uniforms: {
+
+			bumpMap: 	  { type: "t", value: null },
+			bumpScale:	  { type: "f", value: 1 },
+			offsetRepeat: { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }
+
+		},
+
+		fragmentShader : [
+
+			"#extension GL_OES_standard_derivatives : enable\n",
+
+			"varying vec3 normalView;",
+			"varying vec2 vUv;",
+			"varying vec3 vViewPosition;",
+
+			"uniform sampler2D bumpMap;",
+			"uniform float bumpScale;",
+
+			// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
+			//	http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
+
+			// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
+
+			"vec2 dHdxy_fwd() {",
+
+				"vec2 dSTdx = dFdx( vUv );",
+				"vec2 dSTdy = dFdy( vUv );",
+
+				"float Hll = bumpScale * texture2D( bumpMap, vUv ).x;",
+				"float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;",
+				"float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;",
+
+				"return vec2( dBx, dBy );",
+
+			"}",
+
+			"vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {",
+
+				"vec3 vSigmaX = dFdx( surf_pos );",
+				"vec3 vSigmaY = dFdy( surf_pos );",
+				"vec3 vN = surf_norm;",		// normalized
+
+				"vec3 R1 = cross( vSigmaY, vN );",
+				"vec3 R2 = cross( vN, vSigmaX );",
+
+				"float fDet = dot( vSigmaX, R1 );",
+
+				"vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );",
+				"return normalize( abs( fDet ) * surf_norm - vGrad );",
+
+			"}",
+
+			"void main() {",
+
+				"vec3 normal = normalize( normalView );",
+				"normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
+				"gl_FragColor = vec4( vec3( normal * 0.5 + 0.5 ), 1.0 );",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec3 normalView;",
+			"varying vec2 vUv;",
+			"varying vec3 vViewPosition;",
+
+			"uniform vec4 offsetRepeat;",
+
+			"void main() {",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"gl_Position = projectionMatrix * mvPosition;",
+				"normalView = normalize( normalMatrix * normal );",
+				"vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
+				"vViewPosition = -mvPosition.xyz;",
+
+			"}"
+
+		].join("\n")
+
+	},
+
+	"unlit" : {
+
+		uniforms: {
+
+			samplerDepth: { type: "t", value: null },
+			viewWidth:    { type: "f", value: 800 },
+			viewHeight:   { type: "f", value: 600 },
+			lightColor:   { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) }
+
+		},
+
+		fragmentShader : [
+
+			"varying vec4 clipPos;",
+			"uniform sampler2D samplerDepth;",
+
+			"uniform float viewHeight;",
+			"uniform float viewWidth;",
+
+			"uniform vec3 lightColor;",
+
+			"void main() {",
+
+				"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
+				"float z = texture2D( samplerDepth, texCoord ).x;",
+				"vec4 color = vec4( lightColor, 1.0 );",
+				"float depth = clipPos.z / clipPos.w;",
+				"if( depth > z && z > 0.0 ) color.w = 0.0;",
+				"gl_FragColor = color;",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec4 clipPos;",
+
+			"void main() {",
+
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"clipPos = gl_Position;",
+
+			"}"
+
+		].join("\n")
+
+	},
+
+	"composite" : {
+
+		uniforms: {
+
+			samplerLightBuffer: { type: "t", value: null },
+			samplerEmitter: 	{ type: "t", value: null }
+
+		},
+
+		fragmentShader : [
+
+			"varying vec2 texCoord;",
+			"uniform sampler2D samplerLightBuffer;",
+			"uniform sampler2D samplerEmitter;",
+			"uniform vec3 lightPos;",
+
+			"void main() {",
+
+				"vec3 color = texture2D( samplerLightBuffer, texCoord ).xyz;",
+				"vec3 emitter = texture2D( samplerEmitter, texCoord ).xyz;",
+
+				"if ( emitter != vec3( 0.0 ) ) {",
+
+					"gl_FragColor = vec4( emitter, 1.0 );",
+
+				"} else {",
+
+					"gl_FragColor = vec4( sqrt( color ), 1.0 );",
+
+				"}",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec2 texCoord;",
+
+			"void main() {",
+
+				"vec4 pos = vec4( sign( position.xy ), 0.0, 1.0 );",
+				"texCoord = pos.xy * vec2( 0.5 ) + 0.5;",
+				"gl_Position = pos;",
+
+			"}"
+
+		].join("\n")
+
+	},
+
+	"light" : {
+
+		uniforms: {
+
+			samplerLightBuffer: { type: "t", value: null },
+			samplerNormals: { type: "t", value: null },
+			samplerDepth: 	{ type: "t", value: null },
+			samplerColor: 	{ type: "t", value: null },
+			matView: 		{ type: "m4", value: new THREE.Matrix4() },
+			matProjInverse: { type: "m4", value: new THREE.Matrix4() },
+			viewWidth: 		{ type: "f", value: 800 },
+			viewHeight: 	{ type: "f", value: 600 },
+			lightPos: 		{ type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
+			lightColor: 	{ type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
+			lightIntensity: { type: "f", value: 1.0 },
+			lightRadius: 	{ type: "f", value: 1.0 }
+
+		},
+
+		fragmentShader : [
+
+			"varying vec3 lightView;",
+			"varying vec4 clipPos;",
+
+			"uniform sampler2D samplerColor;",
+			"uniform sampler2D samplerDepth;",
+			"uniform sampler2D samplerNormals;",
+			"uniform sampler2D samplerLightBuffer;",
+
+			"uniform float lightRadius;",
+			"uniform float lightIntensity;",
+			"uniform float viewHeight;",
+			"uniform float viewWidth;",
+
+			"uniform vec3 lightColor;",
+
+			"uniform mat4 matProjInverse;",
+
+			"void main() {",
+
+				"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
+
+				"float z = texture2D( samplerDepth, texCoord ).x;",
+				"float lightZ = clipPos.z / clipPos.w;",
+
+				/*
+				"if ( z == 0.0 ) {",
+
+					"gl_FragColor = vec4( vec3( 0.0 ), 1.0 );",
+					"return;",
+
+				"}",
+				*/
+
+				"if ( z == 0.0 || lightZ > z ) discard;",
+
+				"float x = texCoord.x * 2.0 - 1.0;",
+				"float y = texCoord.y * 2.0 - 1.0;",
+
+				"vec4 projectedPos = vec4( x, y, z, 1.0 );",
+
+				"vec4 viewPos = matProjInverse * projectedPos;",
+				"viewPos.xyz /= viewPos.w;",
+				"viewPos.w = 1.0;",
+
+				"vec3 lightDir = lightView - viewPos.xyz;",
+				"float dist = length( lightDir );",
+
+				"if ( dist > lightRadius ) discard;",
+
+				"lightDir = normalize( lightDir );",
+
+				"float cutoff = 0.3;",
+				"float denom = dist/lightRadius + 1.0;",
+				"float attenuation = 1.0 / ( denom * denom );",
+				"attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );",
+				"attenuation = max( attenuation, 0.0 );",
+				"attenuation *= attenuation;",
+
+				"vec3 normal = texture2D( samplerNormals, texCoord ).xyz * 2.0 - 1.0;",
+
+				// wrap around lighting
+
+				"float diffuseFull = max( dot( normal, lightDir ), 0.0 );",
+				"float diffuseHalf = max( 0.5 + 0.5 * dot( normal, lightDir ), 0.0 );",
+
+				"const vec3 wrapRGB = vec3( 0.6, 0.2, 0.2 );",
+				"vec3 diffuse = mix( vec3 ( diffuseFull ), vec3( diffuseHalf ), wrapRGB );",
+
+				// simple lighting
+
+				//"float diffuseFull = max( dot( normal, lightDir ), 0.0 );",
+				//"vec3 diffuse = vec3 ( diffuseFull );",
+
+				// specular
+
+				"const float shininess = 75.0;",
+				"const float specularIntensity = 0.4;",
+
+				"vec3 halfVector = normalize( lightDir - normalize( viewPos.xyz ) );",
+				"float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );",
+
+				// simple specular
+
+				//"vec3 specular = specularIntensity * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;",
+
+				// physically based specular
+
+				"vec3 specularColor = specularIntensity * vec3( 0.312 );",
+
+				"float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
+
+				"vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightDir, halfVector ), 5.0 );",
+				"vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse * specularNormalization;",
+
+				// color
+
+				"vec4 albedo = texture2D( samplerColor, texCoord );",
+
+				// combine
+
+				"vec4 color = vec4( 0.0 );",
+				"color.xyz = albedo.xyz * lightColor * lightIntensity;",
+				"color.w = attenuation;",
+				//"gl_FragColor = color * vec4( diffuse + specular, 1.0 );",
+				"gl_FragColor = color * vec4( diffuse, 1.0 ) + vec4( lightColor * lightIntensity * specular, attenuation );",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader : [
+
+			"varying vec3 lightView;",
+			"varying vec4 clipPos;",
+			"uniform vec3 lightPos;",
+			"uniform mat4 matView;",
+
+			"void main() { ",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"gl_Position = projectionMatrix * mvPosition;",
+				"lightView = vec3( matView * vec4( lightPos, 1.0 ) );",
+				"clipPos = gl_Position;",
+
+			"}"
+
+		].join("\n")
+
+	}
+
+
+};

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 43 - 0
examples/models/animated/elderlyWalk.js


+ 826 - 0
examples/webgl_lights_deferred_morphs.html

@@ -0,0 +1,826 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js webgl - deferred rendering [morphs]</title>
+		<meta charset="utf-8" />
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 20px; width: 100%;
+				color: #ffffff;
+				padding: 5px;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+			}
+
+			a {
+				color: #ff0080;
+				text-decoration: none;
+			}
+
+			a:hover {
+				color: #0080ff;
+			}
+
+			#stats { position: absolute; top:10px; left: 5px }
+			#stats #fps { background: transparent !important }
+			#stats #fps #fpsText { color: #aaa !important }
+			#stats #fps #fpsGraph { display: none }
+		</style>
+	</head>
+
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - webgl deferred rendering with morph animation -
+			character from <a href="http://www.sintel.org/">Sintel</a>
+		</div>
+		<div id="container"></div>
+
+
+		<script src="js/libs/stats.min.js"></script>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+
+		<script src="js/ShaderDeferred.js"></script>
+
+		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/FXAAShader.js"></script>
+		<script src="js/shaders/ColorCorrectionShader.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+
+		<script src="js/controls/TrackballControls.js"></script>
+
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var SCALE = 0.75;
+			var MARGIN = 100;
+
+			var WIDTH = window.innerWidth;
+			var HEIGHT = window.innerHeight - 2 * MARGIN;
+
+			var NEAR = 1.0, FAR = 350.0;
+			var VIEW_ANGLE = 45;
+			var ASPECT = WIDTH / HEIGHT;
+
+			var mouseX = 0;
+			var mouseY = 0;
+
+			var targetX = 0, targetY = 0;
+			var angle = 0;
+			var target = new THREE.Vector3( 0, 0, 0 );
+
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			// core
+
+			var renderer, camera, controls, stats, clock;
+
+			// scenes and scene nodes
+
+			var lightScene, lightNode, scene, sceneNode, emitterScene, emitterNode, quadScene, quadNode;
+
+			// rendertargets
+
+			var rtColor, rtNormals, rtDepth, rtLightBuffer, rtEmitter, rtFinal;
+
+			// composer
+
+			var compColor, compNormals, compDepth, compLightBuffer, compFinal, compEmitter, compositePass;
+			var effectFXAA;
+
+			// materials
+
+			var normalShader, bumpShader, clipDepthShader, lightShader, unlitShader, compositeShader;
+			var matNormal, matClipDepth, matBasic, matUnlit;
+
+			// lights
+
+			var numLights = 50;
+			var lights = new Array();
+
+			// morphs
+
+			var morphs = [];
+
+			// -----------------------------
+
+			function bootstrap() {
+
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setSize( WIDTH, HEIGHT );
+				renderer.setClearColorHex( 0x000000, 1 );
+
+				renderer.domElement.style.position = "absolute";
+				renderer.domElement.style.top = MARGIN + "px";
+				renderer.domElement.style.left = "0px";
+
+				var container = document.getElementById( 'container' );
+				container.appendChild( renderer.domElement );
+
+				// scene camera
+
+				camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
+				camera.position.z = 150;
+
+				controls = new THREE.TrackballControls( camera, renderer.domElement );
+
+				// scene for walt's head model
+
+				scene = new THREE.Scene();
+				sceneNode = new THREE.Object3D();
+				scene.add( sceneNode );
+				scene.add( camera );
+
+				// scene for light proxy geometry
+
+				lightScene = new THREE.Scene();
+				lightNode = new THREE.Object3D();
+				lightScene.add( lightNode );
+
+				// scene for the coloured emitter spheres
+
+				emitterScene = new THREE.Scene();
+				emitterNode = new THREE.Object3D();
+				emitterScene.add( emitterNode );
+
+				// full screen quad for compositing
+
+				quadScene = new THREE.Scene();
+				quadNode = new THREE.Object3D();
+				quadScene.add( quadNode );
+				quadNode.add( new THREE.Mesh( new THREE.PlaneGeometry( 1, 1 ) ) );
+
+				// stats
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '8px';
+				stats.domElement.style.zIndex = 100;
+				container.appendChild( stats.domElement );
+
+				// clock
+
+				clock = new THREE.Clock();
+
+			}
+
+			// -----------------------------
+
+			function createRenderTargets() {
+
+				var rtParamsFloat = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
+							          format: THREE.RGBAFormat, type: THREE.FloatType };
+
+				var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
+							          format: THREE.RGBFormat, type: THREE.UnsignedByteType };
+
+				// ----------------------------------------------------------
+				// g-buffer
+				// ----------------------------------------------------------
+
+				rtNormals = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsFloat );
+				rtDepth = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsFloat );
+				rtColor = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsUByte );
+				rtFinal = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsUByte );
+
+				rtNormals.generateMipmaps = false;
+				rtDepth.generateMipmaps = false;
+				rtColor.generateMipmaps = false;
+				rtFinal.generateMipmaps = false;
+
+				var passNormals = new THREE.RenderPass( scene, camera );
+				compNormals = new THREE.EffectComposer( renderer, rtNormals );
+				compNormals.addPass( passNormals );
+
+				var passDepth = new THREE.RenderPass( scene, camera );
+				compDepth = new THREE.EffectComposer( renderer, rtDepth );
+				compDepth.addPass( passDepth );
+
+				var passColor = new THREE.RenderPass( scene, camera );
+				compColor = new THREE.EffectComposer( renderer, rtColor );
+				compColor.addPass( passColor );
+
+				// ----------------------------------------------------------
+				// light emitter spheres
+				// ----------------------------------------------------------
+
+				var emitterPass = new THREE.RenderPass( emitterScene, camera );
+				rtEmitter = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsUByte );
+				rtEmitter.generateMipmaps = false;
+
+				compEmitter = new THREE.EffectComposer( renderer, rtEmitter );
+				compEmitter.addPass( emitterPass );
+
+				// ----------------------------------------------------------
+				// lighting pass
+				// ----------------------------------------------------------
+
+				rtLightBuffer = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsFloat );
+				rtLightBuffer.generateMipmaps = false;
+
+				var passLight = new THREE.RenderPass( lightScene, camera );
+				compLightBuffer = new THREE.EffectComposer( renderer, rtLightBuffer );
+				compLightBuffer.addPass( passLight );
+
+				lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
+				lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
+				lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
+				lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLightBuffer;
+
+				var geomEmitter = new THREE.SphereGeometry( 0.7, 7, 7 );
+
+				for ( var x = 0; x < numLights; x ++ ) {
+
+					var light = lights[ x ];
+
+					// setup material
+
+					var matLight = new THREE.ShaderMaterial({
+
+						uniforms:       THREE.UniformsUtils.clone( lightShader.uniforms ),
+						vertexShader:   lightShader.vertexShader,
+						fragmentShader: lightShader.fragmentShader
+
+					});
+
+					matLight.blending = THREE.AdditiveBlending;
+					matLight.transparent = true;
+					matLight.depthWrite = false;
+					matLight.uniforms[ "lightPos" ].value = light.position;
+					matLight.uniforms[ "lightRadius" ].value = light.distance;
+					matLight.uniforms[ "lightIntensity" ].value = light.intensity;
+					matLight.uniforms[ "lightColor" ].value = light.color;
+
+					// setup proxy geometry for this light
+
+					var geomLight = new THREE.SphereGeometry( light.distance, 16, 8 );
+					var meshLight = new THREE.Mesh( geomLight, matLight );
+					lightNode.add( meshLight );
+
+					// create emitter sphere
+
+					var matEmitter = new THREE.ShaderMaterial({
+
+						uniforms:       THREE.UniformsUtils.clone( unlitShader.uniforms ),
+						vertexShader:   unlitShader.vertexShader,
+						fragmentShader: unlitShader.fragmentShader
+
+					});
+
+					var meshEmitter = new THREE.Mesh( geomEmitter, matEmitter );
+					meshEmitter.position = light.position;
+					emitterNode.add( meshEmitter );
+
+					// add emitter to light node
+
+					meshLight.emitter = meshEmitter;
+
+				}
+
+				// ----------------------------------------------------------
+				// composite
+				// ----------------------------------------------------------
+
+				compositeShader.uniforms[ 'samplerLightBuffer' ].value = compLightBuffer.renderTarget2;
+				compositeShader.uniforms[ 'samplerEmitter' ].value = compEmitter.renderTarget2;
+
+				compositePass = new THREE.ShaderPass( compositeShader );
+				compositePass.needsSwap = true;
+
+				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / ( SCALE * WIDTH ), 1 / ( SCALE * HEIGHT ) );
+
+				var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
+				effectColor.renderToScreen = true;
+				effectColor.uniforms[ 'powRGB' ].value.set( 1, 1, 1 );
+				effectColor.uniforms[ 'mulRGB' ].value.set( 2, 2, 2 );
+
+				compFinal = new THREE.EffectComposer( renderer, rtFinal );
+				compFinal.addPass( compositePass );
+				compFinal.addPass( effectFXAA );
+				compFinal.addPass( effectColor );
+
+			}
+
+			// -----------------------------
+
+			function initScene( object, y, scale ) {
+
+				var shader = THREE.ShaderLib[ "basic" ];
+
+				object.traverse( function( node ) {
+
+					if ( node.material ) {
+
+						// color material
+
+						var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+						var defines = { "USE_MAP": !!node.material.map, "GAMMA_INPUT": true };
+
+						var material = new THREE.ShaderMaterial( {
+
+							fragmentShader: shader.fragmentShader,
+							vertexShader: 	shader.vertexShader,
+							uniforms: 		uniforms,
+							defines: 		defines,
+							shading:		node.material.shading
+
+						} );
+
+						uniforms.diffuse.value.copy( node.material.color );
+						uniforms.map.value = node.material.map;
+
+						material.vertexColors = node.material.vertexColors;
+						material.morphTargets = node.material.morphTargets;
+						material.morphNormals = node.material.morphNormals;
+
+						if ( node.material.bumpMap ) {
+
+							var offset = node.material.bumpMap.offset;
+							var repeat = node.material.bumpMap.repeat;
+
+							uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
+
+						}
+
+						if ( node.material.transparent ) {
+
+							material.alphaTest = 0.1;
+
+						}
+
+						if ( node.material.name === "eyetrans" ) {
+
+							material.visible = false;
+
+						}
+
+						node.properties.colorMaterial = material;
+
+						// normal material
+
+						if ( node.material.bumpMap ) {
+
+							var uniforms = THREE.UniformsUtils.clone( bumpShader.uniforms );
+
+							var normalMaterial = new THREE.ShaderMaterial( {
+
+								uniforms: 		uniforms,
+								vertexShader: 	bumpShader.vertexShader,
+								fragmentShader: bumpShader.fragmentShader
+
+							} );
+
+							uniforms.bumpMap.value = node.material.bumpMap;
+							uniforms.bumpScale.value = node.material.bumpScale;
+
+							var offset = node.material.bumpMap.offset;
+							var repeat = node.material.bumpMap.repeat;
+
+							uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
+
+							node.properties.normalMaterial = normalMaterial;
+
+						} else if ( node.material.morphTargets ) {
+
+							var normalMaterial = new THREE.ShaderMaterial( {
+
+								uniforms:       THREE.UniformsUtils.clone( normalShader.uniforms ),
+								vertexShader:   normalShader.vertexShader,
+								fragmentShader: normalShader.fragmentShader,
+								shading:		node.material.shading
+
+							} );
+
+							normalMaterial.morphTargets = node.material.morphTargets;
+							normalMaterial.morphNormals = node.material.morphNormals;
+							node.properties.normalMaterial = normalMaterial;
+
+						} else {
+
+							node.properties.normalMaterial = matNormal;
+
+						}
+
+						// depth material
+
+						if ( node.material.morphTargets ) {
+
+							var depthMaterial = new THREE.ShaderMaterial({
+
+								uniforms:       THREE.UniformsUtils.clone( clipDepthShader.uniforms ),
+								vertexShader:   clipDepthShader.vertexShader,
+								fragmentShader: clipDepthShader.fragmentShader
+
+							});
+
+							depthMaterial.morphTargets = node.material.morphTargets;
+
+							node.properties.depthMaterial = depthMaterial;
+
+						} else {
+
+							node.properties.depthMaterial = matClipDepth;
+
+						}
+
+					}
+
+				} );
+
+				object.position.y = y;
+				object.scale.set( scale, scale, scale );
+				sceneNode.add( object );
+
+			}
+
+			// -----------------------------
+
+			function initMaterials() {
+
+				// -----------------------
+				// shader definitions
+				// -----------------------
+
+				normalShader = THREE.ShaderDeferred[ "normals" ];
+				bumpShader = THREE.ShaderDeferred[ "bump" ];
+				clipDepthShader = THREE.ShaderDeferred[ "clipDepth" ];
+				unlitShader = THREE.ShaderDeferred[ "unlit" ];
+				lightShader = THREE.ShaderDeferred[ "light" ];
+				compositeShader = THREE.ShaderDeferred[ "composite" ];
+
+				unlitShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
+				unlitShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+
+				lightShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
+				lightShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+
+				// -----------------------
+				// default materials
+				// -----------------------
+
+				matNormal = new THREE.ShaderMaterial( {
+
+					uniforms:       THREE.UniformsUtils.clone( normalShader.uniforms ),
+					vertexShader:   normalShader.vertexShader,
+					fragmentShader: normalShader.fragmentShader
+
+				} );
+
+				matClipDepth = new THREE.ShaderMaterial({
+
+					uniforms:       THREE.UniformsUtils.clone( clipDepthShader.uniforms ),
+					vertexShader:   clipDepthShader.vertexShader,
+					fragmentShader: clipDepthShader.fragmentShader
+
+				});
+
+			}
+
+			// -----------------------------
+
+			function initLights() {
+
+				var distance = 40;
+
+				// front light
+
+				var light = new THREE.PointLight();
+
+				light.color = new THREE.Vector3( 1, 1, 1 );
+				light.intensity = 1.5;
+				light.distance = 1.5 * distance;
+
+				lights.push( light );
+
+				// random lights
+
+				for ( var i = 1; i < numLights; i ++ ) {
+
+					var light = new THREE.PointLight();
+
+					light.color = new THREE.Vector3( Math.random(), Math.random(), Math.random() ).normalize();
+
+					// gamma to linear
+
+					light.color.x *= light.color.x;
+					light.color.y *= light.color.y;
+					light.color.z *= light.color.z;
+
+					light.intensity = 2.0;
+					light.distance = distance;
+
+					lights.push( light );
+
+				}
+
+			}
+
+			// -----------------------------
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = ( event.clientX - windowHalfX ) * 1;
+				mouseY = ( event.clientY - windowHalfY ) * 1;
+
+			}
+
+			// -----------------------------
+
+			function animate() {
+
+				var delta = clock.getDelta();
+
+				requestAnimationFrame( animate );
+
+				//controls.update( delta );
+
+				targetX = mouseX * .001;
+				targetY = mouseY * .001;
+
+				angle += 0.05 * ( targetX - angle );
+
+				camera.position.x = -Math.sin( angle ) * 150;
+				camera.position.z = Math.cos( angle ) * 150;
+
+				camera.lookAt( target );
+
+				for ( var i = 0; i < morphs.length; i ++ ) {
+
+					morph = morphs[ i ];
+					morph.updateAnimation( 1000 * delta );
+
+					morph.position.x += morph.properties.delta * delta;
+					if ( morph.position.x < -50 ) morph.position.x = 200;
+
+				}
+
+				stats.update();
+				render();
+
+			}
+
+			// -----------------------------
+
+			function render() {
+
+				// -----------------------------
+				// g-buffer color
+				// -----------------------------
+
+				sceneNode.traverse( function( node ) {
+
+					if ( node.material ) {
+
+						node.material = node.properties.colorMaterial;
+
+					}
+
+				} );
+
+				compColor.render();
+
+
+				// -----------------------------
+				// g-buffer depth
+				// -----------------------------
+
+				sceneNode.traverse( function( node ) {
+
+					if ( node.material ) {
+
+						node.material = node.properties.depthMaterial;
+
+					}
+
+				} );
+
+				compDepth.render();
+
+
+				// -----------------------------
+				// g-buffer normals
+				// -----------------------------
+
+				sceneNode.traverse( function( node ) {
+
+					if ( node.material ) {
+
+						node.material = node.properties.normalMaterial;
+
+					}
+
+				} );
+
+				compNormals.render();
+
+				// -----------------------------
+				// emitter pass
+				// -----------------------------
+
+				for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
+
+					var light = lightNode.children[ i ];
+					var color = light.material.uniforms[ "lightColor" ].value;
+
+					var emitter = light.emitter;
+					emitter.material.uniforms[ "samplerDepth" ].value = compDepth.renderTarget2;
+					emitter.material.uniforms[ "lightColor" ].value = color;
+
+				}
+
+				compEmitter.render();
+
+				// -----------------------------
+				// light pass
+				// -----------------------------
+
+				camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
+
+				for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
+
+					var uniforms = lightNode.children[ i ].material.uniforms;
+
+					uniforms[ "matProjInverse" ].value = camera.projectionMatrixInverse;
+					uniforms[ "matView" ].value = camera.matrixWorldInverse;
+
+				}
+
+				var time = Date.now() * 0.0005;
+
+				// update lights
+
+				var x, y, z;
+
+				for ( var i = 0; i < numLights; i ++ ) {
+
+					if ( i > 0 ) {
+
+						x = Math.sin( time + i * 1.7 ) * 80;
+						y = Math.cos( time + i * 1.5 ) * 40;
+						z = Math.cos( time + i * 1.3 ) * 30;
+
+					} else {
+
+						x = Math.sin( time * 3 ) * 20;
+						y = 15;
+						z = Math.cos( time * 3 ) * 25 + 10;
+
+					}
+
+					var light = lightNode.children[ i ];
+					var lightPosition = light.material.uniforms[ "lightPos" ].value;
+
+					lightPosition.x = x;
+					lightPosition.y = y;
+					lightPosition.z = z;
+
+					light.emitter.position = lightPosition;
+					light.position = lightPosition;
+					light.frustumCulled = false;
+
+				}
+
+				compLightBuffer.render();
+
+				// -----------------------------
+				// composite pass
+				// -----------------------------
+
+				compFinal.render( 0.1 );
+
+			}
+
+			function generateBox() {
+
+				var object = new THREE.Object3D();
+
+				var mapHeight2 = THREE.ImageUtils.loadTexture( "obj/lightmap/rocks.jpg" );
+				mapHeight2.repeat.set( 3, 1.5 );
+				mapHeight2.wrapS = mapHeight2.wrapT = THREE.RepeatWrapping;
+				mapHeight2.anisotropy = 4;
+				mapHeight2.format = THREE.RGBFormat;
+
+				var mapHeight3 = THREE.ImageUtils.loadTexture( "textures/water.jpg" );
+				mapHeight3.repeat.set( 16, 8 );
+				mapHeight3.wrapS = mapHeight3.wrapT = THREE.RepeatWrapping;
+				mapHeight3.anisotropy = 4;
+				mapHeight3.format = THREE.RGBFormat;
+
+				var geoPlane = new THREE.PlaneGeometry( 40, 20 );
+				var matPlane = new THREE.MeshPhongMaterial( { color: 0x000000, bumpMap: mapHeight2, bumpScale: 0.5 } );
+				var matPlane2 = new THREE.MeshPhongMaterial( { color: 0x000000, bumpMap: mapHeight3, bumpScale: 0.5 } );
+				var matPlane3 = new THREE.MeshPhongMaterial( { color: 0x000000, bumpMap: mapHeight3, bumpScale: 1 } );
+
+
+				// bottom
+
+				var mesh = new THREE.Mesh( geoPlane, matPlane2 );
+				mesh.position.z = -2;
+				mesh.position.y = -6;
+				mesh.rotation.x = -Math.PI/2;
+				object.add( mesh );
+
+				// top
+
+				var mesh = new THREE.Mesh( geoPlane, matPlane3 );
+				mesh.position.z = -2;
+				mesh.position.y = 7;
+				mesh.rotation.x = Math.PI/2;
+				object.add( mesh );
+
+				// back
+
+				var mesh = new THREE.Mesh( geoPlane, matPlane );
+				mesh.position.z = -4;
+				mesh.position.y = 0;
+				object.add( mesh );
+
+				// right
+
+				var mesh = new THREE.Mesh( geoPlane, matPlane );
+				mesh.position.z = 0;
+				mesh.position.y = 0;
+				mesh.position.x = 13;
+				mesh.rotation.y = -Math.PI/2;
+				//object.add( mesh );
+
+				// left
+
+				var mesh = new THREE.Mesh( geoPlane, matPlane );
+				mesh.position.z = 0;
+				mesh.position.y = 0;
+				mesh.position.x = -13;
+				mesh.rotation.y = Math.PI/2;
+				//object.add( mesh );
+
+				return object;
+
+			}
+
+			// -----------------------------
+			// entry point
+			// -----------------------------
+
+			bootstrap();
+			initMaterials();
+			initLights();
+			createRenderTargets();
+
+			// create animated model
+
+			var loader = new THREE.JSONLoader();
+			loader.load( "models/animated/elderlyWalk.js", function( geometry ) {
+
+				geometry.computeMorphNormals();
+
+				var material = new THREE.MeshPhongMaterial( { color: 0xffffff, morphTargets: true, morphNormals: true, vertexColors: THREE.NoColors, shading: THREE.FlatShading } );
+				var meshAnim = new THREE.MorphAnimMesh( geometry, material );
+
+				meshAnim.duration = 3000;
+				meshAnim.properties.delta = -13;
+
+				var s = 1;
+				meshAnim.scale.set( s, s, s );
+				meshAnim.position.x = 180;
+				meshAnim.position.z = -10;
+				meshAnim.rotation.y = -Math.PI/2;
+
+				morphs.push( meshAnim );
+
+				initScene( meshAnim, -48, 50 );
+
+			} );
+
+			// create box
+
+			var object = generateBox();
+			initScene( object, 0, 8 );
+
+			animate();
+
+			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+		</script>
+	</body>
+
+</html>

+ 1 - 0
utils/includes/examples.json

@@ -79,6 +79,7 @@
 	"../examples/js/ShaderSkin.js",
 	"../examples/js/ShaderTerrain.js",
 	"../examples/js/ShaderToon.js",
+	"../examples/js/ShaderDeferred.js",
 
 	"../examples/js/Sparks.js",
 	"../examples/js/UVsUtils.js",

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác