瀏覽代碼

Started to experiment with properties packing in geometry passes in deferred shading.

Using vec3 <=> float conversions from @benaadams

For the moment just testing how it works (had to fix blending in WebGLRenderer for this). Seems with two RGBA float passes we could eventually get quite decent material range.
alteredq 12 年之前
父節點
當前提交
c0fb64deff
共有 3 個文件被更改,包括 75 次插入40 次删除
  1. 26 1
      examples/js/ShaderDeferred.js
  2. 24 19
      examples/webgl_lights_deferred_morphs.html
  3. 25 20
      examples/webgl_lights_deferred_pointlights.html

+ 26 - 1
examples/js/ShaderDeferred.js

@@ -1,6 +1,7 @@
 /**
 /**
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/
  * @author MPanknin / http://www.redplant.de/
  * @author MPanknin / http://www.redplant.de/
+ * @author benaadams / http://blog.illyriad.co.uk/
  *
  *
  */
  */
 
 
@@ -30,6 +31,15 @@ THREE.ShaderDeferred = {
 			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "specularmap_pars_fragment" ],
 			THREE.ShaderChunk[ "specularmap_pars_fragment" ],
 
 
+			"const float unit = 255.0/256.0;",
+
+			"float vec3_to_float( vec3 data ) {",
+
+				"highp float compressed = fract( data.x * unit ) + floor( data.y * unit * 255.0 ) + floor( data.z * unit * 255.0 ) * 255.0;",
+				"return compressed;",
+
+			"}",
+
 			"void main() {",
 			"void main() {",
 
 
 				"gl_FragColor = vec4( diffuse, opacity );",
 				"gl_FragColor = vec4( diffuse, opacity );",
@@ -46,6 +56,9 @@ THREE.ShaderDeferred = {
 
 
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+				"gl_FragColor.x = vec3_to_float( 0.999 * gl_FragColor.xyz );",
+				"gl_FragColor.yzw = vec3( 0.0 );",
+
 			"}"
 			"}"
 
 
 		].join("\n"),
 		].join("\n"),
@@ -364,6 +377,17 @@ THREE.ShaderDeferred = {
 
 
 			"uniform mat4 matProjInverse;",
 			"uniform mat4 matProjInverse;",
 
 
+			"vec3 float_to_vec3( float data ) {",
+
+				"vec3 uncompressed;",
+				"uncompressed.x = fract( data );",
+				"float zInt = floor( data / 255.0 );",
+				"uncompressed.z = fract( zInt / 255.0 );",
+				"uncompressed.y = fract( floor( data - ( zInt * 255.0 ) ) / 255.0 );",
+				"return uncompressed;",
+
+			"}",
+
 			"void main() {",
 			"void main() {",
 
 
 				"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
 				"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
@@ -443,7 +467,8 @@ THREE.ShaderDeferred = {
 
 
 				// color
 				// color
 
 
-				"vec4 albedo = texture2D( samplerColor, texCoord );",
+				"vec4 colorMap = texture2D( samplerColor, texCoord );",
+				"vec3 albedo = float_to_vec3( abs( colorMap.x ) );",
 
 
 				// combine
 				// combine
 
 

+ 24 - 19
examples/webgl_lights_deferred_morphs.html

@@ -75,6 +75,9 @@
 			var WIDTH = window.innerWidth;
 			var WIDTH = window.innerWidth;
 			var HEIGHT = window.innerHeight - 2 * MARGIN;
 			var HEIGHT = window.innerHeight - 2 * MARGIN;
 
 
+			var SCALED_WIDTH = Math.floor( SCALE * WIDTH );
+			var SCALED_HEIGHT = Math.floor( SCALE * HEIGHT );
+
 			var NEAR = 1.0, FAR = 350.0;
 			var NEAR = 1.0, FAR = 350.0;
 			var VIEW_ANGLE = 45;
 			var VIEW_ANGLE = 45;
 			var ASPECT = WIDTH / HEIGHT;
 			var ASPECT = WIDTH / HEIGHT;
@@ -100,7 +103,7 @@
 
 
 			// rendertargets
 			// rendertargets
 
 
-			var rtColor, rtNormals, rtDepth, rtLightBuffer, rtEmitter, rtFinal;
+			var rtColor, rtNormals, rtDepth, rtLight, rtEmitter, rtFinal;
 
 
 			// composer
 			// composer
 
 
@@ -187,8 +190,11 @@
 
 
 			function createRenderTargets() {
 			function createRenderTargets() {
 
 
-				var rtParamsFloat = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
-							          format: THREE.RGBAFormat, type: THREE.FloatType };
+				var rtParamsFloatLinear = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
+										    format: THREE.RGBAFormat, type: THREE.FloatType };
+
+				var rtParamsFloatNearest = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
+											 format: THREE.RGBAFormat, type: THREE.FloatType };
 
 
 				var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
 				var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
 							          format: THREE.RGBFormat, type: THREE.UnsignedByteType };
 							          format: THREE.RGBFormat, type: THREE.UnsignedByteType };
