12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574 |
- /**
- * @author alteredq / http://alteredqualia.com/
- * @author MPanknin / http://www.redplant.de/
- * @author takahiro / https://github.com/takahirox
- *
- * Dependencies
- * - THREE.CopyShader
- * - THREE.RenderPass
- * - THREE.ShaderPass
- * - THREE.EffectComposer
- * - THREE.FXAAShader
- *
- * TODO
- * - reuse existing glsl
- * - shared material
- * - shadow
- * - optimization
- * - MRT (when it's available on Three.js)
- * - AmbientLight
- * - HemisphereLight
- * - PointLight (distance < 0)
- * - morphNormals
- * - BumpMap
- * - ToneMap
- * - envMap
- * - wrapAround
- * - addEffect
- */
- THREE.WebGLDeferredRenderer = function ( parameters ) {
- parameters = parameters || {};
- // private properties
- var _this = this;
- var _gl;
- var _width, _height;
- var _compColor, _compNormalDepth, _compLight, _compFinal;
- var _passColor, _passNormalDepth, _passLight, _passLightFullscreen, _passFinal, _passForward, _passCopy, _passFXAA;
- var _lightScene, _lightFullscreenScene;
- var _antialias = false, _hasTransparentObject = false;
- var _invisibleMaterial = new THREE.ShaderMaterial( { visible: false } );
- var _tmpVector3 = new THREE.Vector3();
- // external properties
- this.renderer;
- this.domElement;
- this.forwardRendering = false; // for debug
- // private methods
- var init = function ( parameters ) {
- _this.renderer = parameters.renderer !== undefined ? parameters.renderer : new THREE.WebGLRenderer( { antialias: false } );
- _this.domElement = _this.renderer.domElement;
- _gl = _this.renderer.context;
- _width = parameters.width !== undefined ? parameters.width : _this.renderer.getSize().width;
- _height = parameters.height !== undefined ? parameters.height : _this.renderer.getSize().height;
- var antialias = parameters.antialias !== undefined ? parameters.antialias : false;
- initPassFXAA();
- initPassNormalDepth();
- initPassColor();
- initPassLight();
- initPassFinal();
- _this.setSize( _width, _height );
- _this.setAntialias( antialias );
- };
- var initPassFXAA = function () {
- _passFXAA = new THREE.ShaderPass( THREE.FXAAShader );
- };
- var initPassNormalDepth = function () {
- _passNormalDepth = new THREE.RenderPass();
- _passNormalDepth.clear = true;
- var rt = new THREE.WebGLRenderTarget( _width, _height, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.NearestFilter,
- format: THREE.RGBAFormat,
- type: THREE.FloatType,
- stencilBuffer: true,
- depthTexture: new THREE.DepthTexture(
- _width,
- _height,
- THREE.UnsignedInt248Type,
- undefined,
- undefined,
- undefined,
- undefined,
- undefined,
- undefined,
- THREE.DepthStencilFormat
- )
- } );
- rt.texture.generateMipamps = false;
- _compNormalDepth = new THREE.EffectComposer( _this.renderer, rt );
- _compNormalDepth.addPass( _passNormalDepth );
- };
- var initPassColor = function () {
- _passColor = new THREE.RenderPass();
- _passColor.clear = true;
- var rt = new THREE.WebGLRenderTarget( _width, _height, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.NearestFilter,
- format: THREE.RGBAFormat,
- type: THREE.FloatType,
- depthTexture: _compNormalDepth.renderTarget2.depthTexture
- } );
- rt.texture.generateMipamps = false;
- _compColor = new THREE.EffectComposer( _this.renderer, rt );
- _compColor.addPass( _passColor );
- };
- var initPassLight = function () {
- _passLightFullscreen = new THREE.RenderPass();
- _passLightFullscreen.clear = true;
- _passLightFullscreen.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
- _passLight = new THREE.RenderPass();
- _passLight.clear = false;
- var rt = new THREE.WebGLRenderTarget( _width, _height, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.NearestFilter,
- format: THREE.RGBAFormat,
- type: THREE.FloatType,
- depthTexture: _compNormalDepth.renderTarget2.depthTexture
- } );
- rt.texture.generateMipamps = false;
- _compLight = new THREE.EffectComposer( _this.renderer, rt );
- _compLight.addPass( _passLightFullscreen );
- _compLight.addPass( _passLight );
- };
- var initPassFinal = function () {
- _passFinal = new THREE.ShaderPass( THREE.ShaderDeferred[ 'composite' ] );
- _passFinal.clear = true;
- _passFinal.uniforms.samplerLight.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 );
- var rt = new THREE.WebGLRenderTarget( _width, _height, {
- minFilter: THREE.NearestFilter,
- magFilter: THREE.LinearFilter,
- format: THREE.RGBFormat,
- type: THREE.UnsignedByteType,
- depthTexture: _compNormalDepth.renderTarget2.depthTexture
- } );
- rt.texture.generateMipamps = false;
- _compFinal = new THREE.EffectComposer( _this.renderer, rt );
- _compFinal.addPass( _passFinal );
- _compFinal.addPass( _passForward );
- _compFinal.addPass( _passCopy );
- _compFinal.addPass( _passFXAA );
- };
- var initLightScene = function ( scene ) {
- if ( scene.userData.lightScene === undefined ) {
- var lightScene = new THREE.Scene();
- lightScene.userData.lights = {};
- scene.userData.lightScene = lightScene;
- }
- if ( scene.userData.lightFullscreenScene === undefined ) {
- var lightScene = new THREE.Scene();
- lightScene.userData.lights = {};
- lightScene.userData.emissiveLight = createDeferredEmissiveLight();
- lightScene.add( lightScene.userData.emissiveLight );
- scene.userData.lightFullscreenScene = lightScene;
- }
- _lightScene = scene.userData.lightScene;
- _lightFullscreenScene = scene.userData.lightFullscreenScene;
- };
- var initDeferredProperties = function ( object ) {
- if ( object.userData.deferredInitialized === true ) return;
- if ( object.material ) initDeferredMaterials( object );
- if ( object instanceof THREE.Light ) initDeferredLight( object );
- object.userData.deferredInitialized = true;
- };
- var initDeferredMaterials = function ( object ) {
- if ( object.material instanceof THREE.MultiMaterial ) {
- var normalDepthMaterials = [];
- var colorMaterials = [];
- var forwardMaterials = [];
- var materials = object.material.materials;
- for ( var i = 0, il = materials.length; i < il; i ++ ) {
- normalDepthMaterials.push( createDeferredNormalDepthMaterial( materials[ i ] ) );
- colorMaterials.push( createDeferredColorMaterial( materials[ i ] ) );
- forwardMaterials.push( _invisibleMaterial );
- }
- object.userData.normalDepthMaterial = new THREE.MultiMaterial( normalDepthMaterials );
- object.userData.colorMaterial = new THREE.MultiMaterial( colorMaterials );
- object.userData.forwardMaterial = new THREE.MultiMaterial( forwardMaterials );
- } else {
- object.userData.normalDepthMaterial = createDeferredNormalDepthMaterial( object.material );
- object.userData.colorMaterial = createDeferredColorMaterial( object.material );
- }
- };
- var createDeferredNormalDepthMaterial = function ( originalMaterial ) {
- var shader = THREE.ShaderDeferred[ 'normalDepth' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- blending: THREE.NoBlending
- } );
- return material;
- };
- var updateDeferredNormalDepthMaterial = function ( material, originalMaterial ) {
- if ( originalMaterial.skinning !== undefined ) material.skinning = originalMaterial.skinning;
- if ( originalMaterial.morphTargets !== undefined ) material.morphTargets = originalMaterial.morphTargets;
- if ( originalMaterial.visible === true ) {
- material.visible = ! originalMaterial.transparent;
- } else {
- material.visible = false;
- }
- };
- var createDeferredColorMaterial = function ( originalMaterial ) {
- var shader = THREE.ShaderDeferred[ 'color' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- blending: THREE.NoBlending
- } );
- if ( originalMaterial.map !== undefined ) material.map = originalMaterial.map;
- return material;
- };
- var updateDeferredColorMaterial = function ( material, originalMaterial ) {
- var diffuse, emissive;
- if ( originalMaterial instanceof THREE.MeshBasicMaterial ) {
- emissive = originalMaterial.color;
- } else {
- diffuse = originalMaterial.color;
- emissive = originalMaterial.emissive;
- }
- var specular = originalMaterial.specular;
- var shininess = originalMaterial.shininess;
- var map = originalMaterial.map;
- if ( ( originalMaterial instanceof THREE.ShaderMaterial ) && originalMaterial.uniforms !== undefined ) {
- if ( diffuse === undefined && originalMaterial.uniforms.diffuse !== undefined ) diffuse = originalMaterial.uniforms.diffuse.value;
- if ( emissive === undefined && originalMaterial.uniforms.emissive !== undefined ) emissive = originalMaterial.uniforms.emissive.value;
- if ( specular === undefined && originalMaterial.uniforms.specular !== undefined ) specular = originalMaterial.uniforms.specular.value;
- if ( shininess === undefined && originalMaterial.uniforms.shininess !== undefined ) shininess = originalMaterial.uniforms.shininess.value;
- }
- if ( diffuse !== undefined ) material.uniforms.diffuse.value.copy( diffuse );
- if ( emissive !== undefined ) material.uniforms.emissive.value.copy( emissive );
- if ( specular !== undefined ) material.uniforms.specular.value.copy( specular );
- if ( shininess !== undefined ) material.uniforms.shininess.value = shininess;
- if ( map !== undefined ) {
- material.map = map;
- material.uniforms.map.value = map;
- }
- if ( originalMaterial.skinning !== undefined ) material.skinning = originalMaterial.skinning;
- if ( originalMaterial.morphTargets !== undefined ) material.morphTargets = originalMaterial.morphTargets;
- if ( originalMaterial.visible === true ) {
- material.visible = ! originalMaterial.transparent;
- } else {
- material.visible = false;
- }
- };
- var getForwardRenderingMaterial = function ( originalMaterial ) {
- if ( originalMaterial.transparent === true && originalMaterial.visible === true ) {
- return originalMaterial
- } else {
- return _invisibleMaterial;
- }
- };
- var initDeferredLight = function ( light ) {
- var deferredLight;
- if ( light instanceof THREE.PointLight ) {
- deferredLight = createDeferredPointLight( light );
- } else if ( light instanceof THREE.SpotLight ) {
- deferredLight = createDeferredSpotLight( light );
- } else if ( light instanceof THREE.DirectionalLight ) {
- deferredLight = createDeferredDirectionalLight( light );
- }
- light.userData.deferredLight = deferredLight;
- };
- var updateDeferredLight = function ( light, camera ) {
- var originalLight = light.userData.originalLight;
- if ( originalLight instanceof THREE.PointLight ) {
- updateDeferredPointLight( light, camera );
- } else if ( originalLight instanceof THREE.SpotLight ) {
- updateDeferredSpotLight( light, camera );
- } else if ( originalLight instanceof THREE.DirectionalLight ) {
- updateDeferredDirectionalLight( light, camera );
- }
- };
- var createDeferredEmissiveLight = function () {
- var shader = THREE.ShaderDeferred[ 'emissiveLight' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- blending: THREE.NoBlending,
- depthWrite: false
- } );
- material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
- var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
- var mesh = new THREE.Mesh( geometry, material );
- return mesh;
- };
- var updateDeferredEmissiveLight = function ( light, camera ) {
- var uniforms = light.material.uniforms;
- uniforms.viewWidth.value = _width;
- uniforms.viewHeight.value = _height;
- };
- var createDeferredPointLight = function ( light ) {
- var shader = THREE.ShaderDeferred[ 'pointLight' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- transparent: true,
- side: THREE.BackSide,
- blending: THREE.AdditiveBlending,
- depthWrite: false,
- depthFunc: THREE.GreaterEqualDepth
- } );
- material.uniforms.samplerNormalDepth.value = _compNormalDepth.renderTarget2.texture;
- material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
- var geometry = new THREE.SphereGeometry( 1, 16, 8 );
- var mesh = new THREE.Mesh( geometry, material );
- mesh.userData.originalLight = light;
- return mesh;
- };
- var updateDeferredPointLight = function ( light, camera ) {
- var originalLight = light.userData.originalLight;
- var distance = originalLight.distance;
- var uniforms = light.material.uniforms;
- uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
- uniforms.viewWidth.value = _width;
- uniforms.viewHeight.value = _height;
- uniforms.lightColor.value.copy( originalLight.color );
- if ( distance > 0 ) {
- light.scale.set( 1, 1, 1 ).multiplyScalar( distance );
- uniforms.lightRadius.value = distance;
- uniforms.lightIntensity.value = originalLight.intensity;
- uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( camera.matrixWorldInverse );
- light.position.setFromMatrixPosition( originalLight.matrixWorld );
- } else {
- uniforms.lightRadius.value = Infinity;
- }
- };
- var createDeferredSpotLight = function ( light ) {
- var shader = THREE.ShaderDeferred[ 'spotLight' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- transparent: true,
- blending: THREE.AdditiveBlending,
- depthWrite: false,
- depthTest: false
- } );
- material.uniforms.samplerNormalDepth.value = _compNormalDepth.renderTarget2.texture;
- material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
- var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
- var mesh = new THREE.Mesh( geometry, material );
- mesh.userData.originalLight = light;
- return mesh;
- };
- var updateDeferredSpotLight = function ( light, camera ) {
- var originalLight = light.userData.originalLight;
- var uniforms = light.material.uniforms;
- uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
- uniforms.viewWidth.value = _width;
- uniforms.viewHeight.value = _height;
- uniforms.lightAngle.value = originalLight.angle;
- uniforms.lightColor.value.copy( originalLight.color );
- uniforms.lightIntensity.value = originalLight.intensity;
- uniforms.lightPositionVS.value.setFromMatrixPosition( originalLight.matrixWorld ).applyMatrix4( camera.matrixWorldInverse );
- var vec = uniforms.lightDirectionVS.value;
- var vec2 = _tmpVector3;
- vec.setFromMatrixPosition( originalLight.matrixWorld );
- vec2.setFromMatrixPosition( originalLight.target.matrixWorld );
- vec.sub( vec2 ).normalize().transformDirection( camera.matrixWorldInverse );
- };
- var createDeferredDirectionalLight = function ( light ) {
- var shader = THREE.ShaderDeferred[ 'directionalLight' ];
- var material = new THREE.ShaderMaterial( {
- uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
- vertexShader: shader.vertexShader,
- fragmentShader: shader.fragmentShader,
- transparent: true,
- blending: THREE.AdditiveBlending,
- depthWrite: false,
- depthTest: false
- } );
- material.uniforms.samplerNormalDepth.value = _compNormalDepth.renderTarget2.texture;
- material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
- var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
- var mesh = new THREE.Mesh( geometry, material );
- mesh.userData.originalLight = light;
- return mesh;
- };
- var updateDeferredDirectionalLight = function ( light, camera ) {
- var originalLight = light.userData.originalLight;
- var uniforms = light.material.uniforms;
- uniforms.matProjInverse.value.getInverse( camera.projectionMatrix );
- uniforms.viewWidth.value = _width;
- uniforms.viewHeight.value = _height;
- uniforms.lightColor.value.copy( originalLight.color );
- uniforms.lightIntensity.value = originalLight.intensity;
- var vec = uniforms.lightDirectionVS.value;
- var vec2 = _tmpVector3;
- vec.setFromMatrixPosition( originalLight.matrixWorld );
- vec2.setFromMatrixPosition( originalLight.target.matrixWorld );
- vec.sub( vec2 ).normalize().transformDirection( camera.matrixWorldInverse );
- };
- var setMaterialNormalDepth = function ( object ) {
- if ( object.material === undefined ) return;
- if ( object.userData.normalDepthMaterial !== undefined ) {
- object.material = object.userData.normalDepthMaterial;
- if ( object.userData.originalMaterial instanceof THREE.MultiMaterial ) {
- for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
- updateDeferredNormalDepthMaterial( object.material.materials[ i ], object.userData.originalMaterial.materials[ i ] );
- }
- } else {
- updateDeferredNormalDepthMaterial( object.material, object.userData.originalMaterial );
- }
- }
- };
- var setMaterialColor = function ( object ) {
- if ( object.material === undefined ) return;
- if ( object.userData.colorMaterial !== undefined ) {
- object.material = object.userData.colorMaterial;
- if ( object.userData.originalMaterial instanceof THREE.MultiMaterial ) {
- for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
- updateDeferredColorMaterial( object.material.materials[ i ], object.userData.originalMaterial.materials[ i ] );
- }
- } else {
- updateDeferredColorMaterial( object.material, object.userData.originalMaterial );
- }
- }
- };
- var setMaterialForwardRendering = function ( object ) {
- if ( object.material === undefined ) return;
- if ( object.userData.originalMaterial instanceof THREE.MultiMaterial ) {
- object.material = object.userData.forwardMaterial;
- for ( var i = 0, il = object.userData.originalMaterial.materials.length; i < il; i ++ ) {
- object.material.materials[ i ] = getForwardRenderingMaterial( object.userData.originalMaterial.materials[ i ] );
- }
- } else {
- object.material = getForwardRenderingMaterial( object.userData.originalMaterial );
- }
- };
- var saveOriginalMaterialAndCheckTransparency = function ( object ) {
- if ( object.material !== undefined ) {
- object.userData.originalMaterial = object.material;
- if ( object.material instanceof THREE.MultiMaterial ) {
- for ( var i = 0, il = object.material.materials.length; i < il; i ++ ) {
- if ( object.material.materials[ i ].transparent === true ) _hasTransparentObject = true;
- }
- } else {
- if ( object.material.transparent === true ) _hasTransparentObject = true;
- }
- }
- };
- var restoreOriginalMaterial = function ( object ) {
- if ( object.userData.originalMaterial !== undefined ) object.material = object.userData.originalMaterial;
- };
- var enableCompositePasses = function () {
- 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;
- }
- }
- };
- var addDeferredLightsToLightScene = function ( object ) {
- var light = object.userData.deferredLight;
- if ( light !== undefined ) {
- var originalLight = light.userData.originalLight;
- var scene;
- if ( originalLight instanceof THREE.PointLight ) {
- scene = _lightScene;
- } else {
- scene = _lightFullscreenScene;
- }
- var lights = scene.userData.lights;
- if ( lights[ light.uuid ] === undefined ) {
- scene.add( light );
- lights[ light.uuid ] = {
- light: light,
- found: true
- };
- }
- lights[ light.uuid ].found = true;
- }
- };
- var updateDeferredLightsInLightScene = function ( scene, camera ) {
- var lights = scene.userData.lights;
- var keys = Object.keys( lights );
- for ( var i = 0, il = keys.length; i < il; i ++ ) {
- var key = keys[ i ];
- if ( lights[ key ].found === false ) {
- scene.remove( lights[ key ].light );
- delete lights[ key ];
- } else {
- updateDeferredLight( lights[ key ].light, camera );
- lights[ key ].found = false;
- }
- }
- };
- /*
- * 1) g-buffer normal + depth pass
- *
- * RGB: normal
- * A: depth
- */
- var renderNormalDepth = function ( scene, camera ) {
- scene.traverse( setMaterialNormalDepth );
- _passNormalDepth.scene = scene;
- _passNormalDepth.camera = camera;
- _this.renderer.autoClearDepth = true;
- _this.renderer.autoClearStencil = true;
- _gl.enable( _gl.STENCIL_TEST );
- _gl.stencilFunc( _gl.ALWAYS, 1, 0xffffffff );
- _gl.stencilOp( _gl.REPLACE, _gl.REPLACE, _gl.REPLACE );
- _compNormalDepth.render();
- };
- /*
- * 2) g-buffer color pass
- *
- * R: diffuse
- * G: emissive
- * B: specular
- * A: shininess
- */
- var renderColor = function ( scene, camera ) {
- scene.traverse( setMaterialColor );
- _passColor.scene = scene;
- _passColor.camera = camera;
- _this.renderer.autoClearDepth = false;
- _this.renderer.autoClearStencil = false;
- _gl.stencilFunc( _gl.EQUAL, 1, 0xffffffff );
- _gl.stencilOp( _gl.KEEP, _gl.KEEP, _gl.KEEP );
- _compColor.render();
- };
- /*
- * 3) light pass
- *
- * optimization:
- * Here renders PointLight only back face with stencil test.
- */
- var renderLight = function ( scene, camera ) {
- updateDeferredEmissiveLight( _lightFullscreenScene.userData.emissiveLight, camera );
- scene.traverse( addDeferredLightsToLightScene );
- updateDeferredLightsInLightScene( _lightScene, camera );
- updateDeferredLightsInLightScene( _lightFullscreenScene, camera );
- _passLight.scene = _lightScene;
- _passLight.camera = camera;
- _passLightFullscreen.scene = _lightFullscreenScene;
- _this.renderer.autoClearDepth = false;
- _this.renderer.autoClearStencil = false;
- _compLight.render();
- _gl.disable( _gl.STENCIL_TEST );
- };
- /*
- * 4) composite pass
- *
- * transparency handling:
- * If there's any transparent objects, here renders them on the deferred rendering result
- * with forward rendering. This may be the easist way but heavy.
- * We should consider any better ways someday.
- *
- * antialias handling:
- * Here uses postprocessing FXAA for antialias.
- */
- var renderComposite = function ( scene, camera ) {
- if ( _hasTransparentObject ) {
- scene.traverse( setMaterialForwardRendering );
- _passForward.scene = scene;
- _passForward.camera = camera;
- }
- enableCompositePasses();
- _this.renderer.autoClearDepth = false;
- _this.renderer.autoClearStencil = false;
- _compFinal.render();
- };
- // external APIs
- this.setSize = function ( width, height ) {
- _width = width;
- _height = height;
- this.renderer.setSize( _width, _height );
- _compNormalDepth.setSize( _width, _height );
- _compColor.setSize( _width, _height );
- _compLight.setSize( _width, _height );
- _compFinal.setSize( _width, _height );
- _compNormalDepth.renderTarget2.depthTexture.image.width = _width;
- _compNormalDepth.renderTarget2.depthTexture.image.height = _height;
- _compNormalDepth.renderTarget2.depthTexture.needsUpdate = true;
- _passFXAA.uniforms.resolution.value.set( 1 / _width, 1 / _height );
- };
- this.setAntialias = function ( enabled ) {
- _antialias = enabled;
- };
- this.render = function ( scene, camera ) {
- // for debug to compare with normal forward rendering
- if ( this.forwardRendering ) {
- this.renderer.render( scene, camera );
- return;
- }
- var tmpSceneAutoUpdate = scene.autoUpdate;
- var tmpAutoClearColor = this.renderer.autoClearColor;
- var tmpAutoClearDepth = this.renderer.autoClearDepth;
- var tmpAutoClearStencil = this.renderer.autoClearStencil;
- initLightScene( scene );
- scene.autoUpdate = false;
- scene.updateMatrixWorld();
- _hasTransparentObject = false;
- scene.traverse( initDeferredProperties );
- scene.traverse( saveOriginalMaterialAndCheckTransparency );
- renderNormalDepth( scene, camera );
- renderColor( scene, camera );
- renderLight( scene, camera );
- renderComposite( scene, camera );
- scene.traverse( restoreOriginalMaterial );
- scene.autoUpdate = tmpSceneAutoUpdate;
- this.renderer.autoClearColor = tmpAutoClearColor;
- this.renderer.autoClearDepth = tmpAutoClearDepth;
- this.renderer.autoClearStencil = tmpAutoClearStencil;
- };
- // initialize
- init( parameters );
- };
- THREE.DeferredShaderChunk = {
- packVector3: [
- "float vec3_to_float( vec3 data ) {",
- "const float unit = 255.0/256.0;",
- "highp float compressed = fract( data.x * unit ) + floor( data.y * unit * 255.0 ) + floor( data.z * unit * 255.0 ) * 255.0;",
- "return compressed;",
- "}"
- ].join( "\n" ),
- unpackFloat: [
- "vec3 float_to_vec3( float data ) {",
- "const float unit = 255.0;",
- "vec3 uncompressed;",
- "uncompressed.x = fract( data );",
- "float zInt = floor( data / unit );",
- "uncompressed.z = fract( zInt / unit );",
- "uncompressed.y = fract( floor( data - ( zInt * unit ) ) / unit );",
- "return uncompressed;",
- "}"
- ].join( "\n" ),
- computeTextureCoord: [
- "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"
- ].join( "\n" ),
- packNormalDepth: [
- "vec4 packedNormalDepth;",
- "packedNormalDepth.xyz = normal * 0.5 + 0.5;",
- "packedNormalDepth.w = position.z / position.w;",
- ].join( "\n" ),
- unpackNormalDepth: [
- "vec4 normalDepthMap = texture2D( samplerNormalDepth, texCoord );",
- "float depth = normalDepthMap.w;",
- "if ( depth == 0.0 ) discard;",
- "vec3 normal = normalDepthMap.xyz * 2.0 - 1.0;"
- ].join( "\n" ),
- packColor: [
- "vec4 packedColor;",
- "packedColor.x = vec3_to_float( diffuseColor );",
- "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" ),
- 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" ),
- computeSpecular: [
- "vec3 halfVector = normalize( lightVector - normalize( vertexPositionVS.xyz ) );",
- "float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );",
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
- "vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightVector, halfVector ), 5.0 );",
- "vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuseColor * max( dot( normal, lightVector ), 0.0 ) * specularNormalization;"
- ].join( "\n" ),
- combine: [
- "gl_FragColor = vec4( lightIntensity * lightColor * ( diffuseColor * max( dot( normal, lightVector ), 0.0 ) + specular ), attenuation );"
- ].join( "\n" )
- };
- THREE.ShaderDeferred = {
- normalDepth: {
- uniforms: {},
- vertexShader: [
- "varying vec3 vNormal;",
- "varying vec4 vPosition;",
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- "void main() {",
- THREE.ShaderChunk[ "begin_vertex" ],
- THREE.ShaderChunk[ "beginnormal_vertex" ],
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
- THREE.ShaderChunk[ "defaultnormal_vertex" ],
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "project_vertex" ],
- "vNormal = normalize( normalMatrix * objectNormal );",
- "vPosition = gl_Position;",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "varying vec3 vNormal;",
- "varying vec4 vPosition;",
- "void main() {",
- "vec3 normal = vNormal;",
- "vec4 position = vPosition;",
- THREE.DeferredShaderChunk[ "packNormalDepth" ],
- "gl_FragColor = packedNormalDepth;",
- "}"
- ].join( "\n" )
- },
- color: {
- uniforms: {
- map: { type: "t", value: null },
- offsetRepeat: { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
- diffuse: { type: "c", value: new THREE.Color( 0x000000 ) },
- emissive: { type: "c", value: new THREE.Color( 0x000000 ) },
- specular: { type: "c", value: new THREE.Color( 0x000000 ) },
- shininess: { type: "f", value: 30.0 }
- },
- vertexShader: [
- THREE.ShaderChunk[ "uv_pars_vertex" ],
- THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
- THREE.ShaderChunk[ "skinning_pars_vertex" ],
- "void main() {",
- THREE.ShaderChunk[ "uv_vertex" ],
- THREE.ShaderChunk[ "begin_vertex" ],
- THREE.ShaderChunk[ "beginnormal_vertex" ],
- THREE.ShaderChunk[ "skinbase_vertex" ],
- THREE.ShaderChunk[ "skinnormal_vertex" ],
- THREE.ShaderChunk[ "defaultnormal_vertex" ],
- THREE.ShaderChunk[ "morphtarget_vertex" ],
- THREE.ShaderChunk[ "skinning_vertex" ],
- THREE.ShaderChunk[ "project_vertex" ],
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "uniform vec3 diffuse;",
- "uniform vec3 emissive;",
- "uniform vec3 specular;",
- "uniform float shininess;",
- THREE.ShaderChunk[ "uv_pars_fragment" ],
- THREE.ShaderChunk[ "map_pars_fragment" ],
- THREE.DeferredShaderChunk[ "packVector3" ],
- "void main() {",
- "vec3 diffuseColor = diffuse;",
- "vec3 emissiveColor = emissive;",
- "vec3 specularColor = specular;",
- THREE.ShaderChunk[ "map_fragment" ],
- THREE.DeferredShaderChunk[ "packColor" ],
- "gl_FragColor = packedColor;",
- "}"
- ].join( "\n" )
- },
- emissiveLight: {
- uniforms: {
- samplerColor: { type: "t", value: null },
- viewWidth: { type: "f", value: 800 },
- viewHeight: { type: "f", value: 600 }
- },
- vertexShader: [
- "void main() { ",
- "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
- "}"
- ].join( '\n' ),
- fragmentShader: [
- "uniform sampler2D samplerColor;",
- "uniform float viewHeight;",
- "uniform float viewWidth;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- "void main() {",
- THREE.DeferredShaderChunk[ "computeTextureCoord" ],
- THREE.DeferredShaderChunk[ "unpackColor" ],
- "gl_FragColor = vec4( emissiveColor, 1.0 );",
- "}"
- ].join( '\n' )
- },
- pointLight: {
- uniforms: {
- samplerNormalDepth: { type: "t", value: null },
- samplerColor: { type: "t", value: null },
- matProjInverse: { type: "m4", value: new THREE.Matrix4() },
- viewWidth: { type: "f", value: 800 },
- viewHeight: { type: "f", value: 600 },
- lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
- lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
- lightIntensity: { type: "f", value: 1.0 },
- lightRadius: { type: "f", value: 1.0 }
- },
- vertexShader: [
- "void main() {",
- "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "uniform sampler2D samplerNormalDepth;",
- "uniform sampler2D samplerColor;",
- "uniform float viewHeight;",
- "uniform float viewWidth;",
- "uniform vec3 lightColor;",
- "uniform vec3 lightPositionVS;",
- "uniform float lightIntensity;",
- "uniform float lightRadius;",
- "uniform mat4 matProjInverse;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- "void main() {",
- THREE.DeferredShaderChunk[ "computeTextureCoord" ],
- THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
- THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
- "vec3 lightVector = lightPositionVS - vertexPositionVS.xyz;",
- "float distance = length( lightVector );",
- "if ( distance > lightRadius ) discard;",
- "lightVector = normalize( lightVector );",
- THREE.DeferredShaderChunk[ "unpackColor" ],
- THREE.DeferredShaderChunk[ "computeSpecular" ],
- "//float cutoff = 0.3;",
- "//float denom = distance / lightRadius + 1.0;",
- "//float attenuation = 1.0 / ( denom * denom );",
- "//attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );",
- "//attenuation = max( attenuation, 0.0 );",
- "//attenuation *= attenuation;",
- "//diffuseColor *= saturate( -distance / lightRadius + 1.0 );",
- "//float attenuation = 1.0;",
- "float attenuation = saturate( -distance / lightRadius + 1.0 );",
- THREE.DeferredShaderChunk[ "combine" ],
- "}"
- ].join( "\n" )
- },
- spotLight: {
- uniforms: {
- samplerNormalDepth: { type: "t", value: null },
- samplerColor: { type: "t", value: null },
- matProjInverse: { type: "m4", value: new THREE.Matrix4() },
- viewWidth: { type: "f", value: 800 },
- viewHeight: { type: "f", value: 600 },
- lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
- lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
- lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
- lightAngle: { type: "f", value: 1.0 },
- lightIntensity: { type: "f", value: 1.0 }
- },
- vertexShader: [
- "void main() { ",
- "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "uniform sampler2D samplerNormalDepth;",
- "uniform sampler2D samplerColor;",
- "uniform float viewHeight;",
- "uniform float viewWidth;",
- "uniform vec3 lightColor;",
- "uniform vec3 lightPositionVS;",
- "uniform vec3 lightDirectionVS;",
- "uniform float lightAngle;",
- "uniform float lightIntensity;",
- "uniform mat4 matProjInverse;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- "void main() {",
- THREE.DeferredShaderChunk[ "computeTextureCoord" ],
- THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
- THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
- THREE.DeferredShaderChunk[ "unpackColor" ],
- "vec3 lightVector = normalize( lightPositionVS.xyz - vertexPositionVS.xyz );",
- "float rho = dot( lightDirectionVS, lightVector );",
- "float rhoMax = cos( lightAngle * 0.5 );",
- "if ( rho <= rhoMax ) discard;",
- "float theta = rhoMax + 0.0001;",
- "float phi = rhoMax + 0.05;",
- "float falloff = 4.0;",
- "float spot = 0.0;",
- "if ( rho >= phi ) {",
- "spot = 1.0;",
- "} else if ( rho <= theta ) {",
- "spot = 0.0;",
- "} else { ",
- "spot = pow( ( rho - theta ) / ( phi - theta ), falloff );",
- "}",
- "diffuseColor *= spot;",
- THREE.DeferredShaderChunk[ "computeSpecular" ],
- "const float attenuation = 1.0;",
- THREE.DeferredShaderChunk[ "combine" ],
- "}"
- ].join( "\n" )
- },
- directionalLight: {
- uniforms: {
- samplerNormalDepth: { type: "t", value: null },
- samplerColor: { type: "t", value: null },
- matProjInverse: { type: "m4", value: new THREE.Matrix4() },
- viewWidth: { type: "f", value: 800 },
- viewHeight: { type: "f", value: 600 },
- lightColor: { type: "c", value: new THREE.Color( 0x000000 ) },
- lightDirectionVS : { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
- lightIntensity: { type: "f", value: 1.0 }
- },
- vertexShader: [
- "void main() { ",
- "gl_Position = vec4( sign( position.xy ), 0.0, 1.0 );",
- "}"
- ].join( '\n' ),
- fragmentShader: [
- "uniform sampler2D samplerNormalDepth;",
- "uniform sampler2D samplerColor;",
- "uniform float viewHeight;",
- "uniform float viewWidth;",
- "uniform vec3 lightColor;",
- "uniform vec3 lightDirectionVS;",
- "uniform float lightIntensity;",
- "uniform mat4 matProjInverse;",
- THREE.DeferredShaderChunk[ "unpackFloat" ],
- "void main() {",
- THREE.DeferredShaderChunk[ "computeTextureCoord" ],
- THREE.DeferredShaderChunk[ "unpackNormalDepth" ],
- THREE.DeferredShaderChunk[ "computeVertexPositionVS" ],
- THREE.DeferredShaderChunk[ "unpackColor" ],
- "vec3 lightVector = normalize( lightDirectionVS );",
- THREE.DeferredShaderChunk[ "computeSpecular" ],
- "const float attenuation = 1.0;",
- THREE.DeferredShaderChunk[ "combine" ],
- "}"
- ].join( '\n' ),
- },
- composite: {
- uniforms: {
- samplerLight: { type: "t", value: null }
- },
- vertexShader: [
- "varying vec2 texCoord;",
- "void main() {",
- "vec4 pos = vec4( sign( position.xy ), 0.0, 1.0 );",
- "texCoord = pos.xy * vec2( 0.5 ) + 0.5;",
- "gl_Position = pos;",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "varying vec2 texCoord;",
- "uniform sampler2D samplerLight;",
- "void main() {",
- "gl_FragColor = texture2D( samplerLight, texCoord );",
- "}"
- ].join( "\n" )
- }
- };
|