2
0

DeferredHelper.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /**
  2. * @author alteredq / http://alteredqualia.com/
  3. * @author MPanknin / http://www.redplant.de/
  4. */
  5. THREE.DeferredHelper = function ( parameters ) {
  6. var width = parameters.width;
  7. var height = parameters.height;
  8. var renderer = parameters.renderer;
  9. var additiveSpecular = parameters.additiveSpecular;
  10. //
  11. var black = new THREE.Color( 0x000000 );
  12. var colorShader = THREE.ShaderDeferred[ "color" ];
  13. var normalShader = THREE.ShaderDeferred[ "normals" ];
  14. var bumpShader = THREE.ShaderDeferred[ "bump" ];
  15. var clipDepthShader = THREE.ShaderDeferred[ "clipDepth" ];
  16. //
  17. var emissiveLightShader = THREE.ShaderDeferred[ "emissiveLight" ];
  18. var pointLightShader = THREE.ShaderDeferred[ "pointLight" ];
  19. var directionalLightShader = THREE.ShaderDeferred[ "directionalLight" ];
  20. var compositeShader = THREE.ShaderDeferred[ "composite" ];
  21. //
  22. var compColor, compNormal, compDepth, compLight, compFinal;
  23. var passColor, passNormal, passDepth, passLightFullscreen, passLightProxy, compositePass;
  24. var effectFXAA;
  25. //
  26. var lightSceneFullscreen, lightSceneProxy;
  27. var lightMaterials = [];
  28. //
  29. var defaultNormalMaterial = new THREE.ShaderMaterial( {
  30. uniforms: THREE.UniformsUtils.clone( normalShader.uniforms ),
  31. vertexShader: normalShader.vertexShader,
  32. fragmentShader: normalShader.fragmentShader
  33. } );
  34. var defaultDepthMaterial = new THREE.ShaderMaterial( {
  35. uniforms: THREE.UniformsUtils.clone( clipDepthShader.uniforms ),
  36. vertexShader: clipDepthShader.vertexShader,
  37. fragmentShader: clipDepthShader.fragmentShader
  38. } );
  39. //
  40. var rtParamsFloatLinear = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
  41. format: THREE.RGBAFormat, type: THREE.FloatType };
  42. var rtParamsFloatNearest = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
  43. format: THREE.RGBAFormat, type: THREE.FloatType };
  44. var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.LinearFilter, stencilBuffer: false,
  45. format: THREE.RGBFormat, type: THREE.UnsignedByteType };
  46. //
  47. var initDeferredMaterials = function ( object ) {
  48. var originalMaterial = object.material;
  49. // color material
  50. // -----------------
  51. // diffuse color
  52. // specular color
  53. // shininess
  54. // diffuse map
  55. // vertex colors
  56. // alphaTest
  57. // morphs
  58. var uniforms = THREE.UniformsUtils.clone( colorShader.uniforms );
  59. var defines = { "USE_MAP": !! originalMaterial.map, "GAMMA_INPUT": true };
  60. var material = new THREE.ShaderMaterial( {
  61. fragmentShader: colorShader.fragmentShader,
  62. vertexShader: colorShader.vertexShader,
  63. uniforms: uniforms,
  64. defines: defines,
  65. shading: originalMaterial.shading
  66. } );
  67. if ( originalMaterial instanceof THREE.MeshBasicMaterial ) {
  68. var diffuse = black;
  69. var emissive = originalMaterial.color;
  70. } else {
  71. var diffuse = originalMaterial.color;
  72. var emissive = originalMaterial.emissive !== undefined ? originalMaterial.emissive : black;
  73. }
  74. var specular = originalMaterial.specular !== undefined ? originalMaterial.specular : black;
  75. var shininess = originalMaterial.shininess !== undefined ? originalMaterial.shininess : 1;
  76. uniforms.emissive.value.copy( emissive );
  77. uniforms.diffuse.value.copy( diffuse );
  78. uniforms.specular.value.copy( specular );
  79. uniforms.shininess.value = shininess;
  80. uniforms.map.value = originalMaterial.map;
  81. material.vertexColors = originalMaterial.vertexColors;
  82. material.morphTargets = originalMaterial.morphTargets;
  83. material.morphNormals = originalMaterial.morphNormals;
  84. material.alphaTest = originalMaterial.alphaTest;
  85. if ( originalMaterial.bumpMap ) {
  86. var offset = originalMaterial.bumpMap.offset;
  87. var repeat = originalMaterial.bumpMap.repeat;
  88. uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
  89. }
  90. object.properties.colorMaterial = material;
  91. // normal material
  92. // -----------------
  93. // vertex normals
  94. // morph normals
  95. // bump map
  96. // bump scale
  97. if ( originalMaterial.bumpMap ) {
  98. var uniforms = THREE.UniformsUtils.clone( bumpShader.uniforms );
  99. var normalMaterial = new THREE.ShaderMaterial( {
  100. uniforms: uniforms,
  101. vertexShader: bumpShader.vertexShader,
  102. fragmentShader: bumpShader.fragmentShader,
  103. defines: { "USE_BUMPMAP": true }
  104. } );
  105. uniforms.bumpMap.value = originalMaterial.bumpMap;
  106. uniforms.bumpScale.value = originalMaterial.bumpScale;
  107. var offset = originalMaterial.bumpMap.offset;
  108. var repeat = originalMaterial.bumpMap.repeat;
  109. uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
  110. object.properties.normalMaterial = normalMaterial;
  111. } else if ( originalMaterial.morphTargets ) {
  112. var normalMaterial = new THREE.ShaderMaterial( {
  113. uniforms: THREE.UniformsUtils.clone( normalShader.uniforms ),
  114. vertexShader: normalShader.vertexShader,
  115. fragmentShader: normalShader.fragmentShader,
  116. shading: originalMaterial.shading
  117. } );
  118. normalMaterial.morphTargets = originalMaterial.morphTargets;
  119. normalMaterial.morphNormals = originalMaterial.morphNormals;
  120. object.properties.normalMaterial = normalMaterial;
  121. } else {
  122. object.properties.normalMaterial = defaultNormalMaterial;
  123. }
  124. // depth material
  125. if ( originalMaterial.morphTargets ) {
  126. var depthMaterial = new THREE.ShaderMaterial( {
  127. uniforms: THREE.UniformsUtils.clone( clipDepthShader.uniforms ),
  128. vertexShader: clipDepthShader.vertexShader,
  129. fragmentShader: clipDepthShader.fragmentShader
  130. } );
  131. depthMaterial.morphTargets = originalMaterial.morphTargets;
  132. object.properties.depthMaterial = depthMaterial;
  133. } else {
  134. object.properties.depthMaterial = defaultDepthMaterial;
  135. }
  136. };
  137. var createDeferredPointLight = function ( light ) {
  138. // setup light material
  139. var materialLight = new THREE.ShaderMaterial( {
  140. uniforms: THREE.UniformsUtils.clone( pointLightShader.uniforms ),
  141. vertexShader: pointLightShader.vertexShader,
  142. fragmentShader: pointLightShader.fragmentShader,
  143. defines: { "ADDITIVE_SPECULAR": additiveSpecular },
  144. blending: THREE.AdditiveBlending,
  145. depthWrite: false,
  146. transparent: true
  147. } );
  148. materialLight.uniforms[ "lightPos" ].value = light.position;
  149. materialLight.uniforms[ "lightRadius" ].value = light.distance;
  150. materialLight.uniforms[ "lightIntensity" ].value = light.intensity;
  151. materialLight.uniforms[ "lightColor" ].value = light.color;
  152. materialLight.uniforms[ "viewWidth" ].value = width;
  153. materialLight.uniforms[ "viewHeight" ].value = height;
  154. materialLight.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
  155. materialLight.uniforms[ 'samplerNormals' ].value = compNormal.renderTarget2;
  156. materialLight.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
  157. // create light proxy mesh
  158. var geometryLight = new THREE.SphereGeometry( light.distance, 16, 8 );
  159. var meshLight = new THREE.Mesh( geometryLight, materialLight );
  160. meshLight.position = light.position;
  161. // keep reference for size reset
  162. lightMaterials.push( materialLight );
  163. return meshLight;
  164. };
  165. var createDeferredDirectionalLight = function ( light ) {
  166. // setup light material
  167. var materialLight = new THREE.ShaderMaterial( {
  168. uniforms: THREE.UniformsUtils.clone( directionalLightShader.uniforms ),
  169. vertexShader: directionalLightShader.vertexShader,
  170. fragmentShader: directionalLightShader.fragmentShader,
  171. defines: { "ADDITIVE_SPECULAR": additiveSpecular },
  172. blending: THREE.AdditiveBlending,
  173. depthWrite: false,
  174. transparent: true
  175. } );
  176. materialLight.uniforms[ "lightDir" ].value = light.position;
  177. materialLight.uniforms[ "lightIntensity" ].value = light.intensity;
  178. materialLight.uniforms[ "lightColor" ].value = light.color;
  179. materialLight.uniforms[ "viewWidth" ].value = width;
  180. materialLight.uniforms[ "viewHeight" ].value = height;
  181. materialLight.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
  182. materialLight.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
  183. materialLight.uniforms[ 'samplerNormals' ].value = compNormal.renderTarget2;
  184. // create light proxy mesh
  185. var geometryLight = new THREE.PlaneGeometry( 2, 2 );
  186. var meshLight = new THREE.Mesh( geometryLight, materialLight );
  187. // keep reference for size reset
  188. lightMaterials.push( materialLight );
  189. return meshLight;
  190. };
  191. var createDeferredEmissiveLight = function () {
  192. // setup light material
  193. var materialLight = new THREE.ShaderMaterial( {
  194. uniforms: THREE.UniformsUtils.clone( emissiveLightShader.uniforms ),
  195. vertexShader: emissiveLightShader.vertexShader,
  196. fragmentShader: emissiveLightShader.fragmentShader,
  197. blending: THREE.AdditiveBlending,
  198. depthTest: false,
  199. depthWrite: false,
  200. transparent: true
  201. } );
  202. materialLight.uniforms[ "viewWidth" ].value = width;
  203. materialLight.uniforms[ "viewHeight" ].value = height;
  204. materialLight.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
  205. materialLight.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
  206. // create light proxy mesh
  207. var geometryLight = new THREE.PlaneGeometry( 2, 2 );
  208. var meshLight = new THREE.Mesh( geometryLight, materialLight );
  209. // keep reference for size reset
  210. lightMaterials.push( materialLight );
  211. return meshLight;
  212. };
  213. var initDeferredProperties = function ( object ) {
  214. if ( object.properties.deferredInitialized ) return;
  215. if ( object.material ) initDeferredMaterials( object );
  216. if ( object instanceof THREE.PointLight ) {
  217. var meshLight = createDeferredPointLight( object );
  218. lightSceneProxy.add( meshLight );
  219. } else if ( object instanceof THREE.DirectionalLight ) {
  220. var meshLight = createDeferredDirectionalLight( object );
  221. lightSceneFullscreen.add( meshLight );
  222. }
  223. object.properties.deferredInitialized = true;
  224. };
  225. //
  226. var setMaterialColor = function ( object ) {
  227. if ( object.material ) object.material = object.properties.colorMaterial;
  228. };
  229. var setMaterialDepth = function ( object ) {
  230. if ( object.material ) object.material = object.properties.depthMaterial;
  231. };
  232. var setMaterialNormal = function ( object ) {
  233. if ( object.material ) object.material = object.properties.normalMaterial;
  234. };
  235. //
  236. this.setSize = function ( width, height ) {
  237. compColor.setSize( width, height );
  238. compNormal.setSize( width, height );
  239. compDepth.setSize( width, height );
  240. compLight.setSize( width, height );
  241. compFinal.setSize( width, height );
  242. for ( var i = 0, il = lightMaterials.length; i < il; i ++ ) {
  243. var uniforms = lightMaterials[ i ].uniforms;
  244. uniforms[ "viewWidth" ].value = width;
  245. uniforms[ "viewHeight" ].value = height;
  246. uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
  247. uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
  248. if ( uniforms[ 'samplerNormals' ] ) {
  249. uniforms[ 'samplerNormals' ].value = compNormal.renderTarget2;
  250. }
  251. }
  252. compositePass.uniforms[ 'samplerLight' ].value = compLight.renderTarget2;
  253. effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
  254. };
  255. //
  256. this.render = function ( scene, camera ) {
  257. // setup deferred properties
  258. if ( ! scene.properties.lightSceneProxy ) {
  259. scene.properties.lightSceneProxy = new THREE.Scene();
  260. scene.properties.lightSceneFullscreen = new THREE.Scene();
  261. var meshLight = createDeferredEmissiveLight();
  262. scene.properties.lightSceneFullscreen.add( meshLight );
  263. }
  264. lightSceneProxy = scene.properties.lightSceneProxy;
  265. lightSceneFullscreen = scene.properties.lightSceneFullscreen;
  266. passColor.camera = camera;
  267. passNormal.camera = camera;
  268. passDepth.camera = camera;
  269. passLightProxy.camera = camera;
  270. passLightFullscreen.camera = THREE.EffectComposer.camera;
  271. passColor.scene = scene;
  272. passNormal.scene = scene;
  273. passDepth.scene = scene;
  274. passLightFullscreen.scene = lightSceneFullscreen;
  275. passLightProxy.scene = lightSceneProxy;
  276. scene.traverse( initDeferredProperties );
  277. // g-buffer color
  278. scene.traverse( setMaterialColor );
  279. compColor.render();
  280. // g-buffer depth
  281. scene.traverse( setMaterialDepth );
  282. compDepth.render();
  283. // g-buffer normals
  284. scene.traverse( setMaterialNormal );
  285. compNormal.render();
  286. // light pass
  287. camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
  288. for ( var i = 0, il = lightSceneProxy.children.length; i < il; i ++ ) {
  289. var uniforms = lightSceneProxy.children[ i ].material.uniforms;
  290. uniforms[ "matProjInverse" ].value = camera.projectionMatrixInverse;
  291. uniforms[ "matView" ].value = camera.matrixWorldInverse;
  292. }
  293. for ( var i = 0, il = lightSceneFullscreen.children.length; i < il; i ++ ) {
  294. var uniforms = lightSceneFullscreen.children[ i ].material.uniforms;
  295. if ( uniforms[ "matView" ] ) uniforms[ "matView" ].value = camera.matrixWorldInverse;
  296. }
  297. compLight.render();
  298. // composite pass
  299. compFinal.render( 0.1 );
  300. };
  301. var createRenderTargets = function ( ) {
  302. // g-buffers
  303. var rtColor = new THREE.WebGLRenderTarget( width, height, rtParamsFloatNearest );
  304. var rtNormal = new THREE.WebGLRenderTarget( width, height, rtParamsFloatLinear );
  305. var rtDepth = new THREE.WebGLRenderTarget( width, height, rtParamsFloatLinear );
  306. var rtLight = new THREE.WebGLRenderTarget( width, height, rtParamsFloatLinear );
  307. var rtFinal = new THREE.WebGLRenderTarget( width, height, rtParamsUByte );
  308. rtColor.generateMipmaps = false;
  309. rtNormal.generateMipmaps = false;
  310. rtDepth.generateMipmaps = false;
  311. rtLight.generateMipmaps = false;
  312. rtFinal.generateMipmaps = false;
  313. // composers
  314. passColor = new THREE.RenderPass();
  315. compColor = new THREE.EffectComposer( renderer, rtColor );
  316. compColor.addPass( passColor );
  317. passNormal = new THREE.RenderPass();
  318. compNormal = new THREE.EffectComposer( renderer, rtNormal );
  319. compNormal.addPass( passNormal );
  320. passDepth = new THREE.RenderPass();
  321. compDepth = new THREE.EffectComposer( renderer, rtDepth );
  322. compDepth.addPass( passDepth );
  323. passLightProxy = new THREE.RenderPass();
  324. passLightFullscreen = new THREE.RenderPass();
  325. passLightFullscreen.clear = false;
  326. compLight = new THREE.EffectComposer( renderer, rtLight );
  327. compLight.addPass( passLightProxy );
  328. compLight.addPass( passLightFullscreen );
  329. // composite
  330. compositePass = new THREE.ShaderPass( compositeShader );
  331. compositePass.needsSwap = true;
  332. compositePass.uniforms[ 'samplerLight' ].value = compLight.renderTarget2;
  333. // FXAA
  334. effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
  335. effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
  336. // color correction
  337. var effectColor = new THREE.ShaderPass( THREE.ColorCorrectionShader );
  338. effectColor.renderToScreen = true;
  339. effectColor.uniforms[ 'powRGB' ].value.set( 1, 1, 1 );
  340. effectColor.uniforms[ 'mulRGB' ].value.set( 2, 2, 2 );
  341. //
  342. compFinal = new THREE.EffectComposer( renderer, rtFinal );
  343. compFinal.addPass( compositePass );
  344. compFinal.addPass( effectFXAA );
  345. compFinal.addPass( effectColor );
  346. };
  347. // init
  348. createRenderTargets();
  349. };