|
@@ -0,0 +1,2377 @@
|
|
|
|
+/**
|
|
|
|
+ * @author alteredq / http://alteredqualia.com/
|
|
|
|
+ * @author MPanknin / http://www.redplant.de/
|
|
|
|
+ * @author takahiro / https://github.com/takahirox
|
|
|
|
+ *
|
|
|
|
+ * WebGLDeferredRenderer supports two types of Deferred Renderings.
|
|
|
|
+ * One is Classic Deferred Rendering and the other one is
|
|
|
|
+ * Light Pre-Pass (Deferred Lighting).
|
|
|
|
+ * Classic Deferred Rendering is default. You can use Light Pre-Pass
|
|
|
|
+ * by calling .enableLightPrePass( true ) method.
|
|
|
|
+ *
|
|
|
|
+ * Dependencies
|
|
|
|
+ * - THREE.CopyShader
|
|
|
|
+ * - THREE.RenderPass
|
|
|
|
+ * - THREE.ShaderPass
|
|
|
|
+ * - THREE.EffectComposer
|
|
|
|
+ * - THREE.FXAAShader
|
|
|
|
+ *
|
|
|
|
+ * TODO
|
|
|
|
+ * - reuse existing glsl
|
|
|
|
+ * - shared material
|
|
|
|
+ * - shadow
|
|
|
|
+ * - optimization
|
|
|
|
+ * - MRT (when it's available on Three.js)
|
|
|
|
+ * - AmbientLight
|
|
|
|
+ * - HemisphereLight
|
|
|
|
+ * - PointLight (distance < 0)
|
|
|
|
+ * - morphNormals
|
|
|
|
+ * - BumpMap
|
|
|
|
+ * - ToneMap
|
|
|
|
+ * - envMap
|
|
|
|
+ * - wrapAround
|
|
|
|
+ * - addEffect
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+THREE.WebGLDeferredRenderer = function ( parameters ) {
|
|
|
|
+
|
|
|
|
+ parameters = parameters || {};
|
|
|
|
+
|
|
|
|
+ // private properties
|
|
|
|
+
|
|
|
|
+ var _this = this;
|
|
|
|
+
|
|
|
|
+ var _gl;
|
|
|
|
+
|
|
|
|
+ var _width, _height;
|
|
|
|
+
|
|
|
|
+ // for Classic Deferred Rendering
|
|
|
|
+ var _compColor;
|
|
|
|
+ var _passColor, _passForward, _passCopy;
|
|
|
|
+
|
|
|
|
+ // for Light Pre-Pass
|
|
|
|
+ var _compReconstruction;
|
|
|
|
+ var _passReconstruction;
|
|
|
|
+
|
|
|
|
+ // for Common
|
|
|
|
+ var _compNormalDepth, _compLight, _compFinal;
|
|
|
|
+ var _passNormalDepth, _passLight, _passLightFullscreen, _passFinal, _passFXAA;
|
|
|
|
+
|
|
|
|
+ var _depthTexture;
|
|
|
|
+
|
|
|
|
+ var _lightScene, _lightFullscreenScene;
|
|
|
|
+
|
|
|
|
+ var _antialias = false, _hasTransparentObject = false, _lightPrePass = false;
|
|
|
|
+
|
|
|
|
+ var _invisibleMaterial = new THREE.ShaderMaterial( { visible: false } );
|
|
|
|
+
|
|
|
|
+ var _tmpVector3 = new THREE.Vector3();
|
|
|
|
+
|
|
|
|
+ // external properties
|
|
|
|
+
|
|
|
|
+ this.renderer;
|
|
|
|
+ this.domElement;
|
|
|
|
+
|
|
|
|
+ this.forwardRendering = false; // for debug
|
|
|
|
+
|
|
|
|
+ // private methods
|
|
|
|
+
|
|
|
|
+ var init = function ( parameters ) {
|
|
|
|
+
|
|
|
|
+ _this.renderer = parameters.renderer !== undefined ? parameters.renderer : new THREE.WebGLRenderer( { antialias: false } );
|
|
|
|
+ _this.domElement = _this.renderer.domElement;
|
|
|
|
+
|
|
|
|
+ _gl = _this.renderer.context;
|
|
|
|
+
|
|
|
|
+ _width = parameters.width !== undefined ? parameters.width : _this.renderer.getSize().width;
|
|
|
|
+ _height = parameters.height !== undefined ? parameters.height : _this.renderer.getSize().height;
|
|
|
|
+
|
|
|
|
+ var antialias = parameters.antialias !== undefined ? parameters.antialias : false;
|
|
|
|
+
|
|
|
|
+ initDepthTexture();
|
|
|
|
+
|
|
|
|
+ initPassNormalDepth();
|
|
|
|
+ initPassColor();
|
|
|
|
+ initPassLight();
|
|
|
|
+ initPassReconstruction();
|
|
|
|
+ initPassFinal();
|
|
|
|
+
|
|
|
|
+ _this.setSize( _width, _height );
|
|
|
|
+ _this.setAntialias( antialias );
|
|
|
|
+ _this.enableLightPrePass( false );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDepthTexture = function () {
|
|
|
|
+
|
|
|
|
+ _depthTexture = new THREE.DepthTexture(
|
|
|
|
+ _width,
|
|
|
|
+ _height,
|
|
|
|
+ THREE.UnsignedInt248Type,
|
|
|
|
+ undefined,
|
|
|
|
+ undefined,
|
|
|
|
+ undefined,
|
|
|
|
+ undefined,
|
|
|
|
+ undefined,
|
|
|
|
+ undefined,
|
|
|
|
+ THREE.DepthStencilFormat
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initPassNormalDepth = function () {
|
|
|
|
+
|
|
|
|
+ _passNormalDepth = new THREE.RenderPass();
|
|
|
|
+ _passNormalDepth.clear = true;
|
|
|
|
+
|
|
|
|
+ var rt = new THREE.WebGLRenderTarget( _width, _height, {
|
|
|
|
+ minFilter: THREE.NearestFilter,
|
|
|
|
+ magFilter: THREE.NearestFilter,
|
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
|
+ type: THREE.FloatType,
|
|
|
|
+ stencilBuffer: true,
|
|
|
|
+ depthTexture: _depthTexture
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
|
+
|
|
|
|
+ _compNormalDepth = new THREE.EffectComposer( _this.renderer, rt );
|
|
|
|
+ _compNormalDepth.addPass( _passNormalDepth );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initPassColor = function () {
|
|
|
|
+
|
|
|
|
+ _passColor = new THREE.RenderPass();
|
|
|
|
+ _passColor.clear = true;
|
|
|
|
+
|
|
|
|
+ var rt = new THREE.WebGLRenderTarget( _width, _height, {
|
|
|
|
+ minFilter: THREE.NearestFilter,
|
|
|
|
+ magFilter: THREE.NearestFilter,
|
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
|
+ type: THREE.FloatType,
|
|
|
|
+ depthTexture: _depthTexture
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
|
+
|
|
|
|
+ _compColor = new THREE.EffectComposer( _this.renderer, rt );
|
|
|
|
+ _compColor.addPass( _passColor );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initPassLight = function () {
|
|
|
|
+
|
|
|
|
+ _passLightFullscreen = new THREE.RenderPass();
|
|
|
|
+ _passLightFullscreen.clear = true;
|
|
|
|
+ _passLightFullscreen.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
|
|
|
|
+
|
|
|
|
+ _passLight = new THREE.RenderPass();
|
|
|
|
+ _passLight.clear = false;
|
|
|
|
+
|
|
|
|
+ var rt = new THREE.WebGLRenderTarget( _width, _height, {
|
|
|
|
+ minFilter: THREE.NearestFilter,
|
|
|
|
+ magFilter: THREE.NearestFilter,
|
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
|
+ type: THREE.FloatType,
|
|
|
|
+ depthTexture: _depthTexture
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
|
+
|
|
|
|
+ _compLight = new THREE.EffectComposer( _this.renderer, rt );
|
|
|
|
+ _compLight.addPass( _passLightFullscreen );
|
|
|
|
+ _compLight.addPass( _passLight );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initPassReconstruction = function () {
|
|
|
|
+
|
|
|
|
+ _passReconstruction = new THREE.RenderPass();
|
|
|
|
+ _passReconstruction.clear = true;
|
|
|
|
+
|
|
|
|
+ var rt = new THREE.WebGLRenderTarget( _width, _height, {
|
|
|
|
+ minFilter: THREE.NearestFilter,
|
|
|
|
+ magFilter: THREE.NearestFilter,
|
|
|
|
+ format: THREE.RGBAFormat,
|
|
|
|
+ type: THREE.FloatType,
|
|
|
|
+ depthTexture: _depthTexture
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
|
+
|
|
|
|
+ _compReconstruction = new THREE.EffectComposer( _this.renderer, rt );
|
|
|
|
+ _compReconstruction.addPass( _passReconstruction );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initPassFinal = function () {
|
|
|
|
+
|
|
|
|
+ _passFinal = new THREE.ShaderPass( THREE.ShaderDeferred[ 'final' ] );
|
|
|
|
+ _passFinal.clear = true;
|
|
|
|
+ _passFinal.uniforms.samplerResult.value = _compLight.renderTarget2.texture;
|
|
|
|
+ _passFinal.material.blending = THREE.NoBlending;
|
|
|
|
+ _passFinal.material.depthWrite = false;
|
|
|
|
+ _passFinal.material.depthTest = false;
|
|
|
|
+
|
|
|
|
+ _passForward = new THREE.RenderPass();
|
|
|
|
+ _passForward.clear = false;
|
|
|
|
+
|
|
|
|
+ _passCopy = new THREE.ShaderPass( THREE.CopyShader );
|
|
|
|
+
|
|
|
|
+ _passFXAA = new THREE.ShaderPass( THREE.FXAAShader );
|
|
|
|
+
|
|
|
|
+ var rt = new THREE.WebGLRenderTarget( _width, _height, {
|
|
|
|
+ minFilter: THREE.NearestFilter,
|
|
|
|
+ magFilter: THREE.LinearFilter,
|
|
|
|
+ format: THREE.RGBFormat,
|
|
|
|
+ type: THREE.UnsignedByteType,
|
|
|
|
+ depthTexture: _depthTexture
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
|
+
|
|
|
|
+ _compFinal = new THREE.EffectComposer( _this.renderer, rt );
|
|
|
|
+ _compFinal.addPass( _passFinal );
|
|
|
|
+ _compFinal.addPass( _passForward );
|
|
|
|
+ _compFinal.addPass( _passCopy );
|
|
|
|
+ _compFinal.addPass( _passFXAA );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initLightScene = function ( scene ) {
|
|
|
|
+
|
|
|
|
+ if ( scene.userData.lightScene === undefined ) {
|
|
|
|
+
|
|
|
|
+ var lightScene = new THREE.Scene();
|
|
|
|
+ lightScene.userData.lights = {};
|
|
|
|
+
|
|
|
|
+ scene.userData.lightScene = lightScene;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( scene.userData.lightFullscreenScene === undefined ) {
|
|
|
|
+
|
|
|
|
+ var lightScene = new THREE.Scene();
|
|
|
|
+ lightScene.userData.lights = {};
|
|
|
|
+
|
|
|
|
+ lightScene.userData.emissiveLight = createDeferredEmissiveLight();
|
|
|
|
+ lightScene.add( lightScene.userData.emissiveLight );
|
|
|
|
+
|
|
|
|
+ scene.userData.lightFullscreenScene = lightScene;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _lightScene = scene.userData.lightScene;
|
|
|
|
+ _lightFullscreenScene = scene.userData.lightFullscreenScene;
|
|
|
|
+
|
|
|
|
+ // emissiveLight is only for Classic Deferred Rendering
|
|
|
|
+ _lightFullscreenScene.userData.emissiveLight.visible = ! _lightPrePass;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var setMaterialNormalDepth = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
|
+
|
|
|
|
+ object.material = getNormalDepthMaterial( object );
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredNormalDepthMaterial( object.material.materials[ i ], object.userData.originalMaterial.materials[ i ], _lightPrePass );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ updateDeferredNormalDepthMaterial( object.material, object.userData.originalMaterial, _lightPrePass );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var getNormalDepthMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( ( _lightPrePass && object.userData.normalDepthShininessMaterial === undefined ) ||
|
|
|
|
+ ( ! _lightPrePass && object.userData.normalDepthMaterial === undefined ) ) {
|
|
|
|
+
|
|
|
|
+ initDeferredNormalDepthMaterial( object, _lightPrePass );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ( _lightPrePass ) ? object.userData.normalDepthShininessMaterial : object.userData.normalDepthMaterial;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDeferredNormalDepthMaterial = function ( object, isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var originalMaterial = object.userData.originalMaterial;
|
|
|
|
+ var material;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ var materials = [];
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ materials.push( createDeferredNormalDepthMaterial( originalMaterial.materials[ i ], isLightPrePass ) );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ material = new THREE.MultiMaterial( materials );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ material = createDeferredNormalDepthMaterial( originalMaterial, isLightPrePass );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ object.userData.normalDepthShininessMaterial = material;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ object.userData.normalDepthMaterial = material;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredNormalDepthMaterial = function ( originalMaterial, isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var shader = ( isLightPrePass ) ? THREE.ShaderDeferred[ 'normalDepthShininess' ] : THREE.ShaderDeferred[ 'normalDepth' ];
|
|
|
|
+
|
|
|
|
+ var material = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
|
+ blending: THREE.NoBlending
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredNormalDepthMaterial = function ( material, originalMaterial, isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.skinning !== undefined ) material.skinning = originalMaterial.skinning;
|
|
|
|
+ if ( originalMaterial.morphTargets !== undefined ) material.morphTargets = originalMaterial.morphTargets;
|
|
|
|
+
|
|
|
|
+ if ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var shininess = originalMaterial.shininess;
|
|
|
|
+
|
|
|
|
+ if ( ( originalMaterial.isShaderMaterial === true ) && originalMaterial.uniforms !== undefined ) {
|
|
|
|
+
|
|
|
|
+ if ( shininess === undefined && originalMaterial.uniforms.shininess !== undefined ) shininess = originalMaterial.uniforms.shininess.value;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( shininess !== undefined ) material.uniforms.shininess.value = shininess;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.visible === true ) {
|
|
|
|
+
|
|
|
|
+ material.visible = ! originalMaterial.transparent;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ material.visible = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var setMaterialColor = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
|
+
|
|
|
|
+ object.material = getColorMaterial( object );
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredColorMaterial( object.material.materials[ i ], object.userData.originalMaterial.materials[ i ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ updateDeferredColorMaterial( object.material, object.userData.originalMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var getColorMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.userData.colorMaterial === undefined ) {
|
|
|
|
+
|
|
|
|
+ initDeferredColorMaterial( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return object.userData.colorMaterial;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDeferredColorMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ var originalMaterial = object.userData.originalMaterial;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ var materials = [];
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ materials.push( createDeferredColorMaterial( originalMaterial.materials[ i ] ) );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ object.userData.colorMaterial = new THREE.MultiMaterial( materials );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ object.userData.colorMaterial = createDeferredColorMaterial( originalMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredColorMaterial = function ( originalMaterial ) {
|
|
|
|
+
|
|
|
|
+ var shader = THREE.ShaderDeferred[ 'color' ];
|
|
|
|
+
|
|
|
|
+ var material = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
|
+ blending: THREE.NoBlending
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.map !== undefined ) material.map = originalMaterial.map;
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredColorMaterial = function ( material, originalMaterial ) {
|
|
|
|
+
|
|
|
|
+ var diffuse, emissive;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.isMeshBasicMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ emissive = originalMaterial.color;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ diffuse = originalMaterial.color;
|
|
|
|
+ emissive = originalMaterial.emissive;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var specular = originalMaterial.specular;
|
|
|
|
+ var shininess = originalMaterial.shininess;
|
|
|
|
+ var map = originalMaterial.map;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.isShaderMaterial === true && originalMaterial.uniforms !== undefined ) {
|
|
|
|
+
|
|
|
|
+ if ( diffuse === undefined && originalMaterial.uniforms.diffuse !== undefined ) diffuse = originalMaterial.uniforms.diffuse.value;
|
|
|
|
+ if ( emissive === undefined && originalMaterial.uniforms.emissive !== undefined ) emissive = originalMaterial.uniforms.emissive.value;
|
|
|
|
+ if ( specular === undefined && originalMaterial.uniforms.specular !== undefined ) specular = originalMaterial.uniforms.specular.value;
|
|
|
|
+ if ( shininess === undefined && originalMaterial.uniforms.shininess !== undefined ) shininess = originalMaterial.uniforms.shininess.value;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( diffuse !== undefined ) material.uniforms.diffuse.value.copy( diffuse );
|
|
|
|
+ if ( emissive !== undefined ) material.uniforms.emissive.value.copy( emissive );
|
|
|
|
+ if ( specular !== undefined ) material.uniforms.specular.value.copy( specular );
|
|
|
|
+ if ( shininess !== undefined && material.uniforms.shininess !== undefined ) material.uniforms.shininess.value = shininess;
|
|
|
|
+
|
|
|
|
+ if ( map !== undefined ) {
|
|
|
|
+
|
|
|
|
+ material.map = map;
|
|
|
|
+ material.uniforms.map.value = map;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.skinning !== undefined ) material.skinning = originalMaterial.skinning;
|
|
|
|
+ if ( originalMaterial.morphTargets !== undefined ) material.morphTargets = originalMaterial.morphTargets;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.visible === true ) {
|
|
|
|
+
|
|
|
|
+ material.visible = ! originalMaterial.transparent;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ material.visible = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var setMaterialReconstruction = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.transparent === true ) {
|
|
|
|
+
|
|
|
|
+ object.material = object.userData.originalMaterial;
|
|
|
|
+
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ object.material = getReconstructionMaterial( object );
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredReconstructionMaterial( object.material.materials[ i ], object.userData.originalMaterial.materials[ i ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ updateDeferredReconstructionMaterial( object.material, object.userData.originalMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var getReconstructionMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.userData.reconstructionMaterial === undefined ) {
|
|
|
|
+
|
|
|
|
+ initDeferredReconstructionMaterial( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return object.userData.reconstructionMaterial;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDeferredReconstructionMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ var originalMaterial = object.userData.originalMaterial;
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ var materials = [];
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ materials.push( createDeferredReconstructionMaterial( originalMaterial.materials[ i ] ) );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ object.userData.reconstructionMaterial = new THREE.MultiMaterial( materials );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ object.userData.reconstructionMaterial = createDeferredReconstructionMaterial( originalMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredReconstructionMaterial = function ( originalMaterial ) {
|
|
|
|
+
|
|
|
|
+ var shader = THREE.ShaderDeferred[ 'reconstruction' ];
|
|
|
|
+
|
|
|
|
+ var material = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
|
+ blending: THREE.NoBlending
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.map !== undefined ) material.map = originalMaterial.map;
|
|
|
|
+
|
|
|
|
+ material.uniforms.samplerLight.value = _compLight.renderTarget2.texture;
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredReconstructionMaterial = function ( material, originalMaterial ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredColorMaterial( material, originalMaterial );
|
|
|
|
+
|
|
|
|
+ material.uniforms.viewWidth.value = _width;
|
|
|
|
+ material.uniforms.viewHeight.value = _height;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var setMaterialForwardRendering = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ if ( object.userData.forwardMaterial === undefined ) {
|
|
|
|
+
|
|
|
|
+ initInvisibleMaterial( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ object.material = object.userData.forwardMaterial;
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ object.material.materials[ i ] = getForwardRenderingMaterial( object.userData.originalMaterial.materials[ i ] );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ object.material = getForwardRenderingMaterial( object.userData.originalMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initInvisibleMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ var materials = [];
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ materials.push( _invisibleMaterial );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ object.userData.forwardMaterial = new THREE.MultiMaterial( materials );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var getForwardRenderingMaterial = function ( originalMaterial ) {
|
|
|
|
+
|
|
|
|
+ if ( originalMaterial.transparent === true && originalMaterial.visible === true ) {
|
|
|
|
+
|
|
|
|
+ return originalMaterial
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ return _invisibleMaterial;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredEmissiveLight = function () {
|
|
|
|
+
|
|
|
|
+ var shader = THREE.ShaderDeferred[ 'emissiveLight' ];
|
|
|
|
+
|
|
|
|
+ var material = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
|
+ blending: THREE.NoBlending,
|
|
|
|
+ depthWrite: false
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
|
|
|
|
+
|
|
|
|
+ var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
|
|
|
|
+ var mesh = new THREE.Mesh( geometry, material );
|
|
|
|
+
|
|
|
|
+ return mesh;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredEmissiveLight = function ( light, camera ) {
|
|
|
|
+
|
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
|
+
|
|
|
|
+ uniforms.viewWidth.value = _width;
|
|
|
|
+ uniforms.viewHeight.value = _height;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDeferredLight = function ( light ) {
|
|
|
|
+
|
|
|
|
+ var deferredLight;
|
|
|
|
+
|
|
|
|
+ if ( light.isPointLight ) {
|
|
|
|
+
|
|
|
|
+ deferredLight = createDeferredPointLight( light );
|
|
|
|
+
|
|
|
|
+ } else if ( light.isSpotLight ) {
|
|
|
|
+
|
|
|
|
+ deferredLight = createDeferredSpotLight( light );
|
|
|
|
+
|
|
|
|
+ } else if ( light.isDirectionalLight ) {
|
|
|
|
+
|
|
|
|
+ deferredLight = createDeferredDirectionalLight( light );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ deferredLight = null;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ light.userData.deferredLight = deferredLight;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var initDeferredLightMaterial = function ( light, isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
|
+ var material;
|
|
|
|
+
|
|
|
|
+ if ( originalLight.isPointLight ) {
|
|
|
|
+
|
|
|
|
+ material = createDeferredPointLightMaterial( isLightPrePass );
|
|
|
|
+
|
|
|
|
+ } else if ( originalLight.isSpotLight ) {
|
|
|
|
+
|
|
|
|
+ material = createDeferredSpotLightMaterial( isLightPrePass );
|
|
|
|
+
|
|
|
|
+ } else if ( originalLight.isDirectionalLight ) {
|
|
|
|
+
|
|
|
|
+ material = createDeferredDirectionalLightMaterial( isLightPrePass );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ material = null;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ light.userData.materialLightPrePass = material;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ light.userData.materialClassic = material;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var getDeferredLightMaterial = function ( light ) {
|
|
|
|
+
|
|
|
|
+ if ( ( _lightPrePass && light.userData.materialLightPrePass === undefined ) ||
|
|
|
|
+ ( ! _lightPrePass && light.userData.materialClassic === undefined ) ) {
|
|
|
|
+
|
|
|
|
+ initDeferredLightMaterial( light, _lightPrePass );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ( _lightPrePass ) ? light.userData.materialLightPrePass : light.userData.materialClassic;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredLight = function ( light, camera ) {
|
|
|
|
+
|
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
|
+
|
|
|
|
+ if ( originalLight.isPointLight ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredPointLight( light, camera );
|
|
|
|
+
|
|
|
|
+ } else if ( originalLight.isSpotLight ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredSpotLight( light, camera );
|
|
|
|
+
|
|
|
|
+ } else if ( originalLight.isDirectionalLight ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredDirectionalLight( light, camera );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredLightMesh = function ( light, geometry ) {
|
|
|
|
+
|
|
|
|
+ var mesh = new THREE.Mesh( geometry, _invisibleMaterial );
|
|
|
|
+
|
|
|
|
+ mesh.userData.originalLight = light;
|
|
|
|
+
|
|
|
|
+ return mesh;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredLightMaterial = function ( shader, isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var material = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
|
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
|
+ transparent: true,
|
|
|
|
+ blending: THREE.AdditiveBlending,
|
|
|
|
+ depthWrite: false
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ if ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ material.premultipliedAlpha = true;
|
|
|
|
+ material.uniforms.samplerNormalDepthShininess.value = _compNormalDepth.renderTarget2.texture;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ material.uniforms.samplerNormalDepth.value = _compNormalDepth.renderTarget2.texture;
|
|
|
|
+ material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredPointLight = function ( light ) {
|
|
|
|
+
|
|
|
|
+ return createDeferredLightMesh( light, new THREE.SphereGeometry( 1, 16, 8 ) );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * optimization:
|
|
|
|
+ * Renders PointLight only back face with stencil test.
|
|
|
|
+ */
|
|
|
|
+ var createDeferredPointLightMaterial = function ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var shader = ( isLightPrePass ) ? THREE.ShaderDeferred[ 'pointLightPre' ] : THREE.ShaderDeferred[ 'pointLight' ];
|
|
|
|
+
|
|
|
|
+ var material = createDeferredLightMaterial( shader, isLightPrePass );
|
|
|
|
+
|
|
|
|
+ material.side = THREE.BackSide;
|
|
|
|
+ material.depthFunc = THREE.GreaterEqualDepth;
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredPointLight = function ( light, camera ) {
|
|
|
|
+
|
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
|
+ var distance = originalLight.distance;
|
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
|
+
|
|
|
|
+ uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
|
|
|
|
+ uniforms.viewWidth.value = _width;
|
|
|
|
+ uniforms.viewHeight.value = _height;
|
|
|
|
+ uniforms.lightColor.value.copy( originalLight.color );
|
|
|
|
+
|
|
|
|
+ if ( distance > 0 ) {
|
|
|
|
+
|
|
|
|
+ light.scale.set( 1, 1, 1 ).multiplyScalar( distance );
|
|
|
|
+ uniforms.lightRadius.value = distance;
|
|
|
|
+ uniforms.lightIntensity.value = originalLight.intensity;
|
|
|
|
+ uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( camera.matrixWorldInverse );
|
|
|
|
+ light.position.setFromMatrixPosition( originalLight.matrixWorld );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ uniforms.lightRadius.value = Infinity;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredSpotLight = function ( light ) {
|
|
|
|
+
|
|
|
|
+ return createDeferredLightMesh( light, new THREE.PlaneBufferGeometry( 2, 2 ) );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredSpotLightMaterial = function ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var shader = ( isLightPrePass ) ? THREE.ShaderDeferred[ 'spotLightPre' ] : THREE.ShaderDeferred[ 'spotLight' ];
|
|
|
|
+
|
|
|
|
+ var material = createDeferredLightMaterial( shader, isLightPrePass );
|
|
|
|
+
|
|
|
|
+ material.depthTest = false;
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredSpotLight = function ( light, camera ) {
|
|
|
|
+
|
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
|
+
|
|
|
|
+ uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
|
|
|
|
+ uniforms.viewWidth.value = _width;
|
|
|
|
+ uniforms.viewHeight.value = _height;
|
|
|
|
+ uniforms.lightAngle.value = originalLight.angle;
|
|
|
|
+ uniforms.lightColor.value.copy( originalLight.color );
|
|
|
|
+ uniforms.lightIntensity.value = originalLight.intensity;
|
|
|
|
+ uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( camera.matrixWorldInverse );
|
|
|
|
+
|
|
|
|
+ var vec = uniforms.lightDirectionVS.value;
|
|
|
|
+ var vec2 = _tmpVector3;
|
|
|
|
+
|
|
|
|
+ vec.setFromMatrixPosition( originalLight.matrixWorld );
|
|
|
|
+ vec2.setFromMatrixPosition( originalLight.target.matrixWorld );
|
|
|
|
+ vec.sub( vec2 ).normalize().transformDirection( camera.matrixWorldInverse );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredDirectionalLight = function ( light ) {
|
|
|
|
+
|
|
|
|
+ return createDeferredLightMesh( light, new THREE.PlaneBufferGeometry( 2, 2 ) );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var createDeferredDirectionalLightMaterial = function ( isLightPrePass ) {
|
|
|
|
+
|
|
|
|
+ var shader = ( isLightPrePass ) ? THREE.ShaderDeferred[ 'directionalLightPre' ] : THREE.ShaderDeferred[ 'directionalLight' ];
|
|
|
|
+
|
|
|
|
+ var material = createDeferredLightMaterial( shader, isLightPrePass );
|
|
|
|
+
|
|
|
|
+ material.depthTest = false;
|
|
|
|
+
|
|
|
|
+ return material;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredDirectionalLight = function ( light, camera ) {
|
|
|
|
+
|
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
|
+
|
|
|
|
+ uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
|
|
|
|
+ uniforms.viewWidth.value = _width;
|
|
|
|
+ uniforms.viewHeight.value = _height;
|
|
|
|
+ uniforms.lightColor.value.copy( originalLight.color );
|
|
|
|
+ uniforms.lightIntensity.value = originalLight.intensity;
|
|
|
|
+
|
|
|
|
+ var vec = uniforms.lightDirectionVS.value;
|
|
|
|
+ var vec2 = _tmpVector3;
|
|
|
|
+
|
|
|
|
+ vec.setFromMatrixPosition( originalLight.matrixWorld );
|
|
|
|
+ vec2.setFromMatrixPosition( originalLight.target.matrixWorld );
|
|
|
|
+ vec.sub( vec2 ).normalize().transformDirection( camera.matrixWorldInverse );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var saveOriginalMaterialAndCheckTransparency = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material !== undefined ) {
|
|
|
|
+
|
|
|
|
+ object.userData.originalMaterial = object.material;
|
|
|
|
+
|
|
|
|
+ if ( _hasTransparentObject ) return;
|
|
|
|
+
|
|
|
|
+ if ( object.material.isMultiMaterial === true ) {
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = object.material.materials.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ if ( object.material.materials[ i ].transparent === true ) {
|
|
|
|
+
|
|
|
|
+ _hasTransparentObject = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ if ( object.material.transparent === true ) _hasTransparentObject = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var restoreOriginalMaterial = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.userData.originalMaterial !== undefined ) object.material = object.userData.originalMaterial;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var addDeferredLightsToLightScene = function ( object ) {
|
|
|
|
+
|
|
|
|
+ if ( object.isLight !== true ) return;
|
|
|
|
+
|
|
|
|
+ if ( object.userData.deferredLight === undefined ) {
|
|
|
|
+
|
|
|
|
+ initDeferredLight( object );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var light = object.userData.deferredLight;
|
|
|
|
+
|
|
|
|
+ if ( light === null ) return;
|
|
|
|
+
|
|
|
|
+ var scene = ( object.isPointLight === true ) ? _lightScene : _lightFullscreenScene;
|
|
|
|
+
|
|
|
|
+ var lights = scene.userData.lights;
|
|
|
|
+
|
|
|
|
+ if ( lights[ light.uuid ] === undefined ) {
|
|
|
|
+
|
|
|
|
+ scene.add( light );
|
|
|
|
+
|
|
|
|
+ lights[ light.uuid ] = {
|
|
|
|
+ light: light,
|
|
|
|
+ found: true
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ lights[ light.uuid ].found = true;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var updateDeferredLightsInLightScene = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ var lights = scene.userData.lights;
|
|
|
|
+ var keys = Object.keys( lights );
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, il = keys.length; i < il; i ++ ) {
|
|
|
|
+
|
|
|
|
+ var key = keys[ i ];
|
|
|
|
+
|
|
|
|
+ if ( lights[ key ].found === false ) {
|
|
|
|
+
|
|
|
|
+ scene.remove( lights[ key ].light );
|
|
|
|
+ delete lights[ key ];
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ var light = lights[ key ].light;
|
|
|
|
+ var material = getDeferredLightMaterial( light );
|
|
|
|
+ light.material = material;
|
|
|
|
+
|
|
|
|
+ updateDeferredLight( light, camera );
|
|
|
|
+ lights[ key ].found = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ var enableFinalPasses = function () {
|
|
|
|
+
|
|
|
|
+ if ( _lightPrePass ) {
|
|
|
|
+
|
|
|
|
+ _passForward.renderToScreen = false;
|
|
|
|
+ _passForward.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passCopy.renderToScreen = false;
|
|
|
|
+ _passCopy.enabled = false;
|
|
|
|
+
|
|
|
|
+ if ( _antialias ) {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = false;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = true;
|
|
|
|
+ _passFXAA.enabled = true;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = true;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = false;
|
|
|
|
+ _passFXAA.enabled = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ if ( _hasTransparentObject ) {
|
|
|
|
+
|
|
|
|
+ if ( _antialias ) {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = false;
|
|
|
|
+
|
|
|
|
+ _passForward.renderToScreen = false;
|
|
|
|
+ _passForward.enabled = true;
|
|
|
|
+
|
|
|
|
+ _passCopy.renderToScreen = false;
|
|
|
|
+ _passCopy.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = true;
|
|
|
|
+ _passFXAA.enabled = true;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = false;
|
|
|
|
+
|
|
|
|
+ _passForward.renderToScreen = false;
|
|
|
|
+ _passForward.enabled = true;
|
|
|
|
+
|
|
|
|
+ _passCopy.renderToScreen = true;
|
|
|
|
+ _passCopy.enabled = true;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = false;
|
|
|
|
+ _passFXAA.enabled = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ if ( _antialias ) {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = false;
|
|
|
|
+
|
|
|
|
+ _passForward.renderToScreen = false;
|
|
|
|
+ _passForward.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passCopy.renderToScreen = false;
|
|
|
|
+ _passCopy.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = true;
|
|
|
|
+ _passFXAA.enabled = true;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ _passFinal.renderToScreen = true;
|
|
|
|
+
|
|
|
|
+ _passForward.renderToScreen = false;
|
|
|
|
+ _passForward.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passCopy.renderToScreen = false;
|
|
|
|
+ _passCopy.enabled = false;
|
|
|
|
+
|
|
|
|
+ _passFXAA.renderToScreen = false;
|
|
|
|
+ _passFXAA.enabled = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Classic Deferred Rendering
|
|
|
|
+ *
|
|
|
|
+ * 1) g-buffer normal + depth pass
|
|
|
|
+ *
|
|
|
|
+ * RGB: normal
|
|
|
|
+ * A: depth
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
|
+ *
|
|
|
|
+ * 1') g-buffer normal + depth pass + shininess
|
|
|
|
+ *
|
|
|
|
+ * R: normal
|
|
|
|
+ * B: shininess
|
|
|
|
+ * A: depth
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderNormalDepth = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ scene.traverse( setMaterialNormalDepth );
|
|
|
|
+
|
|
|
|
+ _passNormalDepth.scene = scene;
|
|
|
|
+ _passNormalDepth.camera = camera;
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = true;
|
|
|
|
+ _this.renderer.autoClearStencil = true;
|
|
|
|
+
|
|
|
|
+ _gl.enable( _gl.STENCIL_TEST );
|
|
|
|
+ _gl.stencilFunc( _gl.ALWAYS, 1, 0xffffffff );
|
|
|
|
+ _gl.stencilOp( _gl.REPLACE, _gl.REPLACE, _gl.REPLACE );
|
|
|
|
+
|
|
|
|
+ _compNormalDepth.render();
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Classic Deferred Rendering
|
|
|
|
+ *
|
|
|
|
+ * 2) g-buffer color pass
|
|
|
|
+ *
|
|
|
|
+ * R: diffuse
|
|
|
|
+ * G: emissive
|
|
|
|
+ * B: specular
|
|
|
|
+ * A: shininess
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderColor = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ scene.traverse( setMaterialColor );
|
|
|
|
+
|
|
|
|
+ _passColor.scene = scene;
|
|
|
|
+ _passColor.camera = camera;
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
|
+
|
|
|
|
+ _gl.stencilFunc( _gl.EQUAL, 1, 0xffffffff );
|
|
|
|
+ _gl.stencilOp( _gl.KEEP, _gl.KEEP, _gl.KEEP );
|
|
|
|
+
|
|
|
|
+ _compColor.render();
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Classic Deferred Rendering
|
|
|
|
+ *
|
|
|
|
+ * 3) light pass
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderLight = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ updateDeferredEmissiveLight( _lightFullscreenScene.userData.emissiveLight, camera );
|
|
|
|
+
|
|
|
|
+ scene.traverse( addDeferredLightsToLightScene );
|
|
|
|
+
|
|
|
|
+ updateDeferredLightsInLightScene( _lightScene, camera );
|
|
|
|
+ updateDeferredLightsInLightScene( _lightFullscreenScene, camera );
|
|
|
|
+
|
|
|
|
+ _passLight.scene = _lightScene;
|
|
|
|
+ _passLight.camera = camera;
|
|
|
|
+
|
|
|
|
+ _passLightFullscreen.scene = _lightFullscreenScene;
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
|
+
|
|
|
|
+ _compLight.render();
|
|
|
|
+
|
|
|
|
+ _gl.disable( _gl.STENCIL_TEST );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
|
+ *
|
|
|
|
+ * 2') Light pre pass
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderLightPre = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ scene.traverse( addDeferredLightsToLightScene );
|
|
|
|
+
|
|
|
|
+ updateDeferredLightsInLightScene( _lightScene, camera );
|
|
|
|
+ updateDeferredLightsInLightScene( _lightFullscreenScene, camera );
|
|
|
|
+
|
|
|
|
+ _passLight.scene = _lightScene;
|
|
|
|
+ _passLight.camera = camera;
|
|
|
|
+
|
|
|
|
+ _passLightFullscreen.scene = _lightFullscreenScene;
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
|
+
|
|
|
|
+ _gl.stencilFunc( _gl.EQUAL, 1, 0xffffffff );
|
|
|
|
+ _gl.stencilOp( _gl.KEEP, _gl.KEEP, _gl.KEEP );
|
|
|
|
+
|
|
|
|
+ _compLight.render();
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
|
+ *
|
|
|
|
+ * 3') Reconstruction pass
|
|
|
|
+ *
|
|
|
|
+ * Transprency handling:
|
|
|
|
+ * Here renders transparent objects with normal forward rendering.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderReconstruction = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ scene.traverse( setMaterialReconstruction );
|
|
|
|
+
|
|
|
|
+ _passReconstruction.scene = scene;
|
|
|
|
+ _passReconstruction.camera = camera;
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
|
+
|
|
|
|
+ _compReconstruction.render();
|
|
|
|
+
|
|
|
|
+ _gl.disable( _gl.STENCIL_TEST );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Classic Deferred Rendering
|
|
|
|
+ *
|
|
|
|
+ * 4) Final pass
|
|
|
|
+ *
|
|
|
|
+ * transparency handling:
|
|
|
|
+ * If there's any transparent objects, here renders them on the deferred rendering result
|
|
|
|
+ * with normal forward rendering. This may be the easist way but heavy.
|
|
|
|
+ * We should consider any better ways someday.
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
|
+ *
|
|
|
|
+ * 4') Final pass
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ * Common
|
|
|
|
+ *
|
|
|
|
+ * antialias handling:
|
|
|
|
+ * Here uses postprocessing FXAA for antialias.
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ var renderFinal = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ if ( ! _lightPrePass && _hasTransparentObject ) {
|
|
|
|
+
|
|
|
|
+ scene.traverse( setMaterialForwardRendering );
|
|
|
|
+
|
|
|
|
+ _passForward.scene = scene;
|
|
|
|
+ _passForward.camera = camera;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ enableFinalPasses();
|
|
|
|
+
|
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
|
+
|
|
|
|
+ _compFinal.render();
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // external APIs
|
|
|
|
+
|
|
|
|
+ this.setSize = function ( width, height ) {
|
|
|
|
+
|
|
|
|
+ _width = width;
|
|
|
|
+ _height = height;
|
|
|
|
+
|
|
|
|
+ this.renderer.setSize( _width, _height );
|
|
|
|
+
|
|
|
|
+ _compNormalDepth.setSize( _width, _height );
|
|
|
|
+ _compColor.setSize( _width, _height );
|
|
|
|
+ _compLight.setSize( _width, _height );
|
|
|
|
+ _compReconstruction.setSize( _width, _height );
|
|
|
|
+ _compFinal.setSize( _width, _height );
|
|
|
|
+
|
|
|
|
+ _depthTexture.image.width = _width;
|
|
|
|
+ _depthTexture.image.height = _height;
|
|
|
|
+ _depthTexture.needsUpdate = true;
|
|
|
|
+
|
|
|
|
+ _passFXAA.uniforms.resolution.value.set( 1 / _width, 1 / _height );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ this.setAntialias = function ( enabled ) {
|
|
|
|
+
|
|
|
|
+ _antialias = enabled;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ this.enableLightPrePass = function ( enabled ) {
|
|
|
|
+
|
|
|
|
+ _lightPrePass = enabled;
|
|
|
|
+
|
|
|
|
+ _passFinal.uniforms.samplerResult.value = ( _lightPrePass ) ? _compReconstruction.renderTarget2.texture : _compLight.renderTarget2.texture;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ this.render = function ( scene, camera ) {
|
|
|
|
+
|
|
|
|
+ // for debug to compare with normal forward rendering
|
|
|
|
+
|
|
|
|
+ if ( this.forwardRendering ) {
|
|
|
|
+
|
|
|
|
+ this.renderer.render( scene, camera );
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var tmpSceneAutoUpdate = scene.autoUpdate;
|
|
|
|
+ var tmpAutoClearColor = this.renderer.autoClearColor;
|
|
|
|
+ var tmpAutoClearDepth = this.renderer.autoClearDepth;
|
|
|
|
+ var tmpAutoClearStencil = this.renderer.autoClearStencil;
|
|
|
|
+
|
|
|
|
+ initLightScene( scene );
|
|
|
|
+
|
|
|
|
+ scene.autoUpdate = false;
|
|
|
|
+ scene.updateMatrixWorld();
|
|
|
|
+
|
|
|
|
+ _hasTransparentObject = false;
|
|
|
|
+
|
|
|
|
+ scene.traverse( saveOriginalMaterialAndCheckTransparency );
|
|
|
|
+
|
|
|
|
+ renderNormalDepth( scene, camera );
|
|
|
|
+
|
|
|
|
+ if ( _lightPrePass ) {
|
|
|
|
+
|
|
|
|
+ renderLightPre( scene, camera );
|
|
|
|
+ renderReconstruction( scene, camera );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ renderColor( scene, camera );
|
|
|
|
+ renderLight( scene, camera );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ renderFinal( scene, camera );
|
|
|
|
+
|
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
|
+
|
|
|
|
+ scene.autoUpdate = tmpSceneAutoUpdate;
|
|
|
|
+ this.renderer.autoClearColor = tmpAutoClearColor;
|
|
|
|
+ this.renderer.autoClearDepth = tmpAutoClearDepth;
|
|
|
|
+ this.renderer.autoClearStencil = tmpAutoClearStencil;
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // initialize
|
|
|
|
+
|
|
|
|
+ init( parameters );
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+THREE.DeferredShaderChunk = {
|
|
|
|
+
|
|
|
|
+ packVector3: [
|
|
|
|
+
|
|
|
|
+ "float vec3_to_float( vec3 data ) {",
|
|
|
|
+
|
|
|
|
+ "const float unit = 255.0/256.0;",
|
|
|
|
+ "highp float compressed = fract( data.x * unit ) + floor( data.y * unit * 255.0 ) + floor( data.z * unit * 255.0 ) * 255.0;",
|
|
|
|
+ "return compressed;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ unpackFloat: [
|
|
|
|
+
|
|
|
|
+ "vec3 float_to_vec3( float data ) {",
|
|
|
|
+
|
|
|
|
+ "const float unit = 255.0;",
|
|
|
|
+ "vec3 uncompressed;",
|
|
|
|
+ "uncompressed.x = fract( data );",
|
|
|
|
+ "float zInt = floor( data / unit );",
|
|
|
|
+ "uncompressed.z = fract( zInt / unit );",
|
|
|
|
+ "uncompressed.y = fract( floor( data - ( zInt * unit ) ) / unit );",
|
|
|
|
+ "return uncompressed;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ computeTextureCoord: [
|
|
|
|
+
|
|
|
|
+ "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ packNormalDepth: [
|
|
|
|
+
|
|
|
|
+ "vec4 packedNormalDepth;",
|
|
|
|
+ "packedNormalDepth.xyz = normal * 0.5 + 0.5;",
|
|
|
|
+ "packedNormalDepth.w = position.z / position.w;",
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ unpackNormalDepth: [
|
|
|
|
+
|
|
|
|
+ "vec4 normalDepthMap = texture2D( samplerNormalDepth, texCoord );",
|
|
|
|
+ "float depth = normalDepthMap.w;",
|
|
|
|
+
|
|
|
|
+ "if ( depth == 0.0 ) discard;",
|
|
|
|
+
|
|
|
|
+ "vec3 normal = normalDepthMap.xyz * 2.0 - 1.0;"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ // TODO: optimize normal packing. reference http://aras-p.info/texts/CompactNormalStorage.html
|
|
|
|
+ packNormalDepthShininess: [
|
|
|
|
+
|
|
|
|
+ "vec4 packedNormalDepthShininess;",
|
|
|
|
+ "packedNormalDepthShininess.x = vec3_to_float( normal * 0.5 + 0.5 );",
|
|
|
|
+ "packedNormalDepthShininess.z = shininess;",
|
|
|
|
+ "packedNormalDepthShininess.w = position.z / position.w;"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ unpackNormalDepthShininess: [
|
|
|
|
+
|
|
|
|
+ "vec4 normalDepthMap = texture2D( samplerNormalDepthShininess, texCoord );",
|
|
|
|
+ "float depth = normalDepthMap.w;",
|
|
|
|
+
|
|
|
|
+ "if ( depth == 0.0 ) discard;",
|
|
|
|
+
|
|
|
|
+ "vec3 normal = float_to_vec3( normalDepthMap.x ) * 2.0 - 1.0;",
|
|
|
|
+ "float shininess = normalDepthMap.z;"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ packColor: [
|
|
|
|
+
|
|
|
|
+ "vec4 packedColor;",
|
|
|
|
+ "packedColor.x = vec3_to_float( diffuseColor.rgb );",
|
|
|
|
+ "packedColor.y = vec3_to_float( emissiveColor );",
|
|
|
|
+ "packedColor.z = vec3_to_float( specularColor );",
|
|
|
|
+ "packedColor.w = shininess;"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ unpackColor: [
|
|
|
|
+
|
|
|
|
+ "vec4 colorMap = texture2D( samplerColor, texCoord );",
|
|
|
|
+ "vec3 diffuseColor = float_to_vec3( colorMap.x );",
|
|
|
|
+ "vec3 emissiveColor = float_to_vec3( colorMap.y );",
|
|
|
|
+ "vec3 specularColor = float_to_vec3( colorMap.z );",
|
|
|
|
+ "float shininess = colorMap.w;",
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ packLight: [
|
|
|
|
+
|
|
|
|
+ "vec4 packedLight;",
|
|
|
|
+ "packedLight.xyz = lightIntensity * lightColor * max( dot( lightVector, normal ), 0.0 ) * attenuation;",
|
|
|
|
+ "packedLight.w = lightIntensity * specular * max( dot( lightVector, normal ), 0.0 ) * attenuation;",
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ computeVertexPositionVS: [
|
|
|
|
+
|
|
|
|
+ "vec2 xy = texCoord * 2.0 - 1.0;",
|
|
|
|
+ "vec4 vertexPositionProjected = vec4( xy, depth, 1.0 );",
|
|
|
|
+ "vec4 vertexPositionVS = matProjInverse * vertexPositionProjected;",
|
|
|
|
+ "vertexPositionVS.xyz /= vertexPositionVS.w;",
|
|
|
|
+ "vertexPositionVS.w = 1.0;"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ // TODO: calculate schlick
|
|
|
|
+ computeSpecular: [
|
|
|
|
+
|
|
|
|
+ "vec3 halfVector = normalize( lightVector - normalize( vertexPositionVS.xyz ) );",
|
|
|
|
+ "float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );",
|
|
|
|
+ "float specular = 0.31830988618 * ( shininess * 0.5 + 1.0 ) * pow( dotNormalHalf, shininess );",
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ combine: [
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = vec4( lightIntensity * lightColor * max( dot( lightVector, normal ), 0.0 ) * ( diffuseColor + specular * specularColor ) * attenuation, 1.0 );"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+THREE.ShaderDeferred = {
|
|
|
|
+
|
|
|
|
+ normalDepth: {
|
|
|
|
+
|
|
|
|
+ uniforms: {},
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "varying vec3 vNormal;",
|
|
|
|
+ "varying vec4 vPosition;",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_pars_vertex" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "begin_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "beginnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinbase_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "defaultnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "project_vertex" ],
|
|
|
|
+
|
|
|
|
+ "vNormal = normalize( normalMatrix * objectNormal );",
|
|
|
|
+ "vPosition = gl_Position;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "varying vec3 vNormal;",
|
|
|
|
+ "varying vec4 vPosition;",
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "vec3 normal = vNormal;",
|
|
|
|
+ "vec4 position = vPosition;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packNormalDepth" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = packedNormalDepth;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ color: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ map: { type: "t", value: null },
|
|
|
|
+ offsetRepeat: { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
|
|
|
|
+
|
|
|
|
+ diffuse: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ emissive: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ specular: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ shininess: { type: "f", value: 30.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_pars_vertex" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "begin_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "beginnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinbase_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "defaultnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "project_vertex" ],
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform vec3 diffuse;",
|
|
|
|
+ "uniform vec3 emissive;",
|
|
|
|
+ "uniform vec3 specular;",
|
|
|
|
+ "uniform float shininess;",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_pars_fragment" ],
|
|
|
|
+ THREE.ShaderChunk[ "map_pars_fragment" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "packVector3" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "vec4 diffuseColor = vec4( diffuse, 1.0 );",
|
|
|
|
+ "vec3 emissiveColor = emissive;",
|
|
|
|
+ "vec3 specularColor = specular;",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "map_fragment" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "packColor" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = packedColor;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ emissiveLight: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerColor: { type: "t", value: null },
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() { ",
|
|
|
|
+
|
|
|
|
+ "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerColor;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackColor" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = vec4( emissiveColor, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ pointLight: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepth: { type: "t", value: null },
|
|
|
|
+ samplerColor: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 },
|
|
|
|
+ lightRadius: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepth;",
|
|
|
|
+ "uniform sampler2D samplerColor;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightPositionVS;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+ "uniform float lightRadius;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
|
|
|
|
+ "float distance = length( lightVector );",
|
|
|
|
+
|
|
|
|
+ "if ( distance > lightRadius ) discard;",
|
|
|
|
+
|
|
|
|
+ "lightVector = normalize( lightVector );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackColor" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "//float cutoff = 0.3;",
|
|
|
|
+ "//float denom = distance / lightRadius + 1.0;",
|
|
|
|
+ "//float attenuation = 1.0 / ( denom * denom );",
|
|
|
|
+ "//attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );",
|
|
|
|
+ "//attenuation = max( attenuation, 0.0 );",
|
|
|
|
+ "//attenuation *= attenuation;",
|
|
|
|
+
|
|
|
|
+ "//diffuseColor *= saturate( -distance / lightRadius + 1.0 );",
|
|
|
|
+ "//float attenuation = 1.0;",
|
|
|
|
+
|
|
|
|
+ "float attenuation = saturate( -distance / lightRadius + 1.0 );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "combine" ],
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ spotLight: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepth: { type: "t", value: null },
|
|
|
|
+ samplerColor: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightAngle: { type: "f", value: 1.0 },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() { ",
|
|
|
|
+
|
|
|
|
+ "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepth;",
|
|
|
|
+ "uniform sampler2D samplerColor;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightPositionVS;",
|
|
|
|
+ "uniform vec3 lightDirectionVS;",
|
|
|
|
+ "uniform float lightAngle;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackColor" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
|
|
|
|
+
|
|
|
|
+ "float rho = dot( lightDirectionVS, lightVector );",
|
|
|
|
+ "float rhoMax = cos( lightAngle * 0.5 );",
|
|
|
|
+
|
|
|
|
+ "if ( rho <= rhoMax ) discard;",
|
|
|
|
+
|
|
|
|
+ "float theta = rhoMax + 0.0001;",
|
|
|
|
+ "float phi = rhoMax + 0.05;",
|
|
|
|
+ "float falloff = 4.0;",
|
|
|
|
+
|
|
|
|
+ "float spot = 0.0;",
|
|
|
|
+
|
|
|
|
+ "if ( rho >= phi ) {",
|
|
|
|
+
|
|
|
|
+ "spot = 1.0;",
|
|
|
|
+
|
|
|
|
+ "} else if ( rho <= theta ) {",
|
|
|
|
+
|
|
|
|
+ "spot = 0.0;",
|
|
|
|
+
|
|
|
|
+ "} else { ",
|
|
|
|
+
|
|
|
|
+ "spot = pow( ( rho - theta ) / ( phi - theta ), falloff );",
|
|
|
|
+
|
|
|
|
+ "}",
|
|
|
|
+
|
|
|
|
+ "diffuseColor *= spot;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "const float attenuation = 1.0;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "combine" ],
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ directionalLight: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepth: { type: "t", value: null },
|
|
|
|
+ samplerColor: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightDirectionVS : { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() { ",
|
|
|
|
+
|
|
|
|
+ "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepth;",
|
|
|
|
+ "uniform sampler2D samplerColor;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightDirectionVS;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackColor" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = normalize( lightDirectionVS );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "const float attenuation = 1.0;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "combine" ],
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' ),
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ normalDepthShininess: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ shininess: { type: "f", value: 30.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "varying vec3 vNormal;",
|
|
|
|
+ "varying vec4 vPosition;",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_pars_vertex" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "begin_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "beginnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinbase_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "defaultnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "project_vertex" ],
|
|
|
|
+
|
|
|
|
+ "vNormal = normalize( normalMatrix * objectNormal );",
|
|
|
|
+ "vPosition = gl_Position;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "varying vec3 vNormal;",
|
|
|
|
+ "varying vec4 vPosition;",
|
|
|
|
+
|
|
|
|
+ "uniform float shininess;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packVector3" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "vec3 normal = vNormal;",
|
|
|
|
+ "vec4 position = vPosition;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packNormalDepthShininess" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = packedNormalDepthShininess;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ pointLightPre: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepthShininess: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 },
|
|
|
|
+ lightRadius: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepthShininess;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightPositionVS;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+ "uniform float lightRadius;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
|
|
|
|
+ "float distance = length( lightVector );",
|
|
|
|
+
|
|
|
|
+ "if ( distance > lightRadius ) discard;",
|
|
|
|
+
|
|
|
|
+ "lightVector = normalize( lightVector );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "float attenuation = saturate( -distance / lightRadius + 1.0 );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packLight" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = packedLight;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ spotLightPre: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepthShininess: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightAngle: { type: "f", value: 1.0 },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() { ",
|
|
|
|
+
|
|
|
|
+ "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepthShininess;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightPositionVS;",
|
|
|
|
+ "uniform vec3 lightDirectionVS;",
|
|
|
|
+ "uniform float lightAngle;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
|
|
|
|
+
|
|
|
|
+ "float rho = dot( lightDirectionVS, lightVector );",
|
|
|
|
+ "float rhoMax = cos( lightAngle * 0.5 );",
|
|
|
|
+
|
|
|
|
+ "if ( rho <= rhoMax ) discard;",
|
|
|
|
+
|
|
|
|
+ "float theta = rhoMax + 0.0001;",
|
|
|
|
+ "float phi = rhoMax + 0.05;",
|
|
|
|
+ "float falloff = 4.0;",
|
|
|
|
+
|
|
|
|
+ "float spot = 0.0;",
|
|
|
|
+
|
|
|
|
+ "if ( rho >= phi ) {",
|
|
|
|
+
|
|
|
|
+ "spot = 1.0;",
|
|
|
|
+
|
|
|
|
+ "} else if ( rho <= theta ) {",
|
|
|
|
+
|
|
|
|
+ "spot = 0.0;",
|
|
|
|
+
|
|
|
|
+ "} else { ",
|
|
|
|
+
|
|
|
|
+ "spot = pow( ( rho - theta ) / ( phi - theta ), falloff );",
|
|
|
|
+
|
|
|
|
+ "}",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "const float attenuation = 1.0;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packLight" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = spot * packedLight;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ directionalLightPre: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerNormalDepthShininess: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ matProjInverse: { type: "m4", value: new THREE.Matrix4() },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ lightDirectionVS : { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
|
|
|
|
+ lightIntensity: { type: "f", value: 1.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ "void main() { ",
|
|
|
|
+
|
|
|
|
+ "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerNormalDepthShininess;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 lightColor;",
|
|
|
|
+ "uniform vec3 lightDirectionVS;",
|
|
|
|
+ "uniform float lightIntensity;",
|
|
|
|
+
|
|
|
|
+ "uniform mat4 matProjInverse;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
|
+
|
|
|
|
+ "vec3 lightVector = normalize( lightDirectionVS );",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeSpecular" ],
|
|
|
|
+
|
|
|
|
+ "const float attenuation = 1.0;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "packLight" ],
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = packedLight;",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( '\n' ),
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ reconstruction: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerLight: { type: "t", value: null },
|
|
|
|
+
|
|
|
|
+ map: { type: "t", value: null },
|
|
|
|
+ offsetRepeat: { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
|
|
|
|
+
|
|
|
|
+ viewWidth: { type: "f", value: 800 },
|
|
|
|
+ viewHeight: { type: "f", value: 600 },
|
|
|
|
+
|
|
|
|
+ diffuse: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ emissive: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ specular: { type: "c", value: new THREE.Color( 0x000000 ) },
|
|
|
|
+ shininess: { type: "f", value: 30.0 }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ vertexShader: [
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_pars_vertex" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "begin_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "beginnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinbase_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "defaultnormal_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "morphtarget_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "skinning_vertex" ],
|
|
|
|
+ THREE.ShaderChunk[ "project_vertex" ],
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "uniform sampler2D samplerLight;",
|
|
|
|
+
|
|
|
|
+ "uniform vec3 diffuse;",
|
|
|
|
+ "uniform vec3 emissive;",
|
|
|
|
+ "uniform vec3 specular;",
|
|
|
|
+ "uniform float shininess;",
|
|
|
|
+
|
|
|
|
+ "uniform float viewHeight;",
|
|
|
|
+ "uniform float viewWidth;",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "uv_pars_fragment" ],
|
|
|
|
+ THREE.ShaderChunk[ "map_pars_fragment" ],
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "unpackFloat" ],
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "vec4 diffuseColor = vec4( diffuse, 1.0 );",
|
|
|
|
+ "vec3 emissiveColor = emissive;",
|
|
|
|
+ "vec3 specularColor = specular;",
|
|
|
|
+
|
|
|
|
+ THREE.DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
|
+
|
|
|
|
+ "vec4 light = texture2D( samplerLight, texCoord );",
|
|
|
|
+
|
|
|
|
+ THREE.ShaderChunk[ "map_fragment" ],
|
|
|
|
+
|
|
|
|
+ "vec3 diffuseFinal = diffuseColor.rgb * light.rgb;",
|
|
|
|
+ "vec3 emissiveFinal = emissiveColor;",
|
|
|
|
+ "vec3 specularFinal = specularColor * light.rgb * ( light.a / ( 0.2126 * light.r + 0.7152 * light.g + 0.0722 * light.b + 0.00001 ) );",
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = vec4( diffuseFinal + emissiveFinal + specularFinal, 1.0 );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ // TODO: implement tone mapping
|
|
|
|
+ final: {
|
|
|
|
+
|
|
|
|
+ uniforms: {
|
|
|
|
+
|
|
|
|
+ samplerResult: { type: "t", value: null }
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ 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" ),
|
|
|
|
+
|
|
|
|
+ fragmentShader: [
|
|
|
|
+
|
|
|
|
+ "varying vec2 texCoord;",
|
|
|
|
+ "uniform sampler2D samplerResult;",
|
|
|
|
+
|
|
|
|
+ "void main() {",
|
|
|
|
+
|
|
|
|
+ "gl_FragColor = texture2D( samplerResult, texCoord );",
|
|
|
|
+
|
|
|
|
+ "}"
|
|
|
|
+
|
|
|
|
+ ].join( "\n" )
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+};
|