webgl_lights_deferred_pointlights.html 29 KB

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