@@ -197,14 +203,18 @@
 				// g-buffer
 				// 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 = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtDepth   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtColor   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatNearest );
+				rtLight   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtEmitter = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsUByte );
+				rtFinal   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsUByte );
 
 
 				rtNormals.generateMipmaps = false;
 				rtNormals.generateMipmaps = false;
 				rtDepth.generateMipmaps = false;
 				rtDepth.generateMipmaps = false;
 				rtColor.generateMipmaps = false;
 				rtColor.generateMipmaps = false;
+				rtLight.generateMipmaps = false;
+				rtEmitter.generateMipmaps = false;
 				rtFinal.generateMipmaps = false;
 				rtFinal.generateMipmaps = false;
 
 
 				var passNormals = new THREE.RenderPass( scene, camera );
 				var passNormals = new THREE.RenderPass( scene, camera );
@@ -224,8 +234,6 @@
 				// ----------------------------------------------------------
 				// ----------------------------------------------------------
 
 
 				var emitterPass = new THREE.RenderPass( emitterScene, camera );
 				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 = new THREE.EffectComposer( renderer, rtEmitter );
 				compEmitter.addPass( emitterPass );
 				compEmitter.addPass( emitterPass );
@@ -234,17 +242,14 @@
 				// lighting pass
 				// lighting pass
 				// ----------------------------------------------------------
 				// ----------------------------------------------------------
 
 
-				rtLightBuffer = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsFloat );
-				rtLightBuffer.generateMipmaps = false;
-
 				var passLight = new THREE.RenderPass( lightScene, camera );
 				var passLight = new THREE.RenderPass( lightScene, camera );
-				compLightBuffer = new THREE.EffectComposer( renderer, rtLightBuffer );
+				compLightBuffer = new THREE.EffectComposer( renderer, rtLight );
 				compLightBuffer.addPass( passLight );
 				compLightBuffer.addPass( passLight );
 
 
 				lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
 				lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
 				lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
 				lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
 				lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
 				lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
-				lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLightBuffer;
+				lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLight;
 
 
 				var geomEmitter = new THREE.SphereGeometry( 0.7, 7, 7 );
 				var geomEmitter = new THREE.SphereGeometry( 0.7, 7, 7 );
 
 
@@ -309,7 +314,7 @@
 				compositePass.needsSwap = true;
 				compositePass.needsSwap = true;
 
 
 				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
 				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
-				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / ( SCALE * WIDTH ), 1 / ( SCALE * HEIGHT ) );
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCALED_WIDTH, 1 / SCALED_HEIGHT );
 
 
 				var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
 				var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
 				effectColor.renderToScreen = true;
 				effectColor.renderToScreen = true;
@@ -470,11 +475,11 @@
 				lightShader = THREE.ShaderDeferred[ "light" ];
 				lightShader = THREE.ShaderDeferred[ "light" ];
 				compositeShader = THREE.ShaderDeferred[ "composite" ];
 				compositeShader = THREE.ShaderDeferred[ "composite" ];
 
 
-				unlitShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
-				unlitShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+				unlitShader.uniforms[ "viewWidth" ].value = SCALED_WIDTH;
+				unlitShader.uniforms[ "viewHeight" ].value = SCALED_HEIGHT;
 
 
-				lightShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
-				lightShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+				lightShader.uniforms[ "viewWidth" ].value = SCALED_WIDTH;
+				lightShader.uniforms[ "viewHeight" ].value = SCALED_HEIGHT;
 
 
 				// -----------------------
 				// -----------------------
 				// default materials
 				// default materials

+ 25 - 20
examples/webgl_lights_deferred_pointlights.html

@@ -78,6 +78,9 @@
 			var WIDTH = window.innerWidth;
 			var WIDTH = window.innerWidth;
 			var HEIGHT = window.innerHeight - 2 * MARGIN;
 			var HEIGHT = window.innerHeight - 2 * MARGIN;
 
 
+			var SCALED_WIDTH = Math.floor( SCALE * WIDTH );
+			var SCALED_HEIGHT = Math.floor( SCALE * HEIGHT );
+
 			var NEAR = 1.0, FAR = 350.0;
 			var NEAR = 1.0, FAR = 350.0;
 			var VIEW_ANGLE = 45;
 			var VIEW_ANGLE = 45;
 			var ASPECT = WIDTH / HEIGHT;
 			var ASPECT = WIDTH / HEIGHT;
@@ -103,7 +106,7 @@
 
 
 			// rendertargets
 			// rendertargets
 
 
-			var rtColor, rtNormals, rtDepth, rtLightBuffer, rtEmitter, rtFinal;
+			var rtColor, rtNormals, rtDepth, rtLight, rtEmitter, rtFinal;
 
 
 			// composer
 			// composer
 
 
