webgl_lights_deferred_pointlights.html 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. <!DOCTYPE HTML>
  2. <html lang="en">
  3. <head>
  4. <title>three.js webgl - deferred rendering</title>
  5. <meta charset="utf-8" />
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <style>
  8. body {
  9. background-color: #000;
  10. margin: 0px;
  11. overflow: hidden;
  12. }
  13. #info {
  14. position: absolute;
  15. top: 0px; width: 100%;
  16. color: #ffffff;
  17. padding: 5px;
  18. font-family: Monospace;
  19. font-size: 13px;
  20. text-align: center;
  21. }
  22. a {
  23. color: #ff0080;
  24. text-decoration: none;
  25. }
  26. a:hover {
  27. color: #0080ff;
  28. }
  29. </style>
  30. </head>
  31. <body>
  32. <div id="info">
  33. <a href="http://threejs.org" target="_blank">three.js</a> - deferred point lights WebGL demo by <a href="http://de.redplant.de" target=_blank>redPlant</a>.<br />
  34. Walt Disney head by <a href="http://davidoreilly.com/post/18087489343/disneyhead" target="_blank">David OReilly</a><br>
  35. Point Light attenuation formula by <a href="http://imdoingitwrong.wordpress.com/tag/glsl/" target=_blank>Tom Madams</a>
  36. </div>
  37. <div id="container"></div>
  38. <script src="../build/three.min.js"></script>
  39. <script src="js/Detector.js"></script>
  40. <script src="js/libs/stats.min.js"></script>
  41. <script src="js/shaders/CopyShader.js"></script>
  42. <script src="js/shaders/FXAAShader.js"></script>
  43. <script src="js/postprocessing/EffectComposer.js"></script>
  44. <script src="js/postprocessing/RenderPass.js"></script>
  45. <script src="js/postprocessing/ShaderPass.js"></script>
  46. <script src="js/postprocessing/MaskPass.js"></script>
  47. <script src="js/controls/TrackballControls.js"></script>
  48. <script src="js/loaders/ctm/lzma.js"></script>
  49. <script src="js/loaders/ctm/ctm.js"></script>
  50. <script src="js/loaders/ctm/CTMLoader.js"></script>
  51. <script src="js/loaders/UTF8Loader.js"></script>
  52. <script src="js/loaders/MTLLoader.js"></script>
  53. <script>
  54. if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
  55. var WIDTH = window.innerWidth;
  56. var HEIGHT = window.innerHeight;
  57. var NEAR = 1.0, FAR = 250.0;
  58. var VIEW_ANGLE = 45;
  59. var ASPECT = WIDTH / HEIGHT;
  60. // core
  61. var renderer, camera, controls, stats, clock;
  62. // scenes and scene nodes
  63. var lightScene, lightNode, scene, sceneNode, emitterScene, emitterNode, quadScene, quadNode;
  64. // rendertargets
  65. var rtColor, rtNormals, rtDepth, rtLightBuffer, rtEmitter, rtFinal;
  66. // composer
  67. var compColor, compNormals, compDepth, compLightBuffer, compFinal, compEmitter, compositePass;
  68. var effectFXAA;
  69. // materials
  70. var matNormal, matClipDepth, matBasic, matUnlit;
  71. var numLights = 50;
  72. var lights = new Array();
  73. // -----------------------
  74. // shader definitions
  75. // -----------------------
  76. var clipdepth_frag = ""+
  77. "varying vec4 clipPos;"+
  78. "void main() {"+
  79. "gl_FragColor = vec4( clipPos.z / clipPos.w, 1.0, 1.0, 1.0 );"+
  80. "}";
  81. var clipdepth_vert = "" +
  82. "varying vec4 clipPos;"+
  83. "void main() {"+
  84. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
  85. "gl_Position = projectionMatrix * mvPosition;"+
  86. "clipPos = gl_Position;"+
  87. "}";
  88. // -----------------------
  89. var normals_vert = "" +
  90. "varying vec3 normalView;"+
  91. "void main() {"+
  92. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
  93. "gl_Position = projectionMatrix * mvPosition;"+
  94. "normalView = normalize( normalMatrix * normal );"+
  95. "}";
  96. var normals_frag = "" +
  97. "varying vec3 normalView;"+
  98. "void main() {"+
  99. "gl_FragColor = vec4( vec3( normalView * 0.5 + 0.5 ), 1.0 );"+
  100. "}";
  101. // -----------------------
  102. var bump_vert = "" +
  103. "varying vec3 normalView;"+
  104. "varying vec2 vUv;"+
  105. "varying vec3 vViewPosition;"+
  106. "uniform vec4 offsetRepeat;"+
  107. "void main() {"+
  108. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
  109. "gl_Position = projectionMatrix * mvPosition;"+
  110. "normalView = normalize( normalMatrix * normal );"+
  111. "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;"+
  112. "vViewPosition = -mvPosition.xyz;"+
  113. "}";
  114. var bump_frag = "" +
  115. "#extension GL_OES_standard_derivatives : enable\n"+
  116. "varying vec3 normalView;"+
  117. "varying vec2 vUv;"+
  118. "varying vec3 vViewPosition;"+
  119. "uniform sampler2D bumpMap;"+
  120. "uniform float bumpScale;"+
  121. // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
  122. // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
  123. // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
  124. "vec2 dHdxy_fwd() {"+
  125. "vec2 dSTdx = dFdx( vUv );"+
  126. "vec2 dSTdy = dFdy( vUv );"+
  127. "float Hll = bumpScale * texture2D( bumpMap, vUv ).x;"+
  128. "float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;"+
  129. "float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;"+
  130. "return vec2( dBx, dBy );"+
  131. "}"+
  132. "vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {"+
  133. "vec3 vSigmaX = dFdx( surf_pos );"+
  134. "vec3 vSigmaY = dFdy( surf_pos );"+
  135. "vec3 vN = surf_norm;"+ // normalized
  136. "vec3 R1 = cross( vSigmaY, vN );"+
  137. "vec3 R2 = cross( vN, vSigmaX );"+
  138. "float fDet = dot( vSigmaX, R1 );"+
  139. "vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );"+
  140. "return normalize( abs( fDet ) * surf_norm - vGrad );"+
  141. "}"+
  142. "void main() {"+
  143. "vec3 normal = normalize( normalView );"+
  144. "normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );"+
  145. "gl_FragColor = vec4( vec3( normal * 0.5 + 0.5 ), 1.0 );"+
  146. "}";
  147. // -----------------------
  148. var unlit_vert = "" +
  149. "varying vec4 clipPos;"+
  150. "void main() {"+
  151. "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );"+
  152. "clipPos = gl_Position;"+
  153. "}";
  154. var unlit_frag = "" +
  155. "varying vec4 clipPos;"+
  156. "uniform sampler2D samplerDepth;"+
  157. "uniform float viewHeight;"+
  158. "uniform float viewWidth;"+
  159. "uniform vec3 lightColor;" +
  160. "void main() {"+
  161. "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"+
  162. "float z = texture2D( samplerDepth, texCoord ).x;"+
  163. "vec4 color = vec4( lightColor, 1.0 );"+
  164. "float depth = clipPos.z / clipPos.w;"+
  165. "if( depth > z && z > 0.0 ) color.w = 0.0;"+
  166. "gl_FragColor = color;"+
  167. "}";
  168. // -----------------------
  169. var deferredlight_vert = "" +
  170. "varying vec3 lightView;" +
  171. "varying vec4 clipPos;" +
  172. "uniform vec3 lightPos;" +
  173. "uniform mat4 matView;" +
  174. "void main() { " +
  175. "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
  176. "gl_Position = projectionMatrix * mvPosition;"+
  177. "lightView = vec3( matView * vec4( lightPos, 1.0 ) );" +
  178. "clipPos = gl_Position;"+
  179. "}"
  180. var deferredlight_frag = "" +
  181. "varying vec3 lightView;"+
  182. "varying vec4 clipPos;" +
  183. "uniform sampler2D samplerColor;"+
  184. "uniform sampler2D samplerDepth;"+
  185. "uniform sampler2D samplerNormals;"+
  186. "uniform sampler2D samplerLightBuffer;"+
  187. "uniform float lightRadius;"+
  188. "uniform float lightIntensity;"+
  189. "uniform float viewHeight;"+
  190. "uniform float viewWidth;"+
  191. "uniform vec3 lightColor;"+
  192. "uniform mat4 matProjInverse;"+
  193. "void main() {"+
  194. "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"+
  195. "float z = texture2D( samplerDepth, texCoord ).x;"+
  196. "float lightZ = clipPos.z / clipPos.w;"+
  197. /*
  198. "if ( z == 0.0 ) {"+
  199. "gl_FragColor = vec4( vec3( 0.0 ), 1.0 );"+
  200. "return;"+
  201. "}"+
  202. */
  203. "if ( z == 0.0 || lightZ > z ) discard;"+
  204. "float x = texCoord.x * 2.0 - 1.0;"+
  205. "float y = texCoord.y * 2.0 - 1.0;"+
  206. "vec4 projectedPos = vec4( x, y, z, 1.0 );"+
  207. "vec4 viewPos = matProjInverse * projectedPos;"+
  208. "viewPos.xyz /= viewPos.w;"+
  209. "viewPos.w = 1.0;"+
  210. "vec3 lightDir = lightView - viewPos.xyz;"+
  211. "float dist = length( lightDir );"+
  212. "lightDir = normalize( lightDir );"+
  213. "float cutoff = 0.3;"+
  214. "float denom = dist/lightRadius + 1.0;"+
  215. "float attenuation = 1.0 / ( denom * denom );"+
  216. "attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );"+
  217. "attenuation = max( attenuation, 0.0 );"+
  218. "vec3 normal = texture2D( samplerNormals, texCoord ).xyz * 2.0 - 1.0;" +
  219. // wrap around lighting
  220. "float diffuseFull = max( dot( normal, lightDir ), 0.0 );" +
  221. "float diffuseHalf = max( 0.5 + 0.5 * dot( normal, lightDir ), 0.0 );" +
  222. "const vec3 wrapRGB = vec3( 0.9, 0.7, 0.7 );"+
  223. "vec3 diffuse = mix( vec3 ( diffuseFull ), vec3( diffuseHalf ), wrapRGB );"+
  224. // simple lighting
  225. //"float diffuseFull = max( dot( normal, lightDir ), 0.0 );" +
  226. //"vec3 diffuse = vec3 ( diffuseFull );"+
  227. // specular
  228. "const float shininess = 75.0;" +
  229. "const float specularIntensity = 0.4;"+
  230. "vec3 halfVector = normalize( lightDir - normalize( viewPos.xyz ) );" +
  231. "float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );" +
  232. // simple specular
  233. //"vec3 specular = specularIntensity * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;" +
  234. // physically based specular
  235. "vec3 specularColor = specularIntensity * vec3( 0.12 );"+
  236. "float specularNormalization = ( shininess + 2.0001 ) / 8.0;"+
  237. "vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightDir, halfVector ), 5.0 );"+
  238. "vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse * specularNormalization;"+
  239. // color
  240. "vec4 albedo = texture2D( samplerColor, texCoord );"+
  241. // combine
  242. "vec4 color = vec4( 0.0 );"+
  243. "color.xyz = albedo.xyz * lightColor * lightIntensity;"+
  244. "color.w = attenuation;"+
  245. "gl_FragColor = color * vec4( diffuse + specular, 1.0 );" +
  246. //"gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.05 );"+
  247. "}";
  248. var composite_vert = "" +
  249. "varying vec2 texCoord;"+
  250. "void main() {"+
  251. "vec4 pos = vec4( sign( position.xy ), 0.0, 1.0 );"+
  252. "texCoord = pos.xy * vec2( 0.5 ) + 0.5;"+
  253. "gl_Position = pos;"+
  254. "}";
  255. var composite_frag = "" +
  256. "varying vec2 texCoord;"+
  257. "uniform sampler2D samplerLightBuffer;" +
  258. "uniform sampler2D samplerEmitter;" +
  259. "uniform vec3 lightPos;" +
  260. "void main() {" +
  261. "vec3 color = texture2D( samplerLightBuffer, texCoord ).xyz;" +
  262. "vec3 emitter = texture2D( samplerEmitter, texCoord ).xyz;"+
  263. "if ( emitter != vec3( 0.0 ) ) {"+
  264. "gl_FragColor = vec4( emitter, 1.0 );" +
  265. "} else {"+
  266. "gl_FragColor = vec4( sqrt( color ), 1.0 );" +
  267. "}"+
  268. "}"
  269. // -----------------------
  270. var normalShader = {
  271. uniforms: {},
  272. vertexShader: normals_vert,
  273. fragmentShader: normals_frag
  274. };
  275. // -----------------------
  276. var bumpShader = {
  277. uniforms: {
  278. bumpMap: { type: "t", value: null },
  279. bumpScale: { type: "f", value: 1 },
  280. offsetRepeat : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }
  281. },
  282. vertexShader: bump_vert,
  283. fragmentShader: bump_frag
  284. };
  285. // -----------------------
  286. var clipDepthShader = {
  287. uniforms: {},
  288. vertexShader: clipdepth_vert,
  289. fragmentShader: clipdepth_frag
  290. };
  291. // -----------------------
  292. var unlitShader = {
  293. uniforms: {
  294. samplerDepth: { type: "t", value: null },
  295. viewWidth: { type: "f", value: WIDTH },
  296. viewHeight: { type: "f", value: HEIGHT },
  297. lightColor: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) }
  298. },
  299. vertexShader: unlit_vert,
  300. fragmentShader: unlit_frag
  301. };
  302. // -----------------------
  303. var lightShader = {
  304. uniforms: {
  305. samplerLightBuffer: { type: "t", value: null },
  306. samplerNormals: { type: "t", value: null },
  307. samplerDepth: { type: "t", value: null },
  308. samplerColor: { type: "t", value: null },
  309. matView : { type: "m4", value: new THREE.Matrix4() },
  310. matProjInverse : { type: "m4", value: new THREE.Matrix4() },
  311. viewWidth: { type: "f", value: WIDTH },
  312. viewHeight: { type: "f", value: HEIGHT },
  313. lightPos: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
  314. lightColor: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
  315. lightIntensity: { type: "f", value: 1.0 },
  316. lightRadius: { type: "f", value: 1.0 }
  317. },
  318. vertexShader: deferredlight_vert,
  319. fragmentShader: deferredlight_frag
  320. };
  321. // -----------------------
  322. var compositeShader = {
  323. uniforms: {
  324. samplerLightBuffer: { type: "t", value: null },
  325. samplerEmitter: { type: "t", value: null }
  326. },
  327. vertexShader: composite_vert,
  328. fragmentShader: composite_frag
  329. };
  330. // -----------------------------
  331. function bootstrap() {
  332. renderer = new THREE.WebGLRenderer( { alpha: false } );
  333. renderer.setSize( WIDTH, HEIGHT );
  334. renderer.setClearColorHex( 0x000000, 1 );
  335. var container = document.getElementById( 'container' );
  336. container.appendChild( renderer.domElement );
  337. // scene camera
  338. camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
  339. camera.position.z = 125;
  340. controls = new THREE.TrackballControls( camera, renderer.domElement );
  341. // scene for walt's head model
  342. scene = new THREE.Scene();
  343. sceneNode = new THREE.Object3D();
  344. scene.add( sceneNode );
  345. scene.add( camera );
  346. // scene for light proxy geometry
  347. lightScene = new THREE.Scene();
  348. lightNode = new THREE.Object3D();
  349. lightScene.add( lightNode );
  350. // scene for the coloured emitter spheres
  351. emitterScene = new THREE.Scene();
  352. emitterNode = new THREE.Object3D();
  353. emitterScene.add( emitterNode );
  354. // full screen quad for compositing
  355. quadScene = new THREE.Scene();
  356. quadNode = new THREE.Object3D();
  357. quadScene.add( quadNode );
  358. quadNode.add( new THREE.Mesh( new THREE.PlaneGeometry( 1, 1 ) ) );
  359. // stats
  360. stats = new Stats();
  361. stats.domElement.style.position = 'absolute';
  362. stats.domElement.style.top = '8px';
  363. stats.domElement.style.zIndex = 100;
  364. container.appendChild( stats.domElement );
  365. // clock
  366. clock = new THREE.Clock();
  367. }
  368. // -----------------------------
  369. function createRenderTargets() {
  370. var rtParamsFloat = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
  371. format: THREE.RGBAFormat, type: THREE.FloatType };
  372. var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
  373. format: THREE.RGBFormat, type: THREE.UnsignedByteType };
  374. // ----------------------------------------------------------
  375. // g-buffer
  376. // ----------------------------------------------------------
  377. rtNormals = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
  378. rtDepth = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
  379. rtColor = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
  380. rtFinal = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
  381. rtNormals.generateMipmaps = false;
  382. rtDepth.generateMipmaps = false;
  383. rtColor.generateMipmaps = false;
  384. rtFinal.generateMipmaps = false;
  385. var passNormals = new THREE.RenderPass( scene, camera );
  386. compNormals = new THREE.EffectComposer( renderer, rtNormals );
  387. compNormals.addPass( passNormals );
  388. var passDepth = new THREE.RenderPass( scene, camera );
  389. compDepth = new THREE.EffectComposer( renderer, rtDepth );
  390. compDepth.addPass( passDepth );
  391. var passColor = new THREE.RenderPass( scene, camera );
  392. compColor = new THREE.EffectComposer( renderer, rtColor );
  393. compColor.addPass( passColor );
  394. // ----------------------------------------------------------
  395. // light emitter spheres
  396. // ----------------------------------------------------------
  397. var emitterPass = new THREE.RenderPass( emitterScene, camera );
  398. rtEmitter = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
  399. rtEmitter.generateMipmaps = false;
  400. compEmitter = new THREE.EffectComposer( renderer, rtEmitter );
  401. compEmitter.addPass( emitterPass );
  402. // ----------------------------------------------------------
  403. // lighting pass
  404. // ----------------------------------------------------------
  405. rtLightBuffer = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
  406. rtLightBuffer.generateMipmaps = false;
  407. var passLight = new THREE.RenderPass( lightScene, camera );
  408. compLightBuffer = new THREE.EffectComposer( renderer, rtLightBuffer );
  409. compLightBuffer.addPass( passLight );
  410. lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
  411. lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
  412. lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
  413. lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLightBuffer;
  414. var geomEmitter = new THREE.SphereGeometry( 0.4, 7, 7 );
  415. for ( var x = 0; x < numLights; x ++ ) {
  416. var light = lights[ x ];
  417. // setup material
  418. var matLight = new THREE.ShaderMaterial({
  419. uniforms: THREE.UniformsUtils.clone( lightShader.uniforms ),
  420. vertexShader: lightShader.vertexShader,
  421. fragmentShader: lightShader.fragmentShader
  422. });
  423. matLight.blending = THREE.AdditiveBlending;
  424. matLight.transparent = true;
  425. matLight.depthWrite = false;
  426. matLight.uniforms[ "lightPos" ].value = light.position;
  427. matLight.uniforms[ "lightRadius" ].value = light.distance;
  428. matLight.uniforms[ "lightIntensity" ].value = light.intensity;
  429. matLight.uniforms[ "lightColor" ].value = light.color;
  430. // setup proxy geometry for this light
  431. var geomLight = new THREE.SphereGeometry( light.distance, 16, 8 );
  432. var meshLight = new THREE.Mesh( geomLight, matLight );
  433. lightNode.add( meshLight );
  434. // create emitter sphere
  435. var matEmitter = new THREE.ShaderMaterial({
  436. uniforms: THREE.UniformsUtils.clone( unlitShader.uniforms ),
  437. vertexShader: unlitShader.vertexShader,
  438. fragmentShader: unlitShader.fragmentShader
  439. });
  440. var meshEmitter = new THREE.Mesh( geomEmitter, matEmitter );
  441. meshEmitter.position = light.position;
  442. emitterNode.add( meshEmitter );
  443. // add emitter to light node
  444. meshLight.emitter = meshEmitter;
  445. }
  446. // ----------------------------------------------------------
  447. // composite
  448. // ----------------------------------------------------------
  449. compositeShader.uniforms[ 'samplerLightBuffer' ].value = compLightBuffer.renderTarget2;
  450. compositeShader.uniforms[ 'samplerEmitter' ].value = compEmitter.renderTarget2;
  451. compositePass = new THREE.ShaderPass( compositeShader );
  452. compositePass.needsSwap = true;
  453. //compositePass.renderToScreen = true;
  454. effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
  455. var width = window.innerWidth || 2;
  456. var height = window.innerHeight || 2;
  457. effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
  458. effectFXAA.renderToScreen = true;
  459. compFinal = new THREE.EffectComposer( renderer, rtFinal );
  460. compFinal.addPass( compositePass );
  461. compFinal.addPass( effectFXAA );
  462. }
  463. // -----------------------------
  464. function initScene( object, y, scale ) {
  465. var shader = THREE.ShaderLib[ "basic" ];
  466. object.traverse( function( node ) {
  467. if ( node.material ) {
  468. // color material
  469. var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
  470. var defines = { "USE_MAP": !!node.material.map, "GAMMA_INPUT": true };
  471. var material = new THREE.ShaderMaterial( { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, defines: defines } );
  472. uniforms.diffuse.value.copy( node.material.color );
  473. uniforms.map.value = node.material.map;
  474. if ( node.material.transparent ) {
  475. material.alphaTest = 0.1;
  476. }
  477. if ( node.material.name === "eyetrans" ) {
  478. material.visible = false;
  479. }
  480. node.properties.colorMaterial = material;
  481. // normal material
  482. if ( node.material.bumpMap ) {
  483. var uniforms = THREE.UniformsUtils.clone( bumpShader.uniforms );
  484. var normalMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: bumpShader.vertexShader, fragmentShader: bumpShader.fragmentShader } );
  485. uniforms.bumpMap.value = node.material.bumpMap;
  486. uniforms.bumpScale.value = node.material.bumpScale;
  487. var offset = node.material.bumpMap.offset;
  488. var repeat = node.material.bumpMap.repeat;
  489. uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
  490. node.properties.normalMaterial = normalMaterial;
  491. } else {
  492. node.properties.normalMaterial = matNormal;
  493. }
  494. // depth material
  495. node.properties.depthMaterial = matClipDepth;
  496. }
  497. } );
  498. object.position.y = y;
  499. object.scale.set( scale, scale, scale );
  500. sceneNode.add( object );
  501. }
  502. // -----------------------------
  503. function initMaterials() {
  504. matNormal = new THREE.ShaderMaterial({
  505. uniforms: normalShader.uniforms,
  506. vertexShader: normalShader.vertexShader,
  507. fragmentShader: normalShader.fragmentShader
  508. });
  509. matClipDepth = new THREE.ShaderMaterial({
  510. uniforms: clipDepthShader.uniforms,
  511. vertexShader: clipDepthShader.vertexShader,
  512. fragmentShader: clipDepthShader.fragmentShader
  513. });
  514. }
  515. // -----------------------------
  516. function initLights() {
  517. var distance = 20;
  518. // front light
  519. var light = new THREE.PointLight();
  520. light.color = new THREE.Vector3( 1, 1, 1 );
  521. light.intensity = 1.5;
  522. light.distance = 1.5 * distance;
  523. lights.push( light );
  524. // random lights
  525. for ( var i = 1; i < numLights; i ++ ) {
  526. var light = new THREE.PointLight();
  527. light.color = new THREE.Vector3( Math.random(), Math.random(), Math.random() ).normalize();
  528. // gamma to linear
  529. light.color.x *= light.color.x;
  530. light.color.y *= light.color.y;
  531. light.color.z *= light.color.z;
  532. light.intensity = 2.0;
  533. light.distance = distance;
  534. lights.push( light );
  535. }
  536. }
  537. // -----------------------------
  538. function animate() {
  539. var delta = clock.getDelta();
  540. requestAnimationFrame( animate );
  541. controls.update( delta );
  542. stats.update();
  543. render();
  544. }
  545. // -----------------------------
  546. function render() {
  547. // -----------------------------
  548. // g-buffer color
  549. // -----------------------------
  550. sceneNode.traverse( function( node ) {
  551. if ( node.material ) {
  552. node.material = node.properties.colorMaterial;
  553. }
  554. } );
  555. compColor.render();
  556. // -----------------------------
  557. // g-buffer depth
  558. // -----------------------------
  559. sceneNode.traverse( function( node ) {
  560. if ( node.material ) {
  561. node.material = node.properties.depthMaterial;
  562. }
  563. } );
  564. compDepth.render();
  565. // -----------------------------
  566. // g-buffer normals
  567. // -----------------------------
  568. sceneNode.traverse( function( node ) {
  569. if ( node.material ) {
  570. node.material = node.properties.normalMaterial;
  571. }
  572. } );
  573. compNormals.render();
  574. // -----------------------------
  575. // emitter pass
  576. // -----------------------------
  577. for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
  578. var light = lightNode.children[ i ];
  579. var color = light.material.uniforms[ "lightColor" ].value;
  580. var emitter = light.emitter;
  581. emitter.material.uniforms[ "samplerDepth" ].value = compDepth.renderTarget2;
  582. emitter.material.uniforms[ "lightColor" ].value = color;
  583. }
  584. compEmitter.render();
  585. // -----------------------------
  586. // light pass
  587. // -----------------------------
  588. camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
  589. for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
  590. var uniforms = lightNode.children[ i ].material.uniforms;
  591. uniforms[ "matProjInverse" ].value = camera.projectionMatrixInverse;
  592. uniforms[ "matView" ].value = camera.matrixWorldInverse;
  593. }
  594. var time = Date.now() * 0.0002;
  595. // update lights
  596. var x, y, z;
  597. for ( var i = 0; i < numLights; i ++ ) {
  598. if ( i > 0 ) {
  599. x = Math.sin( time + i * 0.175 ) * 20;
  600. y = Math.cos( time + i * 0.153 ) * 30;
  601. z = Math.cos( time + i * 0.137 ) * 20;
  602. } else {
  603. x = Math.sin( time * 3 ) * 20;
  604. y = 15;
  605. z = Math.cos( time * 3 ) * 25 + 10;
  606. }
  607. var light = lightNode.children[ i ];
  608. var lightPosition = light.material.uniforms[ "lightPos" ].value;
  609. lightPosition.x = x;
  610. lightPosition.y = y;
  611. lightPosition.z = z;
  612. light.emitter.position = lightPosition;
  613. light.position = lightPosition;
  614. light.frustumCulled = false;
  615. }
  616. compLightBuffer.render();
  617. // -----------------------------
  618. // composite pass
  619. // -----------------------------
  620. compFinal.render();
  621. }
  622. // -----------------------------
  623. // entry point
  624. // -----------------------------
  625. bootstrap();
  626. initMaterials();
  627. initLights();
  628. createRenderTargets();
  629. var loader = new THREE.UTF8Loader();
  630. /*
  631. loader.load( "models/utf8/ben_dds.js", function ( object ) {
  632. initScene( object, -75, 150 );
  633. animate();
  634. }, { normalizeRGB: true } );
  635. */
  636. /*
  637. loader.load( "models/utf8/WaltHi.js", function ( object ) {
  638. initScene( object, -35, 1 );
  639. animate();
  640. }, { normalizeRGB: true } );
  641. */
  642. var loader = new THREE.JSONLoader();
  643. loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry, materials ) {
  644. var mapColor = THREE.ImageUtils.loadTexture( "obj/leeperrysmith/Map-COL.jpg" );
  645. var mapHeight = THREE.ImageUtils.loadTexture( "obj/leeperrysmith/Infinite-Level_02_Disp_NoSmoothUV-4096.jpg" );
  646. mapHeight.repeat.set( 0.998, 0.998 );
  647. mapHeight.offset.set( 0.001, 0.001 )
  648. mapHeight.wrapS = mapHeight.wrapT = THREE.RepeatWrapping;
  649. mapHeight.anisotropy = 4;
  650. mapHeight.format = THREE.RGBFormat;
  651. var material = new THREE.MeshPhongMaterial( { map: mapColor, bumpMap: mapHeight, bumpScale: 1.5 } );
  652. var object = new THREE.Mesh( geometry, material );
  653. initScene( object, 0, 8 );
  654. animate();
  655. } );
  656. </script>
  657. </body>
  658. </html>
粤ICP备19079148号