|
@@ -0,0 +1,2528 @@
|
|
|
+/**
|
|
|
+ * @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
|
|
|
+ * - CopyShader
|
|
|
+ * - RenderPass
|
|
|
+ * - ShaderPass
|
|
|
+ * - EffectComposer
|
|
|
+ * - FXAAShader
|
|
|
+ *
|
|
|
+ * TODO
|
|
|
+ * - reuse existing glsl
|
|
|
+ * - shadow
|
|
|
+ * - optimization
|
|
|
+ * - MRT (when it's available on Three.js)
|
|
|
+ * - AmbientLight
|
|
|
+ * - HemisphereLight
|
|
|
+ * - PointLight (distance < 0)
|
|
|
+ * - morphNormals
|
|
|
+ * - BumpMap
|
|
|
+ * - ToneMap
|
|
|
+ * - envMap
|
|
|
+ * - wrapAround
|
|
|
+ * - addEffect
|
|
|
+ */
|
|
|
+
|
|
|
+import {
|
|
|
+ AdditiveBlending,
|
|
|
+ BackSide,
|
|
|
+ Color,
|
|
|
+ DepthStencilFormat,
|
|
|
+ DepthTexture,
|
|
|
+ FloatType,
|
|
|
+ GreaterEqualDepth,
|
|
|
+ LinearFilter,
|
|
|
+ Matrix4,
|
|
|
+ Mesh,
|
|
|
+ NearestFilter,
|
|
|
+ NoBlending,
|
|
|
+ OrthographicCamera,
|
|
|
+ PlaneBufferGeometry,
|
|
|
+ RGBAFormat,
|
|
|
+ RGBFormat,
|
|
|
+ Scene,
|
|
|
+ ShaderMaterial,
|
|
|
+ SphereBufferGeometry,
|
|
|
+ Uniform,
|
|
|
+ UnsignedByteType,
|
|
|
+ UnsignedInt248Type,
|
|
|
+ Vector2,
|
|
|
+ Vector3,
|
|
|
+ Vector4,
|
|
|
+ WebGLRenderTarget,
|
|
|
+ WebGLRenderer
|
|
|
+} from "../../../build/three.module.js";
|
|
|
+import { EffectComposer } from "../postprocessing/EffectComposer.js";
|
|
|
+import { ShaderPass } from "../postprocessing/ShaderPass.js";
|
|
|
+import { RenderPass } from "../postprocessing/RenderPass.js";
|
|
|
+import { FXAAShader } from "../shaders/FXAAShader.js";
|
|
|
+import { CopyShader } from "../shaders/CopyShader.js";
|
|
|
+
|
|
|
+var WebGLDeferredRenderer = function ( parameters ) {
|
|
|
+
|
|
|
+ parameters = parameters || {};
|
|
|
+
|
|
|
+ // private properties
|
|
|
+
|
|
|
+ var _this = this;
|
|
|
+
|
|
|
+ var _context;
|
|
|
+ var _state;
|
|
|
+
|
|
|
+ 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 _currentCamera;
|
|
|
+
|
|
|
+ var _lightScene, _lightFullscreenScene;
|
|
|
+
|
|
|
+ var _antialias = false;
|
|
|
+ var _hasTransparentObject = false;
|
|
|
+ var _lightPrePass = false;
|
|
|
+ var _cacheKeepAlive = false;
|
|
|
+
|
|
|
+ var _tmpMaterial = new ShaderMaterial( { visible: false } );
|
|
|
+ var _tmpVector3 = new Vector3();
|
|
|
+
|
|
|
+ // scene/material/light cache for deferred rendering.
|
|
|
+ // save them at the creation and release
|
|
|
+ // if they're unused removeThresholdCount frames
|
|
|
+ // unless _cacheKeepAlive is true.
|
|
|
+
|
|
|
+ // scene.uuid -> lightScene, lightFullscreenScene
|
|
|
+ var _lightScenesCache = {};
|
|
|
+ var _lightFullscreenScenesCache = {};
|
|
|
+
|
|
|
+ // object.material.uuid -> deferredMaterial or
|
|
|
+ // object.material[ n ].uuid -> deferredMaterial
|
|
|
+ var _normalDepthMaterialsCache = {};
|
|
|
+ var _normalDepthShininessMaterialsCache = {};
|
|
|
+ var _colorMaterialsCache = {};
|
|
|
+ var _reconstructionMaterialsCache = {};
|
|
|
+
|
|
|
+ // originalLight.uuid -> deferredLight
|
|
|
+ var _deferredLightsCache = {};
|
|
|
+
|
|
|
+ // deferredLight.uuid -> deferredLightMaterial
|
|
|
+ var _classicDeferredLightMaterialsCache = {};
|
|
|
+ var _lightPrePassMaterialsCache = {};
|
|
|
+
|
|
|
+ var _removeThresholdCount = 60;
|
|
|
+
|
|
|
+ // deferredMaterials.uuid -> object.material or
|
|
|
+ // deferredMaterials.uuid -> object.material[ n ]
|
|
|
+ // save before render and release after render.
|
|
|
+ var _originalMaterialsTable = {};
|
|
|
+
|
|
|
+ // object.uuid -> originalOnBeforeRender
|
|
|
+ // save before render and release after render.
|
|
|
+ var _originalOnBeforeRendersTable = {};
|
|
|
+
|
|
|
+ // object.material.uuid -> object.material.visible or
|
|
|
+ // object.material[ i ].uuid -> object.material[ i ].visible or
|
|
|
+ // save before render and release after render.
|
|
|
+ var _originalVisibleTable = {};
|
|
|
+
|
|
|
+ // external properties
|
|
|
+
|
|
|
+ this.renderer = undefined;
|
|
|
+ this.domElement = undefined;
|
|
|
+
|
|
|
+ this.forwardRendering = false; // for debug
|
|
|
+
|
|
|
+ // private methods
|
|
|
+
|
|
|
+ function init( parameters ) {
|
|
|
+
|
|
|
+ _this.renderer = parameters.renderer !== undefined ? parameters.renderer : new WebGLRenderer();
|
|
|
+ _this.domElement = _this.renderer.domElement;
|
|
|
+
|
|
|
+ _context = _this.renderer.context;
|
|
|
+ _state = _this.renderer.state;
|
|
|
+
|
|
|
+ _width = parameters.width !== undefined ? parameters.width : _this.renderer.getSize( new Vector2() ).width;
|
|
|
+ _height = parameters.height !== undefined ? parameters.height : _this.renderer.getSize( new Vector2() ).height;
|
|
|
+
|
|
|
+ var antialias = parameters.antialias !== undefined ? parameters.antialias : false;
|
|
|
+
|
|
|
+ if ( parameters.cacheKeepAlive !== undefined ) _cacheKeepAlive = parameters.cacheKeepAlive;
|
|
|
+
|
|
|
+ initDepthTexture();
|
|
|
+
|
|
|
+ initPassNormalDepth();
|
|
|
+ initPassColor();
|
|
|
+ initPassLight();
|
|
|
+ initPassReconstruction();
|
|
|
+ initPassFinal();
|
|
|
+
|
|
|
+ _this.setSize( _width, _height );
|
|
|
+ _this.setAntialias( antialias );
|
|
|
+ _this.enableLightPrePass( false );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initDepthTexture() {
|
|
|
+
|
|
|
+ _depthTexture = new DepthTexture(
|
|
|
+ _width,
|
|
|
+ _height,
|
|
|
+ UnsignedInt248Type,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ undefined,
|
|
|
+ DepthStencilFormat
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initPassNormalDepth() {
|
|
|
+
|
|
|
+ _passNormalDepth = new RenderPass();
|
|
|
+ _passNormalDepth.clear = true;
|
|
|
+
|
|
|
+ var rt = new WebGLRenderTarget( _width, _height, {
|
|
|
+ minFilter: NearestFilter,
|
|
|
+ magFilter: NearestFilter,
|
|
|
+ format: RGBAFormat,
|
|
|
+ type: FloatType,
|
|
|
+ stencilBuffer: true,
|
|
|
+ depthTexture: _depthTexture
|
|
|
+ } );
|
|
|
+
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
+
|
|
|
+ _compNormalDepth = new EffectComposer( _this.renderer, rt );
|
|
|
+ _compNormalDepth.renderToScreen = false;
|
|
|
+ _compNormalDepth.addPass( _passNormalDepth );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initPassColor() {
|
|
|
+
|
|
|
+ _passColor = new RenderPass();
|
|
|
+ _passColor.clear = true;
|
|
|
+
|
|
|
+ var rt = new WebGLRenderTarget( _width, _height, {
|
|
|
+ minFilter: NearestFilter,
|
|
|
+ magFilter: NearestFilter,
|
|
|
+ format: RGBAFormat,
|
|
|
+ type: FloatType,
|
|
|
+ depthTexture: _depthTexture
|
|
|
+ } );
|
|
|
+
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
+
|
|
|
+ _compColor = new EffectComposer( _this.renderer, rt );
|
|
|
+ _compColor.renderToScreen = false;
|
|
|
+ _compColor.addPass( _passColor );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initPassLight() {
|
|
|
+
|
|
|
+ _passLightFullscreen = new RenderPass();
|
|
|
+ _passLightFullscreen.clear = true;
|
|
|
+ _passLightFullscreen.camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
|
|
|
+
|
|
|
+ _passLight = new RenderPass();
|
|
|
+ _passLight.clear = false;
|
|
|
+
|
|
|
+ var rt = new WebGLRenderTarget( _width, _height, {
|
|
|
+ minFilter: NearestFilter,
|
|
|
+ magFilter: NearestFilter,
|
|
|
+ format: RGBAFormat,
|
|
|
+ type: FloatType,
|
|
|
+ depthTexture: _depthTexture
|
|
|
+ } );
|
|
|
+
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
+
|
|
|
+ _compLight = new EffectComposer( _this.renderer, rt );
|
|
|
+ _compLight.renderToScreen = false;
|
|
|
+ _compLight.addPass( _passLightFullscreen );
|
|
|
+ _compLight.addPass( _passLight );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initPassReconstruction() {
|
|
|
+
|
|
|
+ _passReconstruction = new RenderPass();
|
|
|
+ _passReconstruction.clear = true;
|
|
|
+
|
|
|
+ var rt = new WebGLRenderTarget( _width, _height, {
|
|
|
+ minFilter: NearestFilter,
|
|
|
+ magFilter: NearestFilter,
|
|
|
+ format: RGBAFormat,
|
|
|
+ type: FloatType,
|
|
|
+ depthTexture: _depthTexture
|
|
|
+ } );
|
|
|
+
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
+
|
|
|
+ _compReconstruction = new EffectComposer( _this.renderer, rt );
|
|
|
+ _compReconstruction.renderToScreen = false;
|
|
|
+ _compReconstruction.addPass( _passReconstruction );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initPassFinal() {
|
|
|
+
|
|
|
+ _passFinal = new ShaderPass( ShaderDeferred[ 'final' ] );
|
|
|
+ _passFinal.clear = true;
|
|
|
+ _passFinal.uniforms.samplerResult.value = _compLight.renderTarget2.texture;
|
|
|
+ _passFinal.material.blending = NoBlending;
|
|
|
+ _passFinal.material.depthWrite = false;
|
|
|
+ _passFinal.material.depthTest = false;
|
|
|
+
|
|
|
+ _passForward = new RenderPass();
|
|
|
+ _passForward.clear = false;
|
|
|
+
|
|
|
+ _passCopy = new ShaderPass( CopyShader );
|
|
|
+
|
|
|
+ _passFXAA = new ShaderPass( FXAAShader );
|
|
|
+
|
|
|
+ var rt = new WebGLRenderTarget( _width, _height, {
|
|
|
+ minFilter: NearestFilter,
|
|
|
+ magFilter: LinearFilter,
|
|
|
+ format: RGBFormat,
|
|
|
+ type: UnsignedByteType,
|
|
|
+ depthTexture: _depthTexture
|
|
|
+ } );
|
|
|
+
|
|
|
+ rt.texture.generateMipamps = false;
|
|
|
+
|
|
|
+ _compFinal = new EffectComposer( _this.renderer, rt );
|
|
|
+ _compFinal.addPass( _passFinal );
|
|
|
+ _compFinal.addPass( _passForward );
|
|
|
+ _compFinal.addPass( _passCopy );
|
|
|
+ _compFinal.addPass( _passFXAA );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function initLightScene( scene ) {
|
|
|
+
|
|
|
+ var lightSceneData = _lightScenesCache[ scene.uuid ];
|
|
|
+ var lightFullscreenSceneData = _lightFullscreenScenesCache[ scene.uuid ];
|
|
|
+
|
|
|
+ if ( lightSceneData === undefined ) {
|
|
|
+
|
|
|
+ var s = new Scene();
|
|
|
+ s.userData.lights = {};
|
|
|
+
|
|
|
+ lightSceneData = createCacheData();
|
|
|
+ lightSceneData.scene = s;
|
|
|
+
|
|
|
+ _lightScenesCache[ scene.uuid ] = lightSceneData;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( lightFullscreenSceneData === undefined ) {
|
|
|
+
|
|
|
+ var s = new Scene();
|
|
|
+ s.userData.lights = {};
|
|
|
+
|
|
|
+ var emissiveLight = createDeferredEmissiveLight();
|
|
|
+
|
|
|
+ s.userData.emissiveLight = emissiveLight;
|
|
|
+ s.add( emissiveLight );
|
|
|
+
|
|
|
+ lightFullscreenSceneData = createCacheData();
|
|
|
+ lightFullscreenSceneData.scene = s;
|
|
|
+
|
|
|
+ _lightFullscreenScenesCache[ scene.uuid ] = lightFullscreenSceneData;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ lightSceneData.used = true;
|
|
|
+ lightFullscreenSceneData.used = true;
|
|
|
+
|
|
|
+ var lightScene = lightSceneData.scene;
|
|
|
+ var lightFullscreenScene = lightFullscreenSceneData.scene;
|
|
|
+
|
|
|
+ // emissiveLight is only for Classic Deferred Rendering
|
|
|
+ lightFullscreenScene.userData.emissiveLight.visible = ! _lightPrePass;
|
|
|
+
|
|
|
+ _lightScene = lightScene;
|
|
|
+ _lightFullscreenScene = lightFullscreenScene;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function getMaterialFromCacheOrCreate( originalMaterial, cache, createFunc, updateFunc ) {
|
|
|
+
|
|
|
+ var data = cache[ originalMaterial.uuid ];
|
|
|
+
|
|
|
+ if ( data === undefined ) {
|
|
|
+
|
|
|
+ data = createCacheData();
|
|
|
+ data.material = createFunc( originalMaterial );
|
|
|
+ cache[ originalMaterial.uuid ] = data;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ data.used = true;
|
|
|
+
|
|
|
+ updateFunc( data.material, originalMaterial );
|
|
|
+
|
|
|
+ _originalMaterialsTable[ data.material.uuid ] = originalMaterial;
|
|
|
+
|
|
|
+ return data.material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function overrideMaterialAndOnBeforeRender( object, getMaterialFunc, onBeforeRender ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
+
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ object.material[ i ] = getMaterialFunc( object.material[ i ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ object.material = getMaterialFunc( object.material );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ object.onBeforeRender = onBeforeRender;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function restoreOriginalMaterial( object ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
+
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ object.material[ i ] = _originalMaterialsTable[ object.material[ i ].uuid ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ object.material = _originalMaterialsTable[ object.material.uuid ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function setMaterialNormalDepth( object ) {
|
|
|
+
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getNormalDepthMaterial, updateDeferredNormalDepthUniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function getNormalDepthMaterial( originalMaterial ) {
|
|
|
+
|
|
|
+ return getMaterialFromCacheOrCreate(
|
|
|
+ originalMaterial,
|
|
|
+ ( _lightPrePass ) ? _normalDepthShininessMaterialsCache : _normalDepthMaterialsCache,
|
|
|
+ createDeferredNormalDepthMaterial,
|
|
|
+ updateDeferredNormalDepthMaterial
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredNormalDepthMaterial() {
|
|
|
+
|
|
|
+ var shader = ( _lightPrePass ) ? ShaderDeferred[ 'normalDepthShininess' ] : ShaderDeferred[ 'normalDepth' ];
|
|
|
+
|
|
|
+ return new ShaderMaterial( {
|
|
|
+ uniforms: Object.assign( {}, shader.uniforms ),
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
+ blending: NoBlending
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredNormalDepthMaterial( material, originalMaterial ) {
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredNormalDepthUniforms( renderer, scene, camera, geometry, material ) {
|
|
|
+
|
|
|
+ if ( ! _lightPrePass ) return;
|
|
|
+
|
|
|
+ var originalMaterial = _originalMaterialsTable[ material.uuid ];
|
|
|
+
|
|
|
+ if ( originalMaterial === undefined || originalMaterial.shininess === undefined ) return;
|
|
|
+
|
|
|
+ material.uniforms.shininess.value = originalMaterial.shininess;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function setMaterialColor( object ) {
|
|
|
+
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getColorMaterial, updateDeferredColorUniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function getColorMaterial( originalMaterial ) {
|
|
|
+
|
|
|
+ return getMaterialFromCacheOrCreate(
|
|
|
+ originalMaterial,
|
|
|
+ _colorMaterialsCache,
|
|
|
+ createDeferredColorMaterial,
|
|
|
+ updateDeferredColorMaterial
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredColorMaterial( originalMaterial ) {
|
|
|
+
|
|
|
+ var shader = ShaderDeferred[ 'color' ];
|
|
|
+
|
|
|
+ var material = new ShaderMaterial( {
|
|
|
+ uniforms: Object.assign( {}, shader.uniforms ),
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
+ blending: NoBlending
|
|
|
+ } );
|
|
|
+
|
|
|
+ if ( originalMaterial.map !== undefined ) material.map = originalMaterial.map;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredColorMaterial( material, originalMaterial ) {
|
|
|
+
|
|
|
+ if ( originalMaterial.map !== undefined ) material.map = originalMaterial.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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredColorUniforms( renderer, scene, camera, geometry, material ) {
|
|
|
+
|
|
|
+ var originalMaterial = _originalMaterialsTable[ material.uuid ];
|
|
|
+ var uniforms = material.uniforms;
|
|
|
+
|
|
|
+ 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 ( diffuse !== undefined ) uniforms.diffuse.value.copy( diffuse );
|
|
|
+ if ( emissive !== undefined ) uniforms.emissive.value.copy( emissive );
|
|
|
+ if ( specular !== undefined ) uniforms.specular.value.copy( specular );
|
|
|
+ if ( shininess !== undefined && uniforms.shininess !== undefined ) uniforms.shininess.value = shininess;
|
|
|
+ if ( map !== undefined ) uniforms.map.value = map;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function setMaterialReconstruction( object ) {
|
|
|
+
|
|
|
+ overrideMaterialAndOnBeforeRender( object, getReconstructionMaterial, updateDeferredReconstructionUniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function getReconstructionMaterial( originalMaterial ) {
|
|
|
+
|
|
|
+ if ( originalMaterial.transparent === true ) {
|
|
|
+
|
|
|
+ _originalMaterialsTable[ originalMaterial.uuid ] = originalMaterial;
|
|
|
+ return originalMaterial;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return getMaterialFromCacheOrCreate(
|
|
|
+ originalMaterial,
|
|
|
+ _reconstructionMaterialsCache,
|
|
|
+ createDeferredReconstructionMaterial,
|
|
|
+ updateDeferredReconstructionMaterial
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredReconstructionMaterial( originalMaterial ) {
|
|
|
+
|
|
|
+ var shader = ShaderDeferred[ 'reconstruction' ];
|
|
|
+
|
|
|
+ var material = new ShaderMaterial( {
|
|
|
+ uniforms: Object.assign( {}, shader.uniforms ),
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
+ blending: NoBlending
|
|
|
+ } );
|
|
|
+
|
|
|
+ if ( originalMaterial.map !== undefined ) material.map = originalMaterial.map;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredReconstructionMaterial( material, originalMaterial ) {
|
|
|
+
|
|
|
+ updateDeferredColorMaterial( material, originalMaterial );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredReconstructionUniforms( renderer, scene, camera, geometry, material, group ) {
|
|
|
+
|
|
|
+ if ( material.transparent === true ) {
|
|
|
+
|
|
|
+ // 'this' is object here because this method is set as object.onBefore()
|
|
|
+ var onBeforeRender = _originalOnBeforeRendersTable[ this.uuid ];
|
|
|
+
|
|
|
+ if ( onBeforeRender ) {
|
|
|
+
|
|
|
+ onBeforeRender.call( this, renderer, scene, camera, geometry, material, group );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ updateDeferredColorUniforms( renderer, scene, camera, geometry, material, group );
|
|
|
+
|
|
|
+ material.uniforms.samplerLight.value = _compLight.renderTarget2.texture;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function setVisibleForForwardRendering( object ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
+
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ if ( _originalVisibleTable[ object.material[ i ].uuid ] === undefined ) {
|
|
|
+
|
|
|
+ _originalVisibleTable[ object.material[ i ].uuid ] = object.material[ i ].visible;
|
|
|
+ object.material[ i ].visible = object.material[ i ].transparent && object.material[ i ].visible;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( _originalVisibleTable[ object.material.uuid ] === undefined ) {
|
|
|
+
|
|
|
+ _originalVisibleTable[ object.material.uuid ] = object.material.visible;
|
|
|
+ object.material.visible = object.material.transparent && object.material.visible;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function restoreVisible( object ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
+
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ object.material[ i ].visible = _originalVisibleTable[ object.material[ i ].uuid ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ object.material.visible = _originalVisibleTable[ object.material.uuid ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredEmissiveLight() {
|
|
|
+
|
|
|
+ var shader = ShaderDeferred[ 'emissiveLight' ];
|
|
|
+
|
|
|
+ var material = new ShaderMaterial( {
|
|
|
+ uniforms: Object.assign( {}, shader.uniforms ),
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
+ blending: NoBlending,
|
|
|
+ depthWrite: false
|
|
|
+ } );
|
|
|
+
|
|
|
+ var geometry = new PlaneBufferGeometry( 2, 2 );
|
|
|
+ var mesh = new Mesh( geometry, material );
|
|
|
+
|
|
|
+ mesh.onBeforeRender = function ( renderer, scene, camera, geometry, material ) {
|
|
|
+
|
|
|
+ material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ return mesh;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredLight( originalLight ) {
|
|
|
+
|
|
|
+ if ( originalLight.isPointLight ) {
|
|
|
+
|
|
|
+ return createDeferredPointLight( originalLight );
|
|
|
+
|
|
|
+ } else if ( originalLight.isSpotLight ) {
|
|
|
+
|
|
|
+ return createDeferredSpotLight( originalLight );
|
|
|
+
|
|
|
+ } else if ( originalLight.isDirectionalLight ) {
|
|
|
+
|
|
|
+ return createDeferredDirectionalLight( originalLight );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredLightMaterial( originalLight ) {
|
|
|
+
|
|
|
+ if ( originalLight.isPointLight ) {
|
|
|
+
|
|
|
+ return createDeferredPointLightMaterial();
|
|
|
+
|
|
|
+ } else if ( originalLight.isSpotLight ) {
|
|
|
+
|
|
|
+ return createDeferredSpotLightMaterial();
|
|
|
+
|
|
|
+ } else if ( originalLight.isDirectionalLight ) {
|
|
|
+
|
|
|
+ return createDeferredDirectionalLightMaterial();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function getDeferredLightMaterial( light ) {
|
|
|
+
|
|
|
+ var cache = ( _lightPrePass ) ? _lightPrePassMaterialsCache : _classicDeferredLightMaterialsCache;
|
|
|
+
|
|
|
+ var data = cache[ light.uuid ];
|
|
|
+
|
|
|
+ if ( data === undefined ) {
|
|
|
+
|
|
|
+ data = createCacheData();
|
|
|
+ data.material = createDeferredLightMaterial( light.userData.originalLight );
|
|
|
+ cache[ light.uuid ] = data;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ data.used = true;
|
|
|
+
|
|
|
+ return data.material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredLight( light ) {
|
|
|
+
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
+
|
|
|
+ if ( originalLight.isPointLight ) {
|
|
|
+
|
|
|
+ updateDeferredPointLight( light );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredLightMesh( light, geometry ) {
|
|
|
+
|
|
|
+ var mesh = new Mesh( geometry, _tmpMaterial );
|
|
|
+
|
|
|
+ mesh.userData.originalLight = light;
|
|
|
+
|
|
|
+ return mesh;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredLightShaderMaterial( shader ) {
|
|
|
+
|
|
|
+ var material = new ShaderMaterial( {
|
|
|
+ uniforms: Object.assign( {}, shader.uniforms ),
|
|
|
+ vertexShader: shader.vertexShader,
|
|
|
+ fragmentShader: shader.fragmentShader,
|
|
|
+ transparent: true,
|
|
|
+ blending: AdditiveBlending,
|
|
|
+ depthWrite: false
|
|
|
+ } );
|
|
|
+
|
|
|
+ if ( _lightPrePass ) material.premultipliedAlpha = true;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredLightCommonUniforms( uniforms ) {
|
|
|
+
|
|
|
+ if ( _lightPrePass ) {
|
|
|
+
|
|
|
+ uniforms.samplerNormalDepthShininess.value = _compNormalDepth.renderTarget2.texture;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ uniforms.samplerNormalDepth.value = _compNormalDepth.renderTarget2.texture;
|
|
|
+ uniforms.samplerColor.value = _compColor.renderTarget2.texture;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredPointLight( light ) {
|
|
|
+
|
|
|
+ var mesh = createDeferredLightMesh( light, new SphereBufferGeometry( 1, 16, 8 ) );
|
|
|
+ mesh.onBeforeRender = updateDeferredPointLightUniforms;
|
|
|
+ return mesh;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * optimization:
|
|
|
+ * Renders PointLight only back face with stencil test.
|
|
|
+ */
|
|
|
+ function createDeferredPointLightMaterial() {
|
|
|
+
|
|
|
+ var shader = ( _lightPrePass ) ? ShaderDeferred[ 'pointLightPre' ] : ShaderDeferred[ 'pointLight' ];
|
|
|
+
|
|
|
+ var material = createDeferredLightShaderMaterial( shader );
|
|
|
+
|
|
|
+ material.side = BackSide;
|
|
|
+ material.depthFunc = GreaterEqualDepth;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredPointLight( light ) {
|
|
|
+
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
+ var distance = originalLight.distance;
|
|
|
+
|
|
|
+ if ( distance > 0 ) {
|
|
|
+
|
|
|
+ light.scale.set( 1, 1, 1 ).multiplyScalar( distance );
|
|
|
+ light.position.setFromMatrixPosition( originalLight.matrixWorld );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredPointLightUniforms( renderer, scene, camera, geometry, material ) {
|
|
|
+
|
|
|
+ var light = this;
|
|
|
+
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
+ var distance = originalLight.distance;
|
|
|
+ var uniforms = material.uniforms;
|
|
|
+
|
|
|
+ uniforms.lightColor.value.copy( originalLight.color );
|
|
|
+
|
|
|
+ if ( distance > 0 ) {
|
|
|
+
|
|
|
+ uniforms.lightRadius.value = distance;
|
|
|
+ uniforms.lightIntensity.value = originalLight.intensity;
|
|
|
+ uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( _currentCamera.matrixWorldInverse );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ uniforms.lightRadius.value = Infinity;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ updateDeferredLightCommonUniforms( uniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredSpotLight( light ) {
|
|
|
+
|
|
|
+ var mesh = createDeferredLightMesh( light, new PlaneBufferGeometry( 2, 2 ) );
|
|
|
+ mesh.onBeforeRender = updateDeferredSpotLightUniforms;
|
|
|
+ return mesh;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredSpotLightMaterial() {
|
|
|
+
|
|
|
+ var shader = ( _lightPrePass ) ? ShaderDeferred[ 'spotLightPre' ] : ShaderDeferred[ 'spotLight' ];
|
|
|
+
|
|
|
+ var material = createDeferredLightShaderMaterial( shader );
|
|
|
+
|
|
|
+ material.depthTest = false;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredSpotLightUniforms() {
|
|
|
+
|
|
|
+ var light = this;
|
|
|
+
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
+
|
|
|
+ uniforms.lightAngle.value = originalLight.angle;
|
|
|
+ uniforms.lightColor.value.copy( originalLight.color );
|
|
|
+ uniforms.lightIntensity.value = originalLight.intensity;
|
|
|
+ uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( _currentCamera.matrixWorldInverse );
|
|
|
+
|
|
|
+ var vec = uniforms.lightDirectionVS.value;
|
|
|
+ var vec2 = _tmpVector3;
|
|
|
+
|
|
|
+ vec.setFromMatrixPosition( originalLight.matrixWorld );
|
|
|
+ vec2.setFromMatrixPosition( originalLight.target.matrixWorld );
|
|
|
+ vec.sub( vec2 ).normalize().transformDirection( _currentCamera.matrixWorldInverse );
|
|
|
+
|
|
|
+ updateDeferredLightCommonUniforms( uniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredDirectionalLight( light ) {
|
|
|
+
|
|
|
+ var mesh = createDeferredLightMesh( light, new PlaneBufferGeometry( 2, 2 ) );
|
|
|
+ mesh.onBeforeRender = updateDeferredDirectionalLightUniforms;
|
|
|
+ return mesh;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createDeferredDirectionalLightMaterial() {
|
|
|
+
|
|
|
+ var shader = ( _lightPrePass ) ? ShaderDeferred[ 'directionalLightPre' ] : ShaderDeferred[ 'directionalLight' ];
|
|
|
+
|
|
|
+ var material = createDeferredLightShaderMaterial( shader );
|
|
|
+
|
|
|
+ material.depthTest = false;
|
|
|
+
|
|
|
+ return material;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredDirectionalLightUniforms() {
|
|
|
+
|
|
|
+ var light = this;
|
|
|
+
|
|
|
+ var originalLight = light.userData.originalLight;
|
|
|
+ var uniforms = light.material.uniforms;
|
|
|
+
|
|
|
+ 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( _currentCamera.matrixWorldInverse );
|
|
|
+
|
|
|
+ updateDeferredLightCommonUniforms( uniforms );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function saveOriginalOnBeforeRenderAndCheckTransparency( object ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ _originalOnBeforeRendersTable[ object.uuid ] = object.onBeforeRender;
|
|
|
+
|
|
|
+ // _hasTransparentObject is used only for Classic Deferred Rendering
|
|
|
+ if ( _hasTransparentObject || _lightPrePass ) return;
|
|
|
+
|
|
|
+ if ( ! object.visible ) return;
|
|
|
+
|
|
|
+ if ( Array.isArray( object.material ) ) {
|
|
|
+
|
|
|
+ for ( var i = 0, il = object.material.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ if ( object.material[ i ].visible === true && object.material[ i ].transparent === true ) {
|
|
|
+
|
|
|
+ _hasTransparentObject = true;
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( object.material.visible === true && object.material.transparent === true ) _hasTransparentObject = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function restoreOriginalOnBeforeRender( object ) {
|
|
|
+
|
|
|
+ if ( object.material === undefined ) return;
|
|
|
+
|
|
|
+ object.onBeforeRender = _originalOnBeforeRendersTable[ object.uuid ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function addDeferredLightsToLightScene( object ) {
|
|
|
+
|
|
|
+ if ( object.isLight !== true ) return;
|
|
|
+
|
|
|
+ var data = _deferredLightsCache[ object.uuid ];
|
|
|
+
|
|
|
+ if ( data === undefined ) {
|
|
|
+
|
|
|
+ data = createCacheData();
|
|
|
+ data.light = createDeferredLight( object );
|
|
|
+ _deferredLightsCache[ object.uuid ] = data;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ data.used = true;
|
|
|
+
|
|
|
+ var light = data.light;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredLightsInLightScene( scene ) {
|
|
|
+
|
|
|
+ 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;
|
|
|
+ light.material = getDeferredLightMaterial( light );
|
|
|
+
|
|
|
+ updateDeferredLight( light );
|
|
|
+ lights[ key ].found = false;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function updateDeferredCommonUniforms( camera ) {
|
|
|
+
|
|
|
+ var uniforms = ShaderDeferredCommon[ 'commonUniforms' ];
|
|
|
+
|
|
|
+ uniforms.viewWidth.value = _width;
|
|
|
+ uniforms.viewHeight.value = _height;
|
|
|
+
|
|
|
+ uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function enableFinalPasses() {
|
|
|
+
|
|
|
+ if ( _lightPrePass ) {
|
|
|
+
|
|
|
+ _passForward.enabled = false;
|
|
|
+ _passCopy.enabled = false;
|
|
|
+
|
|
|
+ if ( _antialias ) {
|
|
|
+
|
|
|
+ _passFXAA.enabled = true;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ _passFXAA.enabled = false;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( _hasTransparentObject ) {
|
|
|
+
|
|
|
+ if ( _antialias ) {
|
|
|
+
|
|
|
+ _passForward.enabled = true;
|
|
|
+ _passCopy.enabled = false;
|
|
|
+ _passFXAA.enabled = true;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ _passForward.enabled = true;
|
|
|
+ _passCopy.enabled = true;
|
|
|
+ _passFXAA.enabled = false;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( _antialias ) {
|
|
|
+
|
|
|
+ _passForward.enabled = false;
|
|
|
+ _passCopy.enabled = false;
|
|
|
+ _passFXAA.enabled = true;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ _passForward.enabled = false;
|
|
|
+ _passCopy.enabled = false;
|
|
|
+ _passFXAA.enabled = false;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function createCacheData() {
|
|
|
+
|
|
|
+ return {
|
|
|
+ used: true,
|
|
|
+ keepAlive: _cacheKeepAlive,
|
|
|
+ count: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function cleanupCache( cache ) {
|
|
|
+
|
|
|
+ var keys = Object.keys( cache );
|
|
|
+
|
|
|
+ for ( var i = 0, il = keys.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var key = keys[ i ];
|
|
|
+
|
|
|
+ if ( cache[ key ].used === false ) {
|
|
|
+
|
|
|
+ cache[ key ].count ++;
|
|
|
+
|
|
|
+ if ( cache[ key ].keepAlive === false && cache[ key ].count > _removeThresholdCount ) {
|
|
|
+
|
|
|
+ delete cache[ key ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ cache[ key ].used = false;
|
|
|
+ cache[ key ].count = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function cleanupTable( table ) {
|
|
|
+
|
|
|
+ var keys = Object.keys( table );
|
|
|
+
|
|
|
+ for ( var i = 0, il = keys.length; i < il; i ++ ) {
|
|
|
+
|
|
|
+ var key = keys[ i ];
|
|
|
+
|
|
|
+ table[ key ] = undefined;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function cleanupCaches() {
|
|
|
+
|
|
|
+ cleanupCache( _lightScenesCache );
|
|
|
+ cleanupCache( _lightFullscreenScenesCache );
|
|
|
+ cleanupCache( _normalDepthMaterialsCache );
|
|
|
+ cleanupCache( _normalDepthShininessMaterialsCache );
|
|
|
+ cleanupCache( _colorMaterialsCache );
|
|
|
+ cleanupCache( _reconstructionMaterialsCache );
|
|
|
+ cleanupCache( _classicDeferredLightMaterialsCache );
|
|
|
+ cleanupCache( _lightPrePassMaterialsCache );
|
|
|
+ cleanupCache( _deferredLightsCache );
|
|
|
+
|
|
|
+ cleanupTable( _originalMaterialsTable );
|
|
|
+ cleanupTable( _originalOnBeforeRendersTable );
|
|
|
+ cleanupTable( _originalVisibleTable );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Classic Deferred Rendering
|
|
|
+ *
|
|
|
+ * 1) g-buffer normal + depth pass
|
|
|
+ *
|
|
|
+ * RGB: normal
|
|
|
+ * A: depth
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
+ *
|
|
|
+ * 1') g-buffer normal + depth pass + shininess
|
|
|
+ *
|
|
|
+ * RG: normal
|
|
|
+ * B: shininess
|
|
|
+ * A: depth
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderNormalDepth( scene, camera ) {
|
|
|
+
|
|
|
+ scene.traverse( setMaterialNormalDepth );
|
|
|
+
|
|
|
+ _passNormalDepth.scene = scene;
|
|
|
+ _passNormalDepth.camera = camera;
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = true;
|
|
|
+ _this.renderer.autoClearStencil = true;
|
|
|
+
|
|
|
+ _state.buffers.stencil.setTest( true );
|
|
|
+ _state.buffers.stencil.setFunc( _context.ALWAYS, 1, 0xffffffff );
|
|
|
+ _state.buffers.stencil.setOp( _context.REPLACE, _context.REPLACE, _context.REPLACE );
|
|
|
+
|
|
|
+ _compNormalDepth.render();
|
|
|
+
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Classic Deferred Rendering
|
|
|
+ *
|
|
|
+ * 2) g-buffer color pass
|
|
|
+ *
|
|
|
+ * R: diffuse
|
|
|
+ * G: emissive
|
|
|
+ * B: specular
|
|
|
+ * A: shininess
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderColor( scene, camera ) {
|
|
|
+
|
|
|
+ scene.traverse( setMaterialColor );
|
|
|
+
|
|
|
+ _passColor.scene = scene;
|
|
|
+ _passColor.camera = camera;
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
+
|
|
|
+ _state.buffers.stencil.setFunc( _context.EQUAL, 1, 0xffffffff );
|
|
|
+ _state.buffers.stencil.setOp( _context.KEEP, _context.KEEP, _context.KEEP );
|
|
|
+
|
|
|
+ _compColor.render();
|
|
|
+
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Classic Deferred Rendering
|
|
|
+ *
|
|
|
+ * 3) light pass
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderLight( scene, camera ) {
|
|
|
+
|
|
|
+ scene.traverse( addDeferredLightsToLightScene );
|
|
|
+
|
|
|
+ updateDeferredLightsInLightScene( _lightScene );
|
|
|
+ updateDeferredLightsInLightScene( _lightFullscreenScene );
|
|
|
+
|
|
|
+ _passLight.scene = _lightScene;
|
|
|
+ _passLight.camera = camera;
|
|
|
+
|
|
|
+ _passLightFullscreen.scene = _lightFullscreenScene;
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
+
|
|
|
+ _compLight.render();
|
|
|
+
|
|
|
+ _state.buffers.stencil.setTest( false );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
+ *
|
|
|
+ * 2') Light pre pass
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderLightPre( scene, camera ) {
|
|
|
+
|
|
|
+ scene.traverse( addDeferredLightsToLightScene );
|
|
|
+
|
|
|
+ updateDeferredLightsInLightScene( _lightScene );
|
|
|
+ updateDeferredLightsInLightScene( _lightFullscreenScene );
|
|
|
+
|
|
|
+ _passLight.scene = _lightScene;
|
|
|
+ _passLight.camera = camera;
|
|
|
+
|
|
|
+ _passLightFullscreen.scene = _lightFullscreenScene;
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
+
|
|
|
+ _state.buffers.stencil.setFunc( _context.EQUAL, 1, 0xffffffff );
|
|
|
+ _state.buffers.stencil.setOp( _context.KEEP, _context.KEEP, _context.KEEP );
|
|
|
+
|
|
|
+ _compLight.render();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Light Pre-Pass Rendering
|
|
|
+ *
|
|
|
+ * 3') Reconstruction pass
|
|
|
+ *
|
|
|
+ * Transprency handling:
|
|
|
+ * Here renders transparent objects with normal forward rendering.
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderReconstruction( scene, camera ) {
|
|
|
+
|
|
|
+ scene.traverse( setMaterialReconstruction );
|
|
|
+
|
|
|
+ _passReconstruction.scene = scene;
|
|
|
+ _passReconstruction.camera = camera;
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
+
|
|
|
+ _compReconstruction.render();
|
|
|
+
|
|
|
+ _state.buffers.stencil.setTest( false );
|
|
|
+
|
|
|
+ scene.traverse( restoreOriginalMaterial );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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.
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+ function renderFinal( scene, camera ) {
|
|
|
+
|
|
|
+ if ( ! _lightPrePass && _hasTransparentObject ) {
|
|
|
+
|
|
|
+ scene.traverse( setVisibleForForwardRendering );
|
|
|
+ scene.traverse( restoreOriginalOnBeforeRender );
|
|
|
+
|
|
|
+ _passForward.scene = scene;
|
|
|
+ _passForward.camera = camera;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ enableFinalPasses();
|
|
|
+
|
|
|
+ _this.renderer.autoClearDepth = false;
|
|
|
+ _this.renderer.autoClearStencil = false;
|
|
|
+
|
|
|
+ _compFinal.render();
|
|
|
+
|
|
|
+ if ( ! _lightPrePass && _hasTransparentObject ) {
|
|
|
+
|
|
|
+ scene.traverse( restoreVisible );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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 currentSceneAutoUpdate = scene.autoUpdate;
|
|
|
+ var currentAutoClearColor = this.renderer.autoClearColor;
|
|
|
+ var currentAutoClearDepth = this.renderer.autoClearDepth;
|
|
|
+ var currentAutoClearStencil = this.renderer.autoClearStencil;
|
|
|
+
|
|
|
+ _currentCamera = camera;
|
|
|
+
|
|
|
+ initLightScene( scene );
|
|
|
+
|
|
|
+ scene.autoUpdate = false;
|
|
|
+ scene.updateMatrixWorld();
|
|
|
+
|
|
|
+ _hasTransparentObject = false;
|
|
|
+
|
|
|
+ scene.traverse( saveOriginalOnBeforeRenderAndCheckTransparency );
|
|
|
+
|
|
|
+ updateDeferredCommonUniforms( camera );
|
|
|
+
|
|
|
+ renderNormalDepth( scene, camera );
|
|
|
+
|
|
|
+ if ( _lightPrePass ) {
|
|
|
+
|
|
|
+ renderLightPre( scene, camera );
|
|
|
+ renderReconstruction( scene, camera );
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ renderColor( scene, camera );
|
|
|
+ renderLight( scene, camera );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ renderFinal( scene, camera );
|
|
|
+
|
|
|
+ scene.traverse( restoreOriginalOnBeforeRender );
|
|
|
+
|
|
|
+ cleanupCaches();
|
|
|
+
|
|
|
+ scene.autoUpdate = currentSceneAutoUpdate;
|
|
|
+ this.renderer.autoClearColor = currentAutoClearColor;
|
|
|
+ this.renderer.autoClearDepth = currentAutoClearDepth;
|
|
|
+ this.renderer.autoClearStencil = currentAutoClearStencil;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ // initialize
|
|
|
+
|
|
|
+ init( parameters );
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+var 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" ),
|
|
|
+
|
|
|
+ // Refer to http://aras-p.info/texts/CompactNormalStorage.html
|
|
|
+ packNormal: [
|
|
|
+
|
|
|
+ "vec2 normal_to_vec2( vec3 normal ) {",
|
|
|
+
|
|
|
+ " return normal.xy / sqrt( normal.z * 8.0 + 8.0 ) + 0.5;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" ),
|
|
|
+
|
|
|
+ unpackVector2: [
|
|
|
+
|
|
|
+ "vec3 vec2_to_normal( vec2 data ) {",
|
|
|
+
|
|
|
+ " vec2 fenc = data * 4.0 - 2.0;",
|
|
|
+ " float f = dot( fenc, fenc );",
|
|
|
+ " float g = sqrt( 1.0 - f / 4.0 );",
|
|
|
+ " vec3 normal;",
|
|
|
+ " normal.xy = fenc * g;",
|
|
|
+ " normal.z = 1.0 - f / 2.0;",
|
|
|
+ " return normal;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].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" ),
|
|
|
+
|
|
|
+ packNormalDepthShininess: [
|
|
|
+
|
|
|
+ "vec4 packedNormalDepthShininess;",
|
|
|
+ "packedNormalDepthShininess.xy = normal_to_vec2( normal );",
|
|
|
+ "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 = vec2_to_normal( normalDepthMap.xy );",
|
|
|
+ "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" )
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+var ShaderDeferredCommon = {
|
|
|
+
|
|
|
+ commonUniforms: {
|
|
|
+
|
|
|
+ matProjInverse: new Uniform( new Matrix4() ),
|
|
|
+
|
|
|
+ viewWidth: new Uniform( 800 ),
|
|
|
+ viewHeight: new Uniform( 600 )
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+var ShaderDeferred = {
|
|
|
+
|
|
|
+ normalDepth: {
|
|
|
+
|
|
|
+ uniforms: {},
|
|
|
+
|
|
|
+ vertexShader: [
|
|
|
+
|
|
|
+ "varying vec3 vNormal;",
|
|
|
+ "varying vec4 vPosition;",
|
|
|
+
|
|
|
+ "#include <morphtarget_pars_vertex>",
|
|
|
+ "#include <skinning_pars_vertex>",
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ "#include <begin_vertex>",
|
|
|
+ "#include <beginnormal_vertex>",
|
|
|
+ "#include <skinbase_vertex>",
|
|
|
+ "#include <skinnormal_vertex>",
|
|
|
+ "#include <defaultnormal_vertex>",
|
|
|
+ "#include <morphtarget_vertex>",
|
|
|
+ "#include <skinning_vertex>",
|
|
|
+ "#include <project_vertex>",
|
|
|
+
|
|
|
+ " vNormal = normalize( transformedNormal );",
|
|
|
+ " vPosition = gl_Position;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" ),
|
|
|
+
|
|
|
+ fragmentShader: [
|
|
|
+
|
|
|
+ "varying vec3 vNormal;",
|
|
|
+ "varying vec4 vPosition;",
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ " vec3 normal = vNormal;",
|
|
|
+ " vec4 position = vPosition;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packNormalDepth" ],
|
|
|
+
|
|
|
+ " gl_FragColor = packedNormalDepth;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ color: {
|
|
|
+
|
|
|
+ uniforms: {
|
|
|
+
|
|
|
+ map: new Uniform( null ),
|
|
|
+ offsetRepeat: new Uniform( new Vector4( 0, 0, 1, 1 ) ),
|
|
|
+
|
|
|
+ diffuse: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ emissive: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ specular: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ shininess: new Uniform( 30.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ vertexShader: [
|
|
|
+
|
|
|
+ "#include <uv_pars_vertex>",
|
|
|
+ "#include <morphtarget_pars_vertex>",
|
|
|
+ "#include <skinning_pars_vertex>",
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ "#include <uv_vertex>",
|
|
|
+ "#include <begin_vertex>",
|
|
|
+ "#include <beginnormal_vertex>",
|
|
|
+ "#include <skinbase_vertex>",
|
|
|
+ "#include <skinnormal_vertex>",
|
|
|
+ "#include <defaultnormal_vertex>",
|
|
|
+ "#include <morphtarget_vertex>",
|
|
|
+ "#include <skinning_vertex>",
|
|
|
+ "#include <project_vertex>",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" ),
|
|
|
+
|
|
|
+ fragmentShader: [
|
|
|
+
|
|
|
+ "uniform vec3 diffuse;",
|
|
|
+ "uniform vec3 emissive;",
|
|
|
+ "uniform vec3 specular;",
|
|
|
+ "uniform float shininess;",
|
|
|
+
|
|
|
+ "#include <uv_pars_fragment>",
|
|
|
+ "#include <map_pars_fragment>",
|
|
|
+ DeferredShaderChunk[ "packVector3" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ " vec4 diffuseColor = vec4( diffuse, 1.0 );",
|
|
|
+ " vec3 emissiveColor = emissive;",
|
|
|
+ " vec3 specularColor = specular;",
|
|
|
+
|
|
|
+ "#include <map_fragment>",
|
|
|
+ DeferredShaderChunk[ "packColor" ],
|
|
|
+
|
|
|
+ " gl_FragColor = packedColor;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ emissiveLight: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerColor: new Uniform( null )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackColor" ],
|
|
|
+
|
|
|
+ " gl_FragColor = vec4( emissiveColor, 1.0 );",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( '\n' )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ pointLight: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepth: new Uniform( null ),
|
|
|
+ samplerColor: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightPositionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightIntensity: new Uniform( 1.0 ),
|
|
|
+ lightRadius: new Uniform( 1.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
|
|
|
+ " float distance = length( lightVector );",
|
|
|
+
|
|
|
+ " if ( distance > lightRadius ) discard;",
|
|
|
+
|
|
|
+ " lightVector = normalize( lightVector );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackColor" ],
|
|
|
+ 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 );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "combine" ],
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ spotLight: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepth: new Uniform( null ),
|
|
|
+ samplerColor: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightDirectionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightPositionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightAngle: new Uniform( 1.0 ),
|
|
|
+ lightIntensity: new Uniform( 1.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+ DeferredShaderChunk[ "unpackColor" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
|
|
|
+
|
|
|
+ " float rho = dot( lightDirectionVS, lightVector );",
|
|
|
+ " float rhoMax = cos( lightAngle );",
|
|
|
+
|
|
|
+ " 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeSpecular" ],
|
|
|
+
|
|
|
+ " const float attenuation = 1.0;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "combine" ],
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ directionalLight: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepth: new Uniform( null ),
|
|
|
+ samplerColor: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightDirectionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightIntensity: new Uniform( 1.0 )
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepth" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+ DeferredShaderChunk[ "unpackColor" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = normalize( lightDirectionVS );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeSpecular" ],
|
|
|
+
|
|
|
+ " const float attenuation = 1.0;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "combine" ],
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( '\n' )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ normalDepthShininess: {
|
|
|
+
|
|
|
+ uniforms: {
|
|
|
+
|
|
|
+ shininess: new Uniform( 30.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ vertexShader: [
|
|
|
+
|
|
|
+ "varying vec3 vNormal;",
|
|
|
+ "varying vec4 vPosition;",
|
|
|
+
|
|
|
+ "#include <morphtarget_pars_vertex>",
|
|
|
+ "#include <skinning_pars_vertex>",
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ "#include <begin_vertex>",
|
|
|
+ "#include <beginnormal_vertex>",
|
|
|
+ "#include <skinbase_vertex>",
|
|
|
+ "#include <skinnormal_vertex>",
|
|
|
+ "#include <defaultnormal_vertex>",
|
|
|
+ "#include <morphtarget_vertex>",
|
|
|
+ "#include <skinning_vertex>",
|
|
|
+ "#include <project_vertex>",
|
|
|
+
|
|
|
+ " vNormal = normalize( transformedNormal );",
|
|
|
+ " vPosition = gl_Position;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" ),
|
|
|
+
|
|
|
+ fragmentShader: [
|
|
|
+
|
|
|
+ "varying vec3 vNormal;",
|
|
|
+ "varying vec4 vPosition;",
|
|
|
+
|
|
|
+ "uniform float shininess;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packNormal" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ " vec3 normal = vNormal;",
|
|
|
+ " vec4 position = vPosition;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packNormalDepthShininess" ],
|
|
|
+
|
|
|
+ " gl_FragColor = packedNormalDepthShininess;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ pointLightPre: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepthShininess: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightPositionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightIntensity: new Uniform( 1.0 ),
|
|
|
+ lightRadius: new Uniform( 1.0 )
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+ DeferredShaderChunk[ "unpackVector2" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
|
|
|
+ " float distance = length( lightVector );",
|
|
|
+
|
|
|
+ " if ( distance > lightRadius ) discard;",
|
|
|
+
|
|
|
+ " lightVector = normalize( lightVector );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeSpecular" ],
|
|
|
+
|
|
|
+ " float attenuation = saturate( -distance / lightRadius + 1.0 );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packLight" ],
|
|
|
+
|
|
|
+ " gl_FragColor = packedLight;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ spotLightPre: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepthShininess: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightDirectionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightPositionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightAngle: new Uniform( 1.0 ),
|
|
|
+ lightIntensity: new Uniform( 1.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+ DeferredShaderChunk[ "unpackVector2" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
|
|
|
+
|
|
|
+ " float rho = dot( lightDirectionVS, lightVector );",
|
|
|
+ " float rhoMax = cos( lightAngle );",
|
|
|
+
|
|
|
+ " 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 );",
|
|
|
+
|
|
|
+ " }",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeSpecular" ],
|
|
|
+
|
|
|
+ " const float attenuation = 1.0;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packLight" ],
|
|
|
+
|
|
|
+ " gl_FragColor = spot * packedLight;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ directionalLightPre: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerNormalDepthShininess: new Uniform( null ),
|
|
|
+
|
|
|
+ lightColor: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ lightDirectionVS: new Uniform( new Vector3( 0, 1, 0 ) ),
|
|
|
+ lightIntensity: new Uniform( 1.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ 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;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+ DeferredShaderChunk[ "unpackVector2" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+ DeferredShaderChunk[ "unpackNormalDepthShininess" ],
|
|
|
+ DeferredShaderChunk[ "computeVertexPositionVS" ],
|
|
|
+
|
|
|
+ " vec3 lightVector = normalize( lightDirectionVS );",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeSpecular" ],
|
|
|
+
|
|
|
+ " const float attenuation = 1.0;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "packLight" ],
|
|
|
+
|
|
|
+ " gl_FragColor = packedLight;",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( '\n' )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ reconstruction: {
|
|
|
+
|
|
|
+ uniforms: Object.assign(
|
|
|
+
|
|
|
+ {
|
|
|
+
|
|
|
+ samplerLight: new Uniform( null ),
|
|
|
+
|
|
|
+ map: new Uniform( null ),
|
|
|
+ offsetRepeat: new Uniform( new Vector4( 0, 0, 1, 1 ) ),
|
|
|
+
|
|
|
+ diffuse: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ emissive: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ specular: new Uniform( new Color( 0x000000 ) ),
|
|
|
+ shininess: new Uniform( 30.0 )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ ShaderDeferredCommon[ 'commonUniforms' ]
|
|
|
+
|
|
|
+ ),
|
|
|
+
|
|
|
+ vertexShader: [
|
|
|
+
|
|
|
+ "#include <uv_pars_vertex>",
|
|
|
+ "#include <morphtarget_pars_vertex>",
|
|
|
+ "#include <skinning_pars_vertex>",
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ "#include <uv_vertex>",
|
|
|
+ "#include <begin_vertex>",
|
|
|
+ "#include <beginnormal_vertex>",
|
|
|
+ "#include <skinbase_vertex>",
|
|
|
+ "#include <skinnormal_vertex>",
|
|
|
+ "#include <defaultnormal_vertex>",
|
|
|
+ "#include <morphtarget_vertex>",
|
|
|
+ "#include <skinning_vertex>",
|
|
|
+ "#include <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;",
|
|
|
+
|
|
|
+ "#include <uv_pars_fragment>",
|
|
|
+ "#include <map_pars_fragment>",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "unpackFloat" ],
|
|
|
+
|
|
|
+ "void main() {",
|
|
|
+
|
|
|
+ " vec4 diffuseColor = vec4( diffuse, 1.0 );",
|
|
|
+ " vec3 emissiveColor = emissive;",
|
|
|
+ " vec3 specularColor = specular;",
|
|
|
+
|
|
|
+ DeferredShaderChunk[ "computeTextureCoord" ],
|
|
|
+
|
|
|
+ " vec4 light = texture2D( samplerLight, texCoord );",
|
|
|
+
|
|
|
+ "#include <map_fragment>",
|
|
|
+
|
|
|
+ " vec3 diffuseFinal = diffuseColor.rgb * light.rgb;",
|
|
|
+ " vec3 emissiveFinal = emissiveColor;",
|
|
|
+ " vec3 specularFinal = specularColor * light.rgb * light.a;",
|
|
|
+
|
|
|
+ " gl_FragColor = vec4( diffuseFinal + emissiveFinal + specularFinal, 1.0 );",
|
|
|
+
|
|
|
+ "}"
|
|
|
+
|
|
|
+ ].join( "\n" )
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // TODO: implement tone mapping
|
|
|
+ final: {
|
|
|
+
|
|
|
+ uniforms: {
|
|
|
+
|
|
|
+ samplerResult: new Uniform( 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" )
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+export { WebGLDeferredRenderer, DeferredShaderChunk, ShaderDeferredCommon, ShaderDeferred };
|