@@ -186,8 +189,11 @@
 
 
 			function createRenderTargets() {
 			function createRenderTargets() {
 
 
-				var rtParamsFloat = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
-							          format: THREE.RGBAFormat, type: THREE.FloatType };
+				var rtParamsFloatLinear = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
+										    format: THREE.RGBAFormat, type: THREE.FloatType };
+
+				var rtParamsFloatNearest = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
+											 format: THREE.RGBAFormat, type: THREE.FloatType };
 
 
 				var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
 				var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
 							          format: THREE.RGBFormat, type: THREE.UnsignedByteType };
 							          format: THREE.RGBFormat, type: THREE.UnsignedByteType };
@@ -196,14 +202,18 @@
 				// g-buffer
 				// 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 = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtDepth   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtColor   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatNearest );
+				rtLight   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsFloatLinear );
+				rtEmitter = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsUByte );
+				rtFinal   = new THREE.WebGLRenderTarget( SCALED_WIDTH, SCALED_HEIGHT, rtParamsUByte );
 
 
 				rtNormals.generateMipmaps = false;
 				rtNormals.generateMipmaps = false;
 				rtDepth.generateMipmaps = false;
 				rtDepth.generateMipmaps = false;
 				rtColor.generateMipmaps = false;
 				rtColor.generateMipmaps = false;
+				rtLight.generateMipmaps = false;
+				rtEmitter.generateMipmaps = false;
 				rtFinal.generateMipmaps = false;
 				rtFinal.generateMipmaps = false;
 
 
 				var passNormals = new THREE.RenderPass( scene, camera );
 				var passNormals = new THREE.RenderPass( scene, camera );
@@ -223,8 +233,6 @@
 				// ----------------------------------------------------------
 				// ----------------------------------------------------------
 
 
 				var emitterPass = new THREE.RenderPass( emitterScene, camera );
 				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 = new THREE.EffectComposer( renderer, rtEmitter );
 				compEmitter.addPass( emitterPass );
 				compEmitter.addPass( emitterPass );
@@ -233,17 +241,14 @@
 				// lighting pass
 				// lighting pass
 				// ----------------------------------------------------------
 				// ----------------------------------------------------------
 
 
-				rtLightBuffer = new THREE.WebGLRenderTarget( SCALE * WIDTH, SCALE * HEIGHT, rtParamsFloat );
-				rtLightBuffer.generateMipmaps = false;
-
 				var passLight = new THREE.RenderPass( lightScene, camera );
 				var passLight = new THREE.RenderPass( lightScene, camera );
-				compLightBuffer = new THREE.EffectComposer( renderer, rtLightBuffer );
+				compLightBuffer = new THREE.EffectComposer( renderer, rtLight );
 				compLightBuffer.addPass( passLight );
 				compLightBuffer.addPass( passLight );
 
 
 				lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
 				lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
 				lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
 				lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
 				lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
 				lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
-				lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLightBuffer;
+				lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLight;
 
 
 				var geomEmitter = new THREE.SphereGeometry( 0.7, 7, 7 );
 				var geomEmitter = new THREE.SphereGeometry( 0.7, 7, 7 );
 
 
@@ -310,8 +315,8 @@
 
 
 				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
 				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
 
 
-				//effectFXAA.uniforms[ 'resolution' ].value.set( 1 / ( WIDTH ), 1 / ( HEIGHT ) );
-				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / ( SCALE * WIDTH ), 1 / ( SCALE * HEIGHT ) );
+				//effectFXAA.uniforms[ 'resolution' ].value.set( 1 / WIDTH, 1 / HEIGHT );
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCALED_WIDTH, 1 / SCALED_HEIGHT );
 				//effectFXAA.renderToScreen = true;
 				//effectFXAA.renderToScreen = true;
 
 
 				var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
 				var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
@@ -434,11 +439,11 @@
 				lightShader = THREE.ShaderDeferred[ "light" ];
 				lightShader = THREE.ShaderDeferred[ "light" ];
 				compositeShader = THREE.ShaderDeferred[ "composite" ];
 				compositeShader = THREE.ShaderDeferred[ "composite" ];
 
 
-				unlitShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
-				unlitShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+				unlitShader.uniforms[ "viewWidth" ].value = SCALED_WIDTH;
+				unlitShader.uniforms[ "viewHeight" ].value = SCALED_HEIGHT;
 
 
-				lightShader.uniforms[ "viewWidth" ].value = SCALE * WIDTH;
-				lightShader.uniforms[ "viewHeight" ].value = SCALE * HEIGHT;
+				lightShader.uniforms[ "viewWidth" ].value = SCALED_WIDTH;
+				lightShader.uniforms[ "viewHeight" ].value = SCALED_HEIGHT;
 
 
 				// -----------------------
 				// -----------------------
 				// default materials
 				// default materials