| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039 |
- <!DOCTYPE HTML>
- <html lang="en">
- <head>
- <title>three.js webgl - deferred rendering</title>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
- <style>
- body {
- background-color: #000;
- margin: 0px;
- overflow: hidden;
- }
- #info {
- position: absolute;
- top: 0px; width: 100%;
- color: #ffffff;
- padding: 5px;
- font-family: Monospace;
- font-size: 13px;
- text-align: center;
- }
- a {
- color: #ff0080;
- text-decoration: none;
- }
- a:hover {
- color: #0080ff;
- }
- </style>
- </head>
- <body>
- <div id="info">
- <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 />
- Walt Disney head by <a href="http://davidoreilly.com/post/18087489343/disneyhead" target="_blank">David OReilly</a><br>
- Point Light attenuation formula by <a href="http://imdoingitwrong.wordpress.com/tag/glsl/" target=_blank>Tom Madams</a>
- </div>
- <div id="container"></div>
- <script src="../build/three.min.js"></script>
- <script src="js/Detector.js"></script>
- <script src="js/libs/stats.min.js"></script>
- <script src="js/shaders/CopyShader.js"></script>
- <script src="js/shaders/FXAAShader.js"></script>
- <script src="js/postprocessing/EffectComposer.js"></script>
- <script src="js/postprocessing/RenderPass.js"></script>
- <script src="js/postprocessing/ShaderPass.js"></script>
- <script src="js/postprocessing/MaskPass.js"></script>
- <script src="js/controls/TrackballControls.js"></script>
- <script src="js/loaders/ctm/lzma.js"></script>
- <script src="js/loaders/ctm/ctm.js"></script>
- <script src="js/loaders/ctm/CTMLoader.js"></script>
- <script src="js/loaders/UTF8Loader.js"></script>
- <script src="js/loaders/MTLLoader.js"></script>
- <script>
- if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
- var WIDTH = window.innerWidth;
- var HEIGHT = window.innerHeight;
- var NEAR = 1.0, FAR = 250.0;
- var VIEW_ANGLE = 45;
- var ASPECT = WIDTH / HEIGHT;
- // core
- var renderer, camera, controls, stats, clock;
- // scenes and scene nodes
- var lightScene, lightNode, scene, sceneNode, emitterScene, emitterNode, quadScene, quadNode;
- // rendertargets
- var rtColor, rtNormals, rtDepth, rtLightBuffer, rtEmitter, rtFinal;
- // composer
- var compColor, compNormals, compDepth, compLightBuffer, compFinal, compEmitter, compositePass;
- var effectFXAA;
- // materials
- var matNormal, matClipDepth, matBasic, matUnlit;
- var numLights = 50;
- var lights = new Array();
- // -----------------------
- // shader definitions
- // -----------------------
- var clipdepth_frag = ""+
- "varying vec4 clipPos;"+
- "void main() {"+
- "gl_FragColor = vec4( clipPos.z / clipPos.w, 1.0, 1.0, 1.0 );"+
- "}";
- var clipdepth_vert = "" +
- "varying vec4 clipPos;"+
- "void main() {"+
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
- "gl_Position = projectionMatrix * mvPosition;"+
- "clipPos = gl_Position;"+
- "}";
- // -----------------------
- var normals_vert = "" +
- "varying vec3 normalView;"+
- "void main() {"+
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
- "gl_Position = projectionMatrix * mvPosition;"+
- "normalView = normalize( normalMatrix * normal );"+
- "}";
- var normals_frag = "" +
- "varying vec3 normalView;"+
- "void main() {"+
- "gl_FragColor = vec4( vec3( normalView * 0.5 + 0.5 ), 1.0 );"+
- "}";
- // -----------------------
- var bump_vert = "" +
- "varying vec3 normalView;"+
- "varying vec2 vUv;"+
- "varying vec3 vViewPosition;"+
- "uniform vec4 offsetRepeat;"+
- "void main() {"+
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
- "gl_Position = projectionMatrix * mvPosition;"+
- "normalView = normalize( normalMatrix * normal );"+
- "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;"+
- "vViewPosition = -mvPosition.xyz;"+
- "}";
- var bump_frag = "" +
- "#extension GL_OES_standard_derivatives : enable\n"+
- "varying vec3 normalView;"+
- "varying vec2 vUv;"+
- "varying vec3 vViewPosition;"+
- "uniform sampler2D bumpMap;"+
- "uniform float bumpScale;"+
- // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
- // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
- // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
- "vec2 dHdxy_fwd() {"+
- "vec2 dSTdx = dFdx( vUv );"+
- "vec2 dSTdy = dFdy( vUv );"+
- "float Hll = bumpScale * texture2D( bumpMap, vUv ).x;"+
- "float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;"+
- "float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;"+
- "return vec2( dBx, dBy );"+
- "}"+
- "vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {"+
- "vec3 vSigmaX = dFdx( surf_pos );"+
- "vec3 vSigmaY = dFdy( surf_pos );"+
- "vec3 vN = surf_norm;"+ // normalized
- "vec3 R1 = cross( vSigmaY, vN );"+
- "vec3 R2 = cross( vN, vSigmaX );"+
- "float fDet = dot( vSigmaX, R1 );"+
- "vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );"+
- "return normalize( abs( fDet ) * surf_norm - vGrad );"+
- "}"+
- "void main() {"+
- "vec3 normal = normalize( normalView );"+
- "normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );"+
- "gl_FragColor = vec4( vec3( normal * 0.5 + 0.5 ), 1.0 );"+
- "}";
- // -----------------------
- var unlit_vert = "" +
- "varying vec4 clipPos;"+
- "void main() {"+
- "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );"+
- "clipPos = gl_Position;"+
- "}";
- var unlit_frag = "" +
- "varying vec4 clipPos;"+
- "uniform sampler2D samplerDepth;"+
- "uniform float viewHeight;"+
- "uniform float viewWidth;"+
- "uniform vec3 lightColor;" +
- "void main() {"+
- "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"+
- "float z = texture2D( samplerDepth, texCoord ).x;"+
- "vec4 color = vec4( lightColor, 1.0 );"+
- "float depth = clipPos.z / clipPos.w;"+
- "if( depth > z && z > 0.0 ) color.w = 0.0;"+
- "gl_FragColor = color;"+
- "}";
- // -----------------------
- var deferredlight_vert = "" +
- "varying vec3 lightView;" +
- "varying vec4 clipPos;" +
- "uniform vec3 lightPos;" +
- "uniform mat4 matView;" +
- "void main() { " +
- "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"+
- "gl_Position = projectionMatrix * mvPosition;"+
- "lightView = vec3( matView * vec4( lightPos, 1.0 ) );" +
- "clipPos = gl_Position;"+
- "}"
- var deferredlight_frag = "" +
- "varying vec3 lightView;"+
- "varying vec4 clipPos;" +
- "uniform sampler2D samplerColor;"+
- "uniform sampler2D samplerDepth;"+
- "uniform sampler2D samplerNormals;"+
- "uniform sampler2D samplerLightBuffer;"+
- "uniform float lightRadius;"+
- "uniform float lightIntensity;"+
- "uniform float viewHeight;"+
- "uniform float viewWidth;"+
- "uniform vec3 lightColor;"+
- "uniform mat4 matProjInverse;"+
- "void main() {"+
- "vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );"+
- "float z = texture2D( samplerDepth, texCoord ).x;"+
- "float lightZ = clipPos.z / clipPos.w;"+
- /*
- "if ( z == 0.0 ) {"+
- "gl_FragColor = vec4( vec3( 0.0 ), 1.0 );"+
- "return;"+
- "}"+
- */
- "if ( z == 0.0 || lightZ > z ) discard;"+
- "float x = texCoord.x * 2.0 - 1.0;"+
- "float y = texCoord.y * 2.0 - 1.0;"+
- "vec4 projectedPos = vec4( x, y, z, 1.0 );"+
- "vec4 viewPos = matProjInverse * projectedPos;"+
- "viewPos.xyz /= viewPos.w;"+
- "viewPos.w = 1.0;"+
- "vec3 lightDir = lightView - viewPos.xyz;"+
- "float dist = length( lightDir );"+
- "lightDir = normalize( lightDir );"+
- "float cutoff = 0.3;"+
- "float denom = dist/lightRadius + 1.0;"+
- "float attenuation = 1.0 / ( denom * denom );"+
- "attenuation = ( attenuation - cutoff ) / ( 1.0 - cutoff );"+
- "attenuation = max( attenuation, 0.0 );"+
- "vec3 normal = texture2D( samplerNormals, texCoord ).xyz * 2.0 - 1.0;" +
- // wrap around lighting
- "float diffuseFull = max( dot( normal, lightDir ), 0.0 );" +
- "float diffuseHalf = max( 0.5 + 0.5 * dot( normal, lightDir ), 0.0 );" +
- "const vec3 wrapRGB = vec3( 0.9, 0.7, 0.7 );"+
- "vec3 diffuse = mix( vec3 ( diffuseFull ), vec3( diffuseHalf ), wrapRGB );"+
- // simple lighting
- //"float diffuseFull = max( dot( normal, lightDir ), 0.0 );" +
- //"vec3 diffuse = vec3 ( diffuseFull );"+
- // specular
- "const float shininess = 75.0;" +
- "const float specularIntensity = 0.4;"+
- "vec3 halfVector = normalize( lightDir - normalize( viewPos.xyz ) );" +
- "float dotNormalHalf = max( dot( normal, halfVector ), 0.0 );" +
- // simple specular
- //"vec3 specular = specularIntensity * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse;" +
- // physically based specular
- "vec3 specularColor = specularIntensity * vec3( 0.12 );"+
- "float specularNormalization = ( shininess + 2.0001 ) / 8.0;"+
- "vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightDir, halfVector ), 5.0 );"+
- "vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse * specularNormalization;"+
- // color
- "vec4 albedo = texture2D( samplerColor, texCoord );"+
- // combine
- "vec4 color = vec4( 0.0 );"+
- "color.xyz = albedo.xyz * lightColor * lightIntensity;"+
- "color.w = attenuation;"+
- "gl_FragColor = color * vec4( diffuse + specular, 1.0 );" +
- //"gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.05 );"+
- "}";
- var composite_vert = "" +
- "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;"+
- "}";
- var composite_frag = "" +
- "varying vec2 texCoord;"+
- "uniform sampler2D samplerLightBuffer;" +
- "uniform sampler2D samplerEmitter;" +
- "uniform vec3 lightPos;" +
- "void main() {" +
- "vec3 color = texture2D( samplerLightBuffer, texCoord ).xyz;" +
- "vec3 emitter = texture2D( samplerEmitter, texCoord ).xyz;"+
- "if ( emitter != vec3( 0.0 ) ) {"+
- "gl_FragColor = vec4( emitter, 1.0 );" +
- "} else {"+
- "gl_FragColor = vec4( sqrt( color ), 1.0 );" +
- "}"+
- "}"
- // -----------------------
- var normalShader = {
- uniforms: {},
- vertexShader: normals_vert,
- fragmentShader: normals_frag
- };
- // -----------------------
- var bumpShader = {
- uniforms: {
- bumpMap: { type: "t", value: null },
- bumpScale: { type: "f", value: 1 },
- offsetRepeat : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) }
- },
- vertexShader: bump_vert,
- fragmentShader: bump_frag
- };
- // -----------------------
- var clipDepthShader = {
- uniforms: {},
- vertexShader: clipdepth_vert,
- fragmentShader: clipdepth_frag
- };
- // -----------------------
- var unlitShader = {
- uniforms: {
- samplerDepth: { type: "t", value: null },
- viewWidth: { type: "f", value: WIDTH },
- viewHeight: { type: "f", value: HEIGHT },
- lightColor: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) }
- },
- vertexShader: unlit_vert,
- fragmentShader: unlit_frag
- };
- // -----------------------
- var lightShader = {
- uniforms: {
- samplerLightBuffer: { type: "t", value: null },
- samplerNormals: { type: "t", value: null },
- samplerDepth: { type: "t", value: null },
- samplerColor: { type: "t", value: null },
- matView : { type: "m4", value: new THREE.Matrix4() },
- matProjInverse : { type: "m4", value: new THREE.Matrix4() },
- viewWidth: { type: "f", value: WIDTH },
- viewHeight: { type: "f", value: HEIGHT },
- lightPos: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
- lightColor: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
- lightIntensity: { type: "f", value: 1.0 },
- lightRadius: { type: "f", value: 1.0 }
- },
- vertexShader: deferredlight_vert,
- fragmentShader: deferredlight_frag
- };
- // -----------------------
- var compositeShader = {
- uniforms: {
- samplerLightBuffer: { type: "t", value: null },
- samplerEmitter: { type: "t", value: null }
- },
- vertexShader: composite_vert,
- fragmentShader: composite_frag
- };
- // -----------------------------
- function bootstrap() {
- renderer = new THREE.WebGLRenderer( { alpha: false } );
- renderer.setSize( WIDTH, HEIGHT );
- renderer.setClearColorHex( 0x000000, 1 );
- var container = document.getElementById( 'container' );
- container.appendChild( renderer.domElement );
- // scene camera
- camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
- camera.position.z = 125;
- controls = new THREE.TrackballControls( camera, renderer.domElement );
- // scene for walt's head model
- scene = new THREE.Scene();
- sceneNode = new THREE.Object3D();
- scene.add( sceneNode );
- scene.add( camera );
- // scene for light proxy geometry
- lightScene = new THREE.Scene();
- lightNode = new THREE.Object3D();
- lightScene.add( lightNode );
- // scene for the coloured emitter spheres
- emitterScene = new THREE.Scene();
- emitterNode = new THREE.Object3D();
- emitterScene.add( emitterNode );
- // full screen quad for compositing
- quadScene = new THREE.Scene();
- quadNode = new THREE.Object3D();
- quadScene.add( quadNode );
- quadNode.add( new THREE.Mesh( new THREE.PlaneGeometry( 1, 1 ) ) );
- // stats
- stats = new Stats();
- stats.domElement.style.position = 'absolute';
- stats.domElement.style.top = '8px';
- stats.domElement.style.zIndex = 100;
- container.appendChild( stats.domElement );
- // clock
- clock = new THREE.Clock();
- }
- // -----------------------------
- function createRenderTargets() {
- var rtParamsFloat = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
- format: THREE.RGBAFormat, type: THREE.FloatType };
- var rtParamsUByte = { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, stencilBuffer: false,
- format: THREE.RGBFormat, type: THREE.UnsignedByteType };
- // ----------------------------------------------------------
- // g-buffer
- // ----------------------------------------------------------
- rtNormals = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
- rtDepth = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
- rtColor = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
- rtFinal = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
- rtNormals.generateMipmaps = false;
- rtDepth.generateMipmaps = false;
- rtColor.generateMipmaps = false;
- rtFinal.generateMipmaps = false;
- var passNormals = new THREE.RenderPass( scene, camera );
- compNormals = new THREE.EffectComposer( renderer, rtNormals );
- compNormals.addPass( passNormals );
- var passDepth = new THREE.RenderPass( scene, camera );
- compDepth = new THREE.EffectComposer( renderer, rtDepth );
- compDepth.addPass( passDepth );
- var passColor = new THREE.RenderPass( scene, camera );
- compColor = new THREE.EffectComposer( renderer, rtColor );
- compColor.addPass( passColor );
- // ----------------------------------------------------------
- // light emitter spheres
- // ----------------------------------------------------------
- var emitterPass = new THREE.RenderPass( emitterScene, camera );
- rtEmitter = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsUByte );
- rtEmitter.generateMipmaps = false;
- compEmitter = new THREE.EffectComposer( renderer, rtEmitter );
- compEmitter.addPass( emitterPass );
- // ----------------------------------------------------------
- // lighting pass
- // ----------------------------------------------------------
- rtLightBuffer = new THREE.WebGLRenderTarget( WIDTH, HEIGHT, rtParamsFloat );
- rtLightBuffer.generateMipmaps = false;
- var passLight = new THREE.RenderPass( lightScene, camera );
- compLightBuffer = new THREE.EffectComposer( renderer, rtLightBuffer );
- compLightBuffer.addPass( passLight );
- lightShader.uniforms[ 'samplerColor' ].value = compColor.renderTarget2;
- lightShader.uniforms[ 'samplerNormals' ].value = compNormals.renderTarget2;
- lightShader.uniforms[ 'samplerDepth' ].value = compDepth.renderTarget2;
- lightShader.uniforms[ 'samplerLightBuffer' ].value = rtLightBuffer;
- var geomEmitter = new THREE.SphereGeometry( 0.4, 7, 7 );
- for ( var x = 0; x < numLights; x ++ ) {
- var light = lights[ x ];
- // setup material
- var matLight = new THREE.ShaderMaterial({
- uniforms: THREE.UniformsUtils.clone( lightShader.uniforms ),
- vertexShader: lightShader.vertexShader,
- fragmentShader: lightShader.fragmentShader
- });
- matLight.blending = THREE.AdditiveBlending;
- matLight.transparent = true;
- matLight.depthWrite = false;
- matLight.uniforms[ "lightPos" ].value = light.position;
- matLight.uniforms[ "lightRadius" ].value = light.distance;
- matLight.uniforms[ "lightIntensity" ].value = light.intensity;
- matLight.uniforms[ "lightColor" ].value = light.color;
- // setup proxy geometry for this light
- var geomLight = new THREE.SphereGeometry( light.distance, 16, 8 );
- var meshLight = new THREE.Mesh( geomLight, matLight );
- lightNode.add( meshLight );
- // create emitter sphere
- var matEmitter = new THREE.ShaderMaterial({
- uniforms: THREE.UniformsUtils.clone( unlitShader.uniforms ),
- vertexShader: unlitShader.vertexShader,
- fragmentShader: unlitShader.fragmentShader
- });
- var meshEmitter = new THREE.Mesh( geomEmitter, matEmitter );
- meshEmitter.position = light.position;
- emitterNode.add( meshEmitter );
- // add emitter to light node
- meshLight.emitter = meshEmitter;
- }
- // ----------------------------------------------------------
- // composite
- // ----------------------------------------------------------
- compositeShader.uniforms[ 'samplerLightBuffer' ].value = compLightBuffer.renderTarget2;
- compositeShader.uniforms[ 'samplerEmitter' ].value = compEmitter.renderTarget2;
- compositePass = new THREE.ShaderPass( compositeShader );
- compositePass.needsSwap = true;
- //compositePass.renderToScreen = true;
- effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
- var width = window.innerWidth || 2;
- var height = window.innerHeight || 2;
- effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
- effectFXAA.renderToScreen = true;
- compFinal = new THREE.EffectComposer( renderer, rtFinal );
- compFinal.addPass( compositePass );
- compFinal.addPass( effectFXAA );
- }
- // -----------------------------
- function initScene( object, y, scale ) {
- var shader = THREE.ShaderLib[ "basic" ];
- object.traverse( function( node ) {
- if ( node.material ) {
- // color material
- var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
- var defines = { "USE_MAP": !!node.material.map, "GAMMA_INPUT": true };
- var material = new THREE.ShaderMaterial( { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, defines: defines } );
- uniforms.diffuse.value.copy( node.material.color );
- uniforms.map.value = node.material.map;
- if ( node.material.transparent ) {
- material.alphaTest = 0.1;
- }
- if ( node.material.name === "eyetrans" ) {
- material.visible = false;
- }
- node.properties.colorMaterial = material;
- // normal material
- if ( node.material.bumpMap ) {
- var uniforms = THREE.UniformsUtils.clone( bumpShader.uniforms );
- var normalMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: bumpShader.vertexShader, fragmentShader: bumpShader.fragmentShader } );
- uniforms.bumpMap.value = node.material.bumpMap;
- uniforms.bumpScale.value = node.material.bumpScale;
- var offset = node.material.bumpMap.offset;
- var repeat = node.material.bumpMap.repeat;
- uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
- node.properties.normalMaterial = normalMaterial;
- } else {
- node.properties.normalMaterial = matNormal;
- }
- // depth material
- node.properties.depthMaterial = matClipDepth;
- }
- } );
- object.position.y = y;
- object.scale.set( scale, scale, scale );
- sceneNode.add( object );
- }
- // -----------------------------
- function initMaterials() {
- matNormal = new THREE.ShaderMaterial({
- uniforms: normalShader.uniforms,
- vertexShader: normalShader.vertexShader,
- fragmentShader: normalShader.fragmentShader
- });
- matClipDepth = new THREE.ShaderMaterial({
- uniforms: clipDepthShader.uniforms,
- vertexShader: clipDepthShader.vertexShader,
- fragmentShader: clipDepthShader.fragmentShader
- });
- }
- // -----------------------------
- function initLights() {
- var distance = 20;
- // front light
- var light = new THREE.PointLight();
- light.color = new THREE.Vector3( 1, 1, 1 );
- light.intensity = 1.5;
- light.distance = 1.5 * distance;
- lights.push( light );
- // random lights
- for ( var i = 1; i < numLights; i ++ ) {
- var light = new THREE.PointLight();
- light.color = new THREE.Vector3( Math.random(), Math.random(), Math.random() ).normalize();
- // gamma to linear
- light.color.x *= light.color.x;
- light.color.y *= light.color.y;
- light.color.z *= light.color.z;
- light.intensity = 2.0;
- light.distance = distance;
- lights.push( light );
- }
- }
- // -----------------------------
- function animate() {
- var delta = clock.getDelta();
- requestAnimationFrame( animate );
- controls.update( delta );
- stats.update();
- render();
- }
- // -----------------------------
- function render() {
- // -----------------------------
- // g-buffer color
- // -----------------------------
- sceneNode.traverse( function( node ) {
- if ( node.material ) {
- node.material = node.properties.colorMaterial;
- }
- } );
- compColor.render();
- // -----------------------------
- // g-buffer depth
- // -----------------------------
- sceneNode.traverse( function( node ) {
- if ( node.material ) {
- node.material = node.properties.depthMaterial;
- }
- } );
- compDepth.render();
- // -----------------------------
- // g-buffer normals
- // -----------------------------
- sceneNode.traverse( function( node ) {
- if ( node.material ) {
- node.material = node.properties.normalMaterial;
- }
- } );
- compNormals.render();
- // -----------------------------
- // emitter pass
- // -----------------------------
- for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
- var light = lightNode.children[ i ];
- var color = light.material.uniforms[ "lightColor" ].value;
- var emitter = light.emitter;
- emitter.material.uniforms[ "samplerDepth" ].value = compDepth.renderTarget2;
- emitter.material.uniforms[ "lightColor" ].value = color;
- }
- compEmitter.render();
- // -----------------------------
- // light pass
- // -----------------------------
- camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
- for ( var i = 0, il = lightNode.children.length; i < il; i ++ ) {
- var uniforms = lightNode.children[ i ].material.uniforms;
- uniforms[ "matProjInverse" ].value = camera.projectionMatrixInverse;
- uniforms[ "matView" ].value = camera.matrixWorldInverse;
- }
- var time = Date.now() * 0.0002;
- // update lights
- var x, y, z;
- for ( var i = 0; i < numLights; i ++ ) {
- if ( i > 0 ) {
- x = Math.sin( time + i * 0.175 ) * 20;
- y = Math.cos( time + i * 0.153 ) * 30;
- z = Math.cos( time + i * 0.137 ) * 20;
- } else {
- x = Math.sin( time * 3 ) * 20;
- y = 15;
- z = Math.cos( time * 3 ) * 25 + 10;
- }
- var light = lightNode.children[ i ];
- var lightPosition = light.material.uniforms[ "lightPos" ].value;
- lightPosition.x = x;
- lightPosition.y = y;
- lightPosition.z = z;
- light.emitter.position = lightPosition;
- light.position = lightPosition;
- light.frustumCulled = false;
- }
- compLightBuffer.render();
- // -----------------------------
- // composite pass
- // -----------------------------
- compFinal.render();
- }
- // -----------------------------
- // entry point
- // -----------------------------
- bootstrap();
- initMaterials();
- initLights();
- createRenderTargets();
- var loader = new THREE.UTF8Loader();
- /*
- loader.load( "models/utf8/ben_dds.js", function ( object ) {
- initScene( object, -75, 150 );
- animate();
- }, { normalizeRGB: true } );
- */
- /*
- loader.load( "models/utf8/WaltHi.js", function ( object ) {
- initScene( object, -35, 1 );
- animate();
- }, { normalizeRGB: true } );
- */
- var loader = new THREE.JSONLoader();
- loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry, materials ) {
- var mapColor = THREE.ImageUtils.loadTexture( "obj/leeperrysmith/Map-COL.jpg" );
- var mapHeight = THREE.ImageUtils.loadTexture( "obj/leeperrysmith/Infinite-Level_02_Disp_NoSmoothUV-4096.jpg" );
- mapHeight.repeat.set( 0.998, 0.998 );
- mapHeight.offset.set( 0.001, 0.001 )
- mapHeight.wrapS = mapHeight.wrapT = THREE.RepeatWrapping;
- mapHeight.anisotropy = 4;
- mapHeight.format = THREE.RGBFormat;
- var material = new THREE.MeshPhongMaterial( { map: mapColor, bumpMap: mapHeight, bumpScale: 1.5 } );
- var object = new THREE.Mesh( geometry, material );
- initScene( object, 0, 8 );
- animate();
- } );
- </script>
- </body>
- </html>
|