123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520 |
- /**
- * @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
- * - 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 _currentCamera;
- var _lightScene, _lightFullscreenScene;
- var _antialias = false;
- var _hasTransparentObject = false;
- var _lightPrePass = false;
- var _cacheKeepAlive = false;
- var _tmpMaterial = new THREE.ShaderMaterial( { visible: false } );
- var _tmpVector3 = new THREE.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 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;
- 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 THREE.DepthTexture(
- _width,
- _height,
- THREE.UnsignedInt248Type,
- undefined,
- undefined,
- undefined,
- undefined,
- undefined,
- undefined,
- THREE.DepthStencilFormat
- );
- }
- function initPassNormalDepth() {
- _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 );
- }
- function initPassColor() {
- _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 );
- }
- function initPassLight() {
- _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 );
- }
- function initPassReconstruction() {
- _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 );
- }
- function initPassFinal() {
- _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 );
- }
- function initLightScene( scene ) {
- var lightSceneData = _lightScenesCache[ scene.uuid ];
- var lightFullscreenSceneData = _lightFullscreenScenesCache[ scene.uuid ];
- if ( lightSceneData === undefined ) {
- var s = new THREE.Scene();
- s.userData.lights = {};
- lightSceneData = createCacheData();
- lightSceneData.scene = s;
- _lightScenesCache[ scene.uuid ] = lightSceneData;
- }
- if ( lightFullscreenSceneData === undefined ) {
- var s = new THREE.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( originalMaterial ) {
- var shader = ( _lightPrePass ) ? THREE.ShaderDeferred[ 'normalDepthShininess' ] : THREE.ShaderDeferred[ 'normalDepth' ];
- return new THREE.ShaderMaterial( {
- uniforms: Object.assign( {}, shader.uniforms ),
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- blending: THREE.NoBlending
- } );
- }
- function updateDeferredNormalDepthMaterial( material, originalMaterial ) {
- 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, group ) {
- 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 = THREE.ShaderDeferred[ 'color' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: Object.assign( {}, shader.uniforms ),
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- blending: THREE.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.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, group ) {
- 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 = THREE.ShaderDeferred[ 'reconstruction' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: Object.assign( {}, shader.uniforms ),
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- blending: THREE.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 = THREE.ShaderDeferred[ 'emissiveLight' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: Object.assign( {}, shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- blending: THREE.NoBlending,
- depthWrite: false
- } );
- var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
- var mesh = new THREE.Mesh( geometry, material );
- mesh.onBeforeRender = function ( renderer, scene, camera, geometry, material, group ) {
- 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 THREE.Mesh( geometry, _tmpMaterial );
- mesh.userData.originalLight = light;
- return mesh;
- }
- function createDeferredLightShaderMaterial( shader ) {
- var material = new THREE.ShaderMaterial( {
- uniforms: Object.assign( {}, shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- transparent: true,
- blending: THREE.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 THREE.SphereGeometry( 1, 16, 8 ) );
- mesh.onBeforeRender = updateDeferredPointLightUniforms;
- return mesh;
- }
- /*
- * optimization:
- * Renders PointLight only back face with stencil test.
- */
- function createDeferredPointLightMaterial() {
- var shader = ( _lightPrePass ) ? THREE.ShaderDeferred[ 'pointLightPre' ] : THREE.ShaderDeferred[ 'pointLight' ];
- var material = createDeferredLightShaderMaterial( shader );
- material.side = THREE.BackSide;
- material.depthFunc = THREE.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, group ) {
- 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 THREE.PlaneBufferGeometry( 2, 2 ) );
- mesh.onBeforeRender = updateDeferredSpotLightUniforms;
- return mesh;
- }
- function createDeferredSpotLightMaterial() {
- var shader = ( _lightPrePass ) ? THREE.ShaderDeferred[ 'spotLightPre' ] : THREE.ShaderDeferred[ 'spotLight' ];
- var material = createDeferredLightShaderMaterial( shader );
- material.depthTest = false;
- return material;
- }
- function updateDeferredSpotLightUniforms( renderer, scene, camera, geometry, material, group ) {
- 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 THREE.PlaneBufferGeometry( 2, 2 ) );
- mesh.onBeforeRender = updateDeferredDirectionalLightUniforms;
- return mesh;
- }
- function createDeferredDirectionalLightMaterial() {
- var shader = ( _lightPrePass ) ? THREE.ShaderDeferred[ 'directionalLightPre' ] : THREE.ShaderDeferred[ 'directionalLight' ];
- var material = createDeferredLightShaderMaterial( shader );
- material.depthTest = false;
- return material;
- }
- function updateDeferredDirectionalLightUniforms( renderer, scene, camera, geometry, material, group ) {
- 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 = THREE.ShaderDeferredCommon[ 'commonUniforms' ];
- uniforms.viewWidth.value = _width;
- uniforms.viewHeight.value = _height;
- uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
- }
- function enableFinalPasses() {
- 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;
- }
- }
- }
- }
- 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;
- _gl.enable( _gl.STENCIL_TEST );
- _gl.stencilFunc( _gl.ALWAYS, 1, 0xffffffff );
- _gl.stencilOp( _gl.REPLACE, _gl.REPLACE, _gl.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;
- _gl.stencilFunc( _gl.EQUAL, 1, 0xffffffff );
- _gl.stencilOp( _gl.KEEP, _gl.KEEP, _gl.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();
- _gl.disable( _gl.STENCIL_TEST );
- }
- /*
- * 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;
- _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.
- */
- function renderReconstruction( 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 );
- 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 );
- };
- 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" ),
- // 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" )
- };
- THREE.ShaderDeferredCommon = {
- commonUniforms: {
- matProjInverse: new THREE.Uniform( new THREE.Matrix4() ),
- viewWidth: new THREE.Uniform( 800 ),
- viewHeight: new THREE.Uniform( 600 )
- }
- };
- 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: new THREE.Uniform( null ),
- offsetRepeat: new THREE.Uniform( new THREE.Vector4( 0, 0, 1, 1 ) ),
- diffuse: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- emissive: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- specular: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- shininess: new THREE.Uniform( 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: Object.assign(
- {
- samplerColor: new THREE.Uniform( null )
- },
- THREE.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;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- "void main() {",
- THREE.DeferredShaderChunk[ "computeTextureCoord" ],
- THREE.DeferredShaderChunk[ "unpackColor" ],
- " gl_FragColor = vec4( emissiveColor, 1.0 );",
- "}"
- ].join( '\n' )
- },
- pointLight: {
- uniforms: Object.assign(
- {
- samplerNormalDepth: new THREE.Uniform( null ),
- samplerColor: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightPositionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightIntensity: new THREE.Uniform( 1.0 ),
- lightRadius: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- 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: Object.assign(
- {
- samplerNormalDepth: new THREE.Uniform( null ),
- samplerColor: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightDirectionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightPositionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightAngle: new THREE.Uniform( 1.0 ),
- lightIntensity: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- 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 );",
- " 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: Object.assign(
- {
- samplerNormalDepth: new THREE.Uniform( null ),
- samplerColor: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightDirectionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightIntensity: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- 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: new THREE.Uniform( 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[ "packNormal" ],
- "void main() {",
- " vec3 normal = vNormal;",
- " vec4 position = vPosition;",
- THREE.DeferredShaderChunk[ "packNormalDepthShininess" ],
- " gl_FragColor = packedNormalDepthShininess;",
- "}"
- ].join( "\n" )
- },
- pointLightPre: {
- uniforms: Object.assign(
- {
- samplerNormalDepthShininess: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightPositionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightIntensity: new THREE.Uniform( 1.0 ),
- lightRadius: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- THREE.DeferredShaderChunk[ "unpackVector2" ],
- "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: Object.assign(
- {
- samplerNormalDepthShininess: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightDirectionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightPositionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightAngle: new THREE.Uniform( 1.0 ),
- lightIntensity: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- THREE.DeferredShaderChunk[ "unpackVector2" ],
- "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 );",
- " 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: Object.assign(
- {
- samplerNormalDepthShininess: new THREE.Uniform( null ),
- lightColor: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- lightDirectionVS: new THREE.Uniform( new THREE.Vector3( 0, 1, 0 ) ),
- lightIntensity: new THREE.Uniform( 1.0 )
- },
- THREE.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;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- THREE.DeferredShaderChunk[ "unpackVector2" ],
- "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: Object.assign(
- {
- samplerLight: new THREE.Uniform( null ),
- map: new THREE.Uniform( null ),
- offsetRepeat: new THREE.Uniform( new THREE.Vector4( 0, 0, 1, 1 ) ),
- diffuse: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- emissive: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- specular: new THREE.Uniform( new THREE.Color( 0x000000 ) ),
- shininess: new THREE.Uniform( 30.0 )
- },
- THREE.ShaderDeferredCommon[ 'commonUniforms' ]
- ),
- 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;",
- " gl_FragColor = vec4( diffuseFinal + emissiveFinal + specularFinal, 1.0 );",
- "}"
- ].join( "\n" )
- },
- // TODO: implement tone mapping
- final: {
- uniforms: {
- samplerResult: new THREE.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" )
- }
- };
|