source: other-projects/nz-flag-design/trunk/render-3d/test.html@ 29968

Last change on this file since 29968 was 29547, checked in by bmt11, 9 years ago

Added updating of textures so when the flag is changed the updated version will display. Also started implementing some nice CSS buttons for weather control and wind control to come soon

File size: 15.2 KB
Line 
1<!DOCTYPE html>
2<!-- saved from url=(0032)http://webgl.onikenkon.com/flag/ -->
3<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4
5 <title>three.js webgl - 3D Flag</title>
6 <meta charset="utf-8">
7 <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
8 <style>
9 body {
10 font-family: Monospace;
11 background-color: #000;
12 color: #000;
13 margin: 0px;
14 overflow: hidden;
15 }
16
17 #info {
18 text-align: center;
19 padding: 10px;
20 z-index: 10;
21 width: 100%;
22 position: absolute;
23 top: 80%;
24 }
25
26 a {
27 text-decoration: underline;
28 cursor: pointer;
29 }
30 </style>
31 <style type="text/css"></style></head>
32
33 <body>
34 <div id="info">
35 Toggle: <a onclick="rotate = !rotate;">Camera</a> |
36 <a onclick="wind = !wind;">Wind</a>
37 </div>
38
39 <script src="./Flag_files/three.js"></script>
40 <script src="./Flag_files/Detector.js"></script>
41 <script src="./Flag_files/Stats.js"></script>
42 <script src="./Flag_files/Flag.js"></script>
43 <script src="./Flag_files/KeyboardState.js"></script>
44
45 <script type="x-shader/x-fragment" id="fragmentShaderDepth">
46
47 uniform sampler2D texture;
48 varying vec2 vUV;
49
50 vec4 pack_depth( const in float depth ) {
51
52 const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );
53 const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );
54 vec4 res = fract( depth * bit_shift );
55 res -= res.xxyz * bit_mask;
56 return res;
57
58 }
59
60 void main() {
61
62 vec4 pixel = texture2D( texture, vUV );
63
64 if ( pixel.a < 0.5 ) discard;
65
66 gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );
67
68 }
69 </script>
70
71 <script type="x-shader/x-vertex" id="vertexShaderDepth">
72
73 varying vec2 vUV;
74
75 void main() {
76
77 vUV = 0.75 * uv;
78
79 vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
80
81 gl_Position = projectionMatrix * mvPosition;
82
83 }
84
85 </script>
86
87 <script>
88 var keyboard = new KeyboardState();
89 var clothTextures = [];
90
91 /* testing cloth simulation */
92
93 var flagRelease;
94 var initial = true;
95
96 var pins = [];
97 for (var j=0;j<=cloth.h;j++)
98 pins.push(cloth.index(0, j));
99
100 /* Weather variables */
101
102 var particle;
103 var particleSystem;
104 var particleCount;
105
106 /* ------------------ */
107
108 if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
109
110 var container, stats;
111 var camera, scene, renderer;
112
113 var clothGeometry;
114 var sphere;
115 var object, tmpFlag, arrow;
116
117 var rotate = false;
118
119 // array for holding existing flags
120
121 var flags = ["./images/flag.png", "./images/random.png", "./images/canada.png"];
122 var flagSelector = 0;
123 var materials;
124 var vertexShader;
125 var fragmentShader;
126 var uniforms;
127
128 init();
129 animate();
130
131 function init() {
132
133 container = document.createElement( 'div' );
134 document.body.appendChild( container );
135
136
137
138 // scene
139
140 scene = new THREE.Scene();
141
142 //scene.fog = new THREE.Fog( 0x0, 500, 10000 );
143 //scene.fog.color.setHSL( 0.6, 0.2, 1 );
144
145 // camera
146
147 camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, 1, 10000 );
148 camera.position.y = 50;
149 camera.position.z = 1500;
150 scene.add( camera );
151
152 // lights
153
154 var light;
155
156 scene.add( new THREE.AmbientLight( 0x666666 ) );
157
158 light = new THREE.DirectionalLight( 0xffffff, 1.75 );
159 light.color.setHSL( 0.6, 0.125, 1 );
160 light.position.set( 50, 200, 100 );
161 light.position.multiplyScalar( 1.3 );
162
163 light.castShadow = true;
164 //light.shadowCameraVisible = true;
165
166 light.shadowMapWidth = 2048;
167 light.shadowMapHeight = 2048;
168
169 var d = 100;
170
171 light.shadowCameraLeft = -d;
172 light.shadowCameraRight = d;
173 light.shadowCameraTop = d;
174 light.shadowCameraBottom = -d;
175
176 light.shadowCameraFar = 1000;
177 light.shadowDarkness = 0.5;
178
179 scene.add( light );
180
181 var light2 = new THREE.AmbientLight( 0x404040 ); // soft white light
182 scene.add( light2 );
183
184 light = new THREE.DirectionalLight( 0xffffff, 0.35 );
185 light.color.setHSL( 0.3, 0.95, 1 );
186 light.position.set( 0, -1, 0 );
187
188 scene.add( light );
189
190 // load flag textures
191 var i;
192
193 for(i = 0; i < flags.length; i++){
194 clothTextures[i] = THREE.ImageUtils.loadTexture( flags[i] );
195 clothTextures[i].wrapS = clothTextures[i].wrapT = THREE.RepeatWrapping;
196 clothTextures[i].anisotropy = 16;
197 }
198 createFlag();
199
200
201 // sphere
202
203 var ballGeo = new THREE.SphereGeometry( ballSize, 20, 20 );
204 var ballMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } );
205
206 sphere = new THREE.Mesh( ballGeo, ballMaterial );
207 sphere.castShadow = true;
208 sphere.receiveShadow = true;
209 scene.add( sphere );
210
211 // arrow
212
213 arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 0 ), 50, 0xff0000 );
214 arrow.position.set( -200, -50, -200 );
215 scene.add( arrow );
216
217
218 // create the particle variables
219 particleCount = 1000,
220 particles = new THREE.Geometry(),
221 pMaterial = new THREE.ParticleBasicMaterial({
222 color: 0xFFFFFF,
223 size: 20,
224 map: THREE.ImageUtils.loadTexture(
225 "./images/raindrop.png"
226 ),
227 blending: THREE.AdditiveBlending,
228 transparent: true
229 });
230
231 // now create the individual particles
232 for(var p = 0; p < particleCount; p++) {
233
234 // create a particle with random
235 // position values, -250 -> 250
236 var pX = Math.random() * 500 - 250,
237 pY = Math.random() * 500 - 250,
238 pZ = Math.random() * 500 - 250,
239 particle = new THREE.Vector3(pX, pY, pZ);
240
241 // create a velocity vector
242 particle.velocity = new THREE.Vector3(
243 0, // x
244 -Math.random(), // y
245 0); // z
246
247 // add it to the geometry
248 particles.vertices.push(particle);
249 }
250
251 // create the particle system
252 particleSystem = new THREE.ParticleSystem(
253 particles,
254 pMaterial);
255
256 particleSystem.sortParticles = true;
257
258 // add it to the scene
259 scene.add(particleSystem);
260
261
262 // ground
263
264 var initColor = new THREE.Color( 0x00ff00 );
265 initColor.setHSL( 0.25, 0.85, 0.5 );
266 var initTexture = THREE.ImageUtils.generateDataTexture( 1, 1, initColor );
267
268 var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: initTexture, perPixel: true } );
269
270 var groundTexture = THREE.ImageUtils.loadTexture( "grass.png", undefined, function() { groundMaterial.map = groundTexture } );
271 groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
272 groundTexture.repeat.set( 1, 1 );
273 groundTexture.anisotropy = 16;
274
275 var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
276 mesh.position.y = -250;
277 mesh.rotation.x = - Math.PI / 2;
278 mesh.receiveShadow = true;
279 scene.add( mesh );
280
281 // poles
282
283 var poleGeo = new THREE.BoxGeometry( 5, 750, 5 );
284 var poleMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 100, perPixel: true } );
285
286 var mesh = new THREE.Mesh( poleGeo, poleMat );
287 mesh.position.y = -175; //-250
288 mesh.position.x = 0;
289 mesh.receiveShadow = true;
290 mesh.castShadow = true;
291 scene.add( mesh );
292
293
294 var gg = new THREE.BoxGeometry( 10, 10, 10 );
295 var mesh = new THREE.Mesh( gg, poleMat );
296 mesh.position.y = -250;
297 mesh.position.x = 0; //125
298 mesh.receiveShadow = true;
299 mesh.castShadow = true;
300 scene.add( mesh );
301
302
303 //
304 renderer = new THREE.WebGLRenderer( { antialias: true } );
305 renderer.setSize( window.innerWidth, window.innerHeight );
306 //renderer.setClearColor( scene.fog.color );
307
308 container.appendChild( renderer.domElement );
309
310 renderer.gammaInput = true;
311 renderer.gammaOutput = true;
312 renderer.physicallyBasedShading = true;
313
314 renderer.shadowMapEnabled = true;
315
316 //
317
318 stats = new Stats();
319 stats.domElement.style.position = 'absolute';
320 stats.domElement.style.top = '0px';
321 container.appendChild( stats.domElement );
322
323 stats.domElement.children[ 0 ].children[ 0 ].style.color = "#aaa";
324 stats.domElement.children[ 0 ].style.background = "transparent";
325 stats.domElement.children[ 0 ].children[ 1 ].style.display = "none";
326
327 //
328
329 window.addEventListener( 'resize', onWindowResize, false );
330
331 sphere.visible = !true
332
333 }
334
335 //
336
337 function createFlag() {
338
339 // create materials
340 materials = [
341 new THREE.MeshPhongMaterial( { alphaTest: 0.5, ambient: 0xffffff, color: 0xffffff, specular: 0x030303, emissive: 0x111111, shininess: 20, perPixel: true, metal: false, map: clothTextures[flagSelector], side: THREE.DoubleSide } ),
342 new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true, transparent: true, opacity: 0.9 } )
343 ];
344
345
346
347 if(initial){
348
349 // cloth geometry
350
351 clothGeometry = new THREE.ParametricGeometry( clothFunction, cloth.w, cloth.h, true );
352 clothGeometry.dynamic = true;
353 clothGeometry.computeFaceNormals();
354
355 uniforms = { texture: { type: "t", value: 0, texture: clothTextures[0] } };
356 vertexShader = document.getElementById( 'vertexShaderDepth' ).textContent;
357 fragmentShader = document.getElementById( 'fragmentShaderDepth' ).textContent;
358
359 // cloth mesh
360 object = new THREE.Mesh( clothGeometry, materials[ 0 ] );
361 object.position.set( 0, 0, 0 );
362 object.castShadow = true;
363 object.receiveShadow = true;
364 scene.add( object );
365 initial = false;
366 object.customDepthMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: vertexShader, fragmentShader: fragmentShader } );
367
368 }else{
369 setPinning(false);
370 flagRelease = setInterval(function () {switchFlag()}, 2000);
371 }
372
373 }
374
375 //
376
377 function switchFlag() {
378
379 scene.remove( object );
380 setPinning(true);
381 object = new THREE.Mesh( clothGeometry, materials[ 0 ] );
382
383 object.position.set( 0, 0, 0 );
384 object.castShadow = true;
385 object.receiveShadow = true;
386 scene.add( object );
387 object.customDepthMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: vertexShader, fragmentShader: fragmentShader } );
388
389 // stop the timer for calling this method
390 clearInterval(flagRelease);
391 }
392
393 //
394
395 function onWindowResize() {
396
397 camera.aspect = window.innerWidth / window.innerHeight;
398 camera.updateProjectionMatrix();
399
400 renderer.setSize( window.innerWidth, window.innerHeight );
401
402 }
403
404 //
405
406 function animate() {
407
408 requestAnimationFrame( animate );
409
410 var time = Date.now();
411
412 windStrength = Math.cos( time / 7000 ) * 100 + 200;
413 windForce.set( 1000,500,Math.sin( time / 1000 ) ).normalize().multiplyScalar( windStrength );
414 arrow.setLength( windStrength );
415 arrow.setDirection( windForce );
416
417 // add some rotation to the system
418 particleSystem.rotation.y += 0.01;
419
420 var pCount = particleCount;
421 while(pCount > 0) {
422
423 // get the particle
424 particle = particles.vertices[pCount-1];
425
426 // check if we need to reset
427 if(particle.y < -200) {
428 particle.y = 200;
429 //particle.velocity.y = 0;
430 }
431 particle.velocity.y = -0.001;
432 particle.setY(
433 particle.y + particle.velocity);
434 pCount--;
435 }
436
437 // flag to the particle system that we've
438 // changed its vertices. This is the
439 // dirty little secret.
440 particleSystem.geometry.__dirtyVertices = true;
441 simulate(time);
442 render();
443 stats.update();
444
445 }
446
447 function render() {
448
449
450 var timer = Date.now() * 0.0002;
451
452 var p = cloth.particles;
453 keyboard.update();
454 if( keyboard.down("A")) {
455 flagSelector--;
456 if(flagSelector < 0) flagSelector = flags.length-1;
457 createFlag();
458
459 }else if(keyboard.down("D")) {
460 flagSelector++;
461 if(flagSelector >= flags.length) flagSelector = 0;
462 createFlag();
463 }
464
465
466 for ( var i = 0, il = p.length; i < il; i ++ ) {
467
468 clothGeometry.vertices[ i ].copy( p[ i ].position );
469
470 }
471
472 clothGeometry.computeFaceNormals();
473 clothGeometry.computeVertexNormals();
474
475 clothGeometry.normalsNeedUpdate = true;
476 clothGeometry.verticesNeedUpdate = true;
477
478 sphere.position.copy( ballPosition );
479
480 if ( rotate ) {
481
482 camera.position.x = Math.cos( timer ) * 1500;
483 camera.position.z = Math.sin( timer ) * 1500;
484
485 }
486
487 camera.lookAt( new THREE.Vector3(scene.position.x+150, scene.position.y+100, scene.position.z) );
488
489 renderer.render( scene, camera );
490
491 }
492
493 </script><div><canvas width="1366" height="600"></canvas><!--<div style="cursor: pointer; width: 80px; opacity: 0.9; z-index: 10001; position: absolute; top: 0px;"><div style="padding: 2px 0px 3px; background: transparent;"><div style="font-family: Helvetica, Arial, sans-serif; text-align: left; font-size: 9px; color: rgb(170, 170, 170); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">55 FPS</span> (0-60)</div><canvas width="74" height="30" style="display: none; margin-left: 3px;"></canvas></div><div style="padding: 2px 0px 3px; display: none; background-color: rgb(8, 24, 8);"><div style="font-family: Helvetica, Arial, sans-serif; text-align: left; font-size: 9px; color: rgb(0, 255, 0); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">16 MS</span> (1-607201)</div><canvas width="74" height="30" style="display: block; margin-left: 3px;"></canvas></div><div style="padding: 2px 0px 3px; display: none; background-color: rgb(24, 8, 13);"><div style="font-family: Helvetica, Arial, sans-serif; text-align: left; font-size: 9px; color: rgb(255, 0, 128); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">10 MEM</span> (10-10)</div><canvas width="74" height="30" style="display: block; margin-left: 3px;"></canvas></div></div></div><div><canvas height="932" width="1920"></canvas><div style="cursor: pointer; width: 80px; opacity: 0.9; z-index: 10001; position: absolute; top: 0px;"><div style="background: none repeat scroll 0% 0% transparent; padding: 2px 0px 3px;"><div style="font-family: Helvetica,Arial,sans-serif; text-align: left; font-size: 9px; color: rgb(170, 170, 170); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">60 FPS</span> (30-69)</div><canvas style="display: none; margin-left: 3px;" height="30" width="74"></canvas></div><div style="background-color: rgb(8, 24, 8); padding: 2px 0px 3px; display: none;"><div style="font-family: Helvetica,Arial,sans-serif; text-align: left; font-size: 9px; color: rgb(0, 255, 0); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">10 MS</span> (5-504)</div><canvas style="display: block; margin-left: 3px;" height="30" width="74"></canvas></div><div style="background-color: rgb(24, 8, 13); padding: 2px 0px 3px; display: none;"><div style="font-family: Helvetica,Arial,sans-serif; text-align: left; font-size: 9px; color: rgb(255, 0, 128); margin: 0px 0px 1px 3px;"><span style="font-weight:bold">MEM</span></div><canvas style="display: block; margin-left: 3px;" height="30" width="74"></canvas></div></div>--></div>
494
495</body></html>
Note: See TracBrowser for help on using the repository browser.