Update ReadMe.md
[qtwebkit.git] / JSTests / microbenchmarks / v8-raytrace-with-empty-try-catch.js
blob54222dbfcf28d0f7189b59ed2125087706431f7b
1 // The ray tracer code in this file is written by Adam Burmister. It
2 // is available in its original form from:
3 //
4 //   http://labs.flog.nz.co/raytracer/
5 //
6 // It has been modified slightly by Google to work as a standalone
7 // benchmark, but the all the computational code remains
8 // untouched. This file also contains a copy of parts of the Prototype
9 // JavaScript framework which is used by the ray tracer.
11 // Variable used to hold a number that can be used to verify that
12 // the scene was ray traced correctly.
13 var checkNumber;
16 // ------------------------------------------------------------------------
17 // ------------------------------------------------------------------------
19 // The following is a copy of parts of the Prototype JavaScript library:
21 // Prototype JavaScript framework, version 1.5.0
22 // (c) 2005-2007 Sam Stephenson
24 // Prototype is freely distributable under the terms of an MIT-style license.
25 // For details, see the Prototype web site: http://prototype.conio.net/
27 var Class = {
28     create: function() {
29         return function() {
30             try {
31                 this.initialize.apply(this, arguments);
32             } catch(e) { }
33         }
34     }
38 Object.extend = function(destination, source) {
39     for (var property in source) {
40         try {
41             destination[property] = source[property];
42         } catch(e) { }
43     }
44     return destination;
48 // ------------------------------------------------------------------------
49 // ------------------------------------------------------------------------
51 // The rest of this file is the actual ray tracer written by Adam
52 // Burmister. It's a concatenation of the following files:
54 //   flog/color.js
55 //   flog/light.js
56 //   flog/vector.js
57 //   flog/ray.js
58 //   flog/scene.js
59 //   flog/material/basematerial.js
60 //   flog/material/solid.js
61 //   flog/material/chessboard.js
62 //   flog/shape/baseshape.js
63 //   flog/shape/sphere.js
64 //   flog/shape/plane.js
65 //   flog/intersectioninfo.js
66 //   flog/camera.js
67 //   flog/background.js
68 //   flog/engine.js
71 /* Fake a Flog.* namespace */
72 if(typeof(Flog) == 'undefined') var Flog = {};
73 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
75 Flog.RayTracer.Color = Class.create();
77 Flog.RayTracer.Color.prototype = {
78     red : 0.0,
79     green : 0.0,
80     blue : 0.0,
82     initialize : function(r, g, b) {
83         try {
84             if(!r) r = 0.0;
85             if(!g) g = 0.0;
86             if(!b) b = 0.0;
88             this.red = r;
89             this.green = g;
90             this.blue = b;
91         } catch(e) { }
92     },
94     add : function(c1, c2){
95         try {
96             var result = new Flog.RayTracer.Color(0,0,0);
98             result.red = c1.red + c2.red;
99             result.green = c1.green + c2.green;
100             result.blue = c1.blue + c2.blue;
102         } catch(e) { }
104         return result;
105     },
107     addScalar: function(c1, s){
108         try {
109             var result = new Flog.RayTracer.Color(0,0,0);
111             result.red = c1.red + s;
112             result.green = c1.green + s;
113             result.blue = c1.blue + s;
115             result.limit();
117         } catch(e) { }
119         return result;
120     },
122     subtract: function(c1, c2){
123         try {
124             var result = new Flog.RayTracer.Color(0,0,0);
126             result.red = c1.red - c2.red;
127             result.green = c1.green - c2.green;
128             result.blue = c1.blue - c2.blue;
130         } catch(e) { }
132         return result;
133     },
135     multiply : function(c1, c2) {
136         try {
137             var result = new Flog.RayTracer.Color(0,0,0);
139             result.red = c1.red * c2.red;
140             result.green = c1.green * c2.green;
141             result.blue = c1.blue * c2.blue;
143         } catch(e) { }
145         return result;
146     },
148     multiplyScalar : function(c1, f) {
149         try {
150             var result = new Flog.RayTracer.Color(0,0,0);
152             result.red = c1.red * f;
153             result.green = c1.green * f;
154             result.blue = c1.blue * f;
156         } catch(e) { }
158         return result;
159     },
161     divideFactor : function(c1, f) {
162         try {
163             var result = new Flog.RayTracer.Color(0,0,0);
165             result.red = c1.red / f;
166             result.green = c1.green / f;
167             result.blue = c1.blue / f;
169         } catch(e) { }
171         return result;
172     },
174     limit: function(){
175         try { 
176             this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0;
177             this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0;
178             this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0;
180         } catch(e) { }
181     },
183     distance : function(color) {
184         try {
185             var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
186         } catch(e) { }
187         return d;
188     },
190     blend: function(c1, c2, w){
191         try {
192             var result = new Flog.RayTracer.Color(0,0,0);
193             result = Flog.RayTracer.Color.prototype.add(
194                     Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
195                     Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
196                     );
197         } catch(e) { }
198         return result;
199     },
201     brightness : function() {
202         try {
203             var r = Math.floor(this.red*255);
204             var g = Math.floor(this.green*255);
205             var b = Math.floor(this.blue*255);
206         } catch(e) { }
207         return (r * 77 + g * 150 + b * 29) >> 8;
208     },
210     toString : function () {
211         try {
212             var r = Math.floor(this.red*255);
213             var g = Math.floor(this.green*255);
214             var b = Math.floor(this.blue*255);
215         } catch(e) { }
217         return "rgb("+ r +","+ g +","+ b +")";
218     }
220 /* Fake a Flog.* namespace */
221 if(typeof(Flog) == 'undefined') var Flog = {};
222 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
224 Flog.RayTracer.Light = Class.create();
226 Flog.RayTracer.Light.prototype = {
227     position: null,
228     color: null,
229     intensity: 10.0,
231     initialize : function(pos, color, intensity) {
232         try {
233             this.position = pos;
234             this.color = color;
235             this.intensity = (intensity ? intensity : 10.0);
237         } catch(e) { }
238     },
240     toString : function () {
241         try {
242             var result = 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
243         } catch(e) { }
244         return result;
245     }
247 /* Fake a Flog.* namespace */
248 if(typeof(Flog) == 'undefined') var Flog = {};
249 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
251 Flog.RayTracer.Vector = Class.create();
253 Flog.RayTracer.Vector.prototype = {
254     x : 0.0,
255     y : 0.0,
256     z : 0.0,
258     initialize : function(x, y, z) {
259         try {
260             this.x = (x ? x : 0);
261             this.y = (y ? y : 0);
262             this.z = (z ? z : 0);
263         } catch(e) { }
264     },
266     copy: function(vector){
267         try {
268             this.x = vector.x;
269             this.y = vector.y;
270             this.z = vector.z;
271         } catch(e) { }
272     },
274     normalize : function() {
275         try {
276             var m = this.magnitude();
277             var result = new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
278         } catch(e) { }
279         return result;
280     },
282     magnitude : function() {
283         try {
284             return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
285         } catch(e)  { }
286     },
288     cross : function(w) {
289         try {
290             return new Flog.RayTracer.Vector(
291                     -this.z * w.y + this.y * w.z,
292                     this.z * w.x - this.x * w.z,
293                     -this.y * w.x + this.x * w.y);
294         } catch(e) { }
295     },
297     dot : function(w) {
298         try {
299             return this.x * w.x + this.y * w.y + this.z * w.z;
300         } catch(e) { }
301     },
303     add : function(v, w) {
304         try {
305             return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
306         } catch(e) { }
307     },
309     subtract : function(v, w) {
310         try {
311             if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
312             return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
313         } catch(e) { }
314     },
316     multiplyVector : function(v, w) {
317         try {
318             return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
319         } catch(e) { }
320     },
322     multiplyScalar : function(v, w) {
323         try {
324             return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
325         } catch(e) { }
326     },
328     toString : function () {
329         try {
330             return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
331         } catch(e) { }
332     }
334 /* Fake a Flog.* namespace */
335 if(typeof(Flog) == 'undefined') var Flog = {};
336 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
338 Flog.RayTracer.Ray = Class.create();
340 Flog.RayTracer.Ray.prototype = {
341     position : null,
342     direction : null,
343     initialize : function(pos, dir) {
344         try {
345             this.position = pos;
346             this.direction = dir;
347         } catch(e) { }
348     },
350     toString : function () {
351         try {
352             return 'Ray [' + this.position + ',' + this.direction + ']';
353         } catch(e) { }
354     }
356 /* Fake a Flog.* namespace */
357 if(typeof(Flog) == 'undefined') var Flog = {};
358 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
360 Flog.RayTracer.Scene = Class.create();
362 Flog.RayTracer.Scene.prototype = {
363     camera : null,
364     shapes : [],
365     lights : [],
366     background : null,
368     initialize : function() {
369         try {
370             this.camera = new Flog.RayTracer.Camera(
371                     new Flog.RayTracer.Vector(0,0,-5),
372                     new Flog.RayTracer.Vector(0,0,1),
373                     new Flog.RayTracer.Vector(0,1,0)
374                     );
375             this.shapes = new Array();
376             this.lights = new Array();
377             this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
379         } catch(e) { }
380     }
382 /* Fake a Flog.* namespace */
383 if(typeof(Flog) == 'undefined') var Flog = {};
384 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
385 if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
387 Flog.RayTracer.Material.BaseMaterial = Class.create();
389 Flog.RayTracer.Material.BaseMaterial.prototype = {
391     gloss: 2.0,             // [0...infinity] 0 = matt
392     transparency: 0.0,      // 0=opaque
393     reflection: 0.0,        // [0...infinity] 0 = no reflection
394     refraction: 0.50,
395     hasTexture: false,
397     initialize : function() {
399     },
401     getColor: function(u, v){
403     },
405     wrapUp: function(t){
406         try {
407             t = t % 2.0;
408             if(t < -1) t += 2.0;
409             if(t >= 1) t -= 2.0;
410         } catch(e) { }
411         return t;
412     },
414     toString : function () {
415         try {
416             return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
417         } catch(e) { }
418     }
420 /* Fake a Flog.* namespace */
421 if(typeof(Flog) == 'undefined') var Flog = {};
422 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
424 Flog.RayTracer.Material.Solid = Class.create();
426 Flog.RayTracer.Material.Solid.prototype = Object.extend(
427         new Flog.RayTracer.Material.BaseMaterial(), {
428             initialize : function(color, reflection, refraction, transparency, gloss) {
429                 try {
430                     this.color = color;
431                     this.reflection = reflection;
432                     this.transparency = transparency;
433                     this.gloss = gloss;
434                     this.hasTexture = false;
435                 } catch(e) { }
436             },
438             getColor: function(u, v){
439                 try {
440                     return this.color;
441                 } catch(e) { }
442             },
444             toString : function () {
445                 try {
446                     return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
447                 } catch(e) { }
448             }
449         }
450         );
451 /* Fake a Flog.* namespace */
452 if(typeof(Flog) == 'undefined') var Flog = {};
453 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
455 Flog.RayTracer.Material.Chessboard = Class.create();
457 Flog.RayTracer.Material.Chessboard.prototype = Object.extend(
458         new Flog.RayTracer.Material.BaseMaterial(), {
459             colorEven: null,
460             colorOdd: null,
461             density: 0.5,
463             initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
464                 try {
465                     this.colorEven = colorEven;
466                     this.colorOdd = colorOdd;
467                     this.reflection = reflection;
468                     this.transparency = transparency;
469                     this.gloss = gloss;
470                     this.density = density;
471                     this.hasTexture = true;
472                 } catch(e) { }
473             },
475             getColor: function(u, v){
476                 try {
477                     var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
478                 } catch(e) { }
480                 if(t < 0.0)
481                     return this.colorEven;
482                 else
483                     return this.colorOdd;
484             },
486             toString : function () {
487                 try {
488                     return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
489                 } catch(e) { }
490             }
491         }
493 /* Fake a Flog.* namespace */
494 if(typeof(Flog) == 'undefined') var Flog = {};
495 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
496 if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
498 Flog.RayTracer.Shape.Sphere = Class.create();
500 Flog.RayTracer.Shape.Sphere.prototype = {
501     initialize : function(pos, radius, material) {
502         try {
503             this.radius = radius;
504             this.position = pos;
505             this.material = material;
507         } catch(e) { }
508     },
510     intersect: function(ray){
511         try {
512             var info = new Flog.RayTracer.IntersectionInfo();
513             info.shape = this;
515             var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
517             var B = dst.dot(ray.direction);
518             var C = dst.dot(dst) - (this.radius * this.radius);
519             var D = (B * B) - C;
521             if(D > 0){ // intersection!
522                 info.isHit = true;
523                 info.distance = (-B) - Math.sqrt(D);
524                 info.position = Flog.RayTracer.Vector.prototype.add(
525                         ray.position,
526                         Flog.RayTracer.Vector.prototype.multiplyScalar(
527                             ray.direction,
528                             info.distance
529                             )
530                         );
531                 info.normal = Flog.RayTracer.Vector.prototype.subtract(
532                         info.position,
533                         this.position
534                         ).normalize();
536                 info.color = this.material.getColor(0,0);
537             } else {
538                 info.isHit = false;
539             }
541         } catch(e) { }
542         return info;
543     },
545     toString : function () {
546         try {
547             return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
548         } catch(e) { }
549     }
551 /* Fake a Flog.* namespace */
552 if(typeof(Flog) == 'undefined') var Flog = {};
553 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
554 if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
556 Flog.RayTracer.Shape.Plane = Class.create();
558 Flog.RayTracer.Shape.Plane.prototype = {
559     d: 0.0,
561     initialize : function(pos, d, material) {
562         try {
563             this.position = pos;
564             this.d = d;
565             this.material = material;
566         } catch(e) { }
567     },
569     intersect: function(ray){
570         try {
571             var info = new Flog.RayTracer.IntersectionInfo();
573             var Vd = this.position.dot(ray.direction);
574             if(Vd == 0) return info; // no intersection
576             var t = -(this.position.dot(ray.position) + this.d) / Vd;
577             if(t <= 0) return info;
579             info.shape = this;
580             info.isHit = true;
581             info.position = Flog.RayTracer.Vector.prototype.add(
582                     ray.position,
583                     Flog.RayTracer.Vector.prototype.multiplyScalar(
584                         ray.direction,
585                         t
586                         )
587                     );
588             info.normal = this.position;
589             info.distance = t;
591             if(this.material.hasTexture){
592                 var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
593                 var vV = vU.cross(this.position);
594                 var u = info.position.dot(vU);
595                 var v = info.position.dot(vV);
596                 info.color = this.material.getColor(u,v);
597             } else {
598                 info.color = this.material.getColor(0,0);
599             }
601         } catch(e) { }
602         return info;
603     },
605     toString : function () {
606         try {
607             return 'Plane [' + this.position + ', d=' + this.d + ']';
608         } catch(e) { }
609     }
611 /* Fake a Flog.* namespace */
612 if(typeof(Flog) == 'undefined') var Flog = {};
613 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
615 Flog.RayTracer.IntersectionInfo = Class.create();
617 Flog.RayTracer.IntersectionInfo.prototype = {
618     isHit: false,
619     hitCount: 0,
620     shape: null,
621     position: null,
622     normal: null,
623     color: null,
624     distance: null,
626     initialize : function() {
627         try {
628             this.color = new Flog.RayTracer.Color(0,0,0);
629         } catch(e) { }
630     },
632     toString : function () {
633         try {
634             return 'Intersection [' + this.position + ']';
635         } catch(e) { }
636     }
638 /* Fake a Flog.* namespace */
639 if(typeof(Flog) == 'undefined') var Flog = {};
640 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
642 Flog.RayTracer.Camera = Class.create();
644 Flog.RayTracer.Camera.prototype = {
645     position: null,
646     lookAt: null,
647     equator: null,
648     up: null,
649     screen: null,
651     initialize : function(pos, lookAt, up) {
652         try {
653             this.position = pos;
654             this.lookAt = lookAt;
655             this.up = up;
656             this.equator = lookAt.normalize().cross(this.up);
657             this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
658         } catch(e) { }
659     },
661     getRay: function(vx, vy){
662         try {
663             var pos = Flog.RayTracer.Vector.prototype.subtract(
664                     this.screen,
665                     Flog.RayTracer.Vector.prototype.subtract(
666                         Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
667                         Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
668                         )
669                     );
670             pos.y = pos.y * -1;
671             var dir = Flog.RayTracer.Vector.prototype.subtract(
672                     pos,
673                     this.position
674                     );
676             var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
678         } catch(e) { }
679         return ray;
680     },
682     toString : function () {
683         try {
684             return 'Ray []';
685         } catch(e) { }
686     }
688 /* Fake a Flog.* namespace */
689 if(typeof(Flog) == 'undefined') var Flog = {};
690 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
692 Flog.RayTracer.Background = Class.create();
694 Flog.RayTracer.Background.prototype = {
695     color : null,
696     ambience : 0.0,
698     initialize : function(color, ambience) {
699         try {
700             this.color = color;
701             this.ambience = ambience;
702         } catch(e) { }
703     }
705 /* Fake a Flog.* namespace */
706 if(typeof(Flog) == 'undefined') var Flog = {};
707 if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
709 Flog.RayTracer.Engine = Class.create();
711 Flog.RayTracer.Engine.prototype = {
712     canvas: null, /* 2d context we can render to */
714     initialize: function(options){
715         try {
716             this.options = Object.extend({
717                 canvasHeight: 100,
718                 canvasWidth: 100,
719                 pixelWidth: 2,
720                 pixelHeight: 2,
721                 renderDiffuse: false,
722                 renderShadows: false,
723                 renderHighlights: false,
724                 renderReflections: false,
725                 rayDepth: 2
726             }, options || {});
728             this.options.canvasHeight /= this.options.pixelHeight;
729             this.options.canvasWidth /= this.options.pixelWidth;
731         } catch(e) { }
733         /* TODO: dynamically include other scripts */
734     },
736     setPixel: function(x, y, color){
737         try {
738             var pxW, pxH;
739             pxW = this.options.pixelWidth;
740             pxH = this.options.pixelHeight;
742             if (this.canvas) {
743                 this.canvas.fillStyle = color.toString();
744                 this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
745             } else {
746                 if (x ===  y) {
747                     checkNumber += color.brightness();
748                 }
749                 // print(x * pxW, y * pxH, pxW, pxH);
750             }
752         } catch(e) { }
753     },
755     renderScene: function(scene, canvas){
756         try {
757             checkNumber = 0;
758             /* Get canvas */
759             if (canvas) {
760                 this.canvas = canvas.getContext("2d");
761             } else {
762                 this.canvas = null;
763             }
765             var canvasHeight = this.options.canvasHeight;
766             var canvasWidth = this.options.canvasWidth;
768             for(var y=0; y < canvasHeight; y++){
769                 for(var x=0; x < canvasWidth; x++){
770                     try {
771                         var yp = y * 1.0 / canvasHeight * 2 - 1;
772                         var xp = x * 1.0 / canvasWidth * 2 - 1;
774                         var ray = scene.camera.getRay(xp, yp);
776                         var color = this.getPixelColor(ray, scene);
778                         this.setPixel(x, y, color);
780                     } catch(e) { }
781                 }
782             }
783         } catch(e) { }
784         if (checkNumber !== 2321) {
785             throw new Error("Scene rendered incorrectly");
786         }
787     },
789     getPixelColor: function(ray, scene){
790         try {
791             var info = this.testIntersection(ray, scene, null);
792             if(info.isHit){
793                 var color = this.rayTrace(info, ray, scene, 0);
794                 return color;
795             }
796             return scene.background.color;
797         } catch(e) { }
798     },
800     testIntersection: function(ray, scene, exclude){
801         try {
802             var hits = 0;
803             var best = new Flog.RayTracer.IntersectionInfo();
804             best.distance = 2000;
806             for(var i=0; i<scene.shapes.length; i++){
807                 try {
808                     var shape = scene.shapes[i];
810                     if(shape != exclude){
811                         var info = shape.intersect(ray);
812                         if(info.isHit && info.distance >= 0 && info.distance < best.distance){
813                             best = info;
814                             hits++;
815                         }
816                     }
818                 } catch(e) { }
819             }
820             best.hitCount = hits;
822         } catch(e) { }
823         return best;
824     },
826     getReflectionRay: function(P,N,V){
827         try {
828             var c1 = -N.dot(V);
829             var R1 = Flog.RayTracer.Vector.prototype.add(
830                     Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
831                     V
832                     );
834         } catch(e) { }
835         return new Flog.RayTracer.Ray(P, R1);
836     },
838     rayTrace: function(info, ray, scene, depth){
839         // Calc ambient
840         try {
841             var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
842             var oldColor = color;
843             var shininess = Math.pow(10, info.shape.material.gloss + 1);
845             for(var i=0; i<scene.lights.length; i++){
846                 try {
847                     var light = scene.lights[i];
849                     // Calc diffuse lighting
850                     var v = Flog.RayTracer.Vector.prototype.subtract(
851                             light.position,
852                             info.position
853                             ).normalize();
855                     if(this.options.renderDiffuse){
856                         var L = v.dot(info.normal);
857                         if(L > 0.0){
858                             color = Flog.RayTracer.Color.prototype.add(
859                                     color,
860                                     Flog.RayTracer.Color.prototype.multiply(
861                                         info.color,
862                                         Flog.RayTracer.Color.prototype.multiplyScalar(
863                                             light.color,
864                                             L
865                                             )
866                                         )
867                                     );
868                         }
869                     }
871                 } catch(e) { }
873                 try {
874                     // The greater the depth the more accurate the colours, but
875                     // this is exponentially (!) expensive
876                     if(depth <= this.options.rayDepth){
877                         // calculate reflection ray
878                         if(this.options.renderReflections && info.shape.material.reflection > 0)
879                         {
880                             var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
881                             var refl = this.testIntersection(reflectionRay, scene, info.shape);
883                             if (refl.isHit && refl.distance > 0){
884                                 refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
885                             } else {
886                                 refl.color = scene.background.color;
887                             }
889                             color = Flog.RayTracer.Color.prototype.blend(
890                                     color,
891                                     refl.color,
892                                     info.shape.material.reflection
893                                     );
894                         }
896                         // Refraction
897                         /* TODO */
898                     }
899                 }  catch(e) { }
901                 /* Render shadows and highlights */
903                 var shadowInfo = new Flog.RayTracer.IntersectionInfo();
905                 if(this.options.renderShadows){
906                     var shadowRay = new Flog.RayTracer.Ray(info.position, v);
908                     shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
909                     if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){
910                         var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
911                         var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
912                         color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
913                     }
914                 }
916                 try {
917                     // Phong specular highlights
918                     if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){
919                         var Lv = Flog.RayTracer.Vector.prototype.subtract(
920                                 info.shape.position,
921                                 light.position
922                                 ).normalize();
924                         var E = Flog.RayTracer.Vector.prototype.subtract(
925                                 scene.camera.position,
926                                 info.shape.position
927                                 ).normalize();
929                         var H = Flog.RayTracer.Vector.prototype.subtract(
930                                 E,
931                                 Lv
932                                 ).normalize();
934                         var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
935                         color = Flog.RayTracer.Color.prototype.add(
936                                 Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
937                                 color
938                                 );
939                     }
940                 } catch(e) { }
941             }
942             color.limit();
944         } catch(e) { }
945         return color;
946     }
950 function renderScene(){
951     try {
952         var scene = new Flog.RayTracer.Scene();
954         scene.camera = new Flog.RayTracer.Camera(
955                 new Flog.RayTracer.Vector(0, 0, -15),
956                 new Flog.RayTracer.Vector(-0.2, 0, 5),
957                 new Flog.RayTracer.Vector(0, 1, 0)
958                 );
960         scene.background = new Flog.RayTracer.Background(
961                 new Flog.RayTracer.Color(0.5, 0.5, 0.5),
962                 0.4
963                 );
965         var sphere = new Flog.RayTracer.Shape.Sphere(
966                 new Flog.RayTracer.Vector(-1.5, 1.5, 2),
967                 1.5,
968                 new Flog.RayTracer.Material.Solid(
969                     new Flog.RayTracer.Color(0,0.5,0.5),
970                     0.3,
971                     0.0,
972                     0.0,
973                     2.0
974                     )
975                 );
977         var sphere1 = new Flog.RayTracer.Shape.Sphere(
978                 new Flog.RayTracer.Vector(1, 0.25, 1),
979                 0.5,
980                 new Flog.RayTracer.Material.Solid(
981                     new Flog.RayTracer.Color(0.9,0.9,0.9),
982                     0.1,
983                     0.0,
984                     0.0,
985                     1.5
986                     )
987                 );
989         var plane = new Flog.RayTracer.Shape.Plane(
990                 new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
991                 1.2,
992                 new Flog.RayTracer.Material.Chessboard(
993                     new Flog.RayTracer.Color(1,1,1),
994                     new Flog.RayTracer.Color(0,0,0),
995                     0.2,
996                     0.0,
997                     1.0,
998                     0.7
999                     )
1000                 );
1002         scene.shapes.push(plane);
1003         scene.shapes.push(sphere);
1004         scene.shapes.push(sphere1);
1006         var light = new Flog.RayTracer.Light(
1007                 new Flog.RayTracer.Vector(5, 10, -1),
1008                 new Flog.RayTracer.Color(0.8, 0.8, 0.8)
1009                 );
1011         var light1 = new Flog.RayTracer.Light(
1012                 new Flog.RayTracer.Vector(-3, 5, -15),
1013                 new Flog.RayTracer.Color(0.8, 0.8, 0.8),
1014                 100
1015                 );
1017         scene.lights.push(light);
1018         scene.lights.push(light1);
1020         var imageWidth = 100; // $F('imageWidth');
1021         var imageHeight = 100; // $F('imageHeight');
1022         var pixelSize = "5,5".split(','); //  $F('pixelSize').split(',');
1023         var renderDiffuse = true; // $F('renderDiffuse');
1024         var renderShadows = true; // $F('renderShadows');
1025         var renderHighlights = true; // $F('renderHighlights');
1026         var renderReflections = true; // $F('renderReflections');
1027         var rayDepth = 2;//$F('rayDepth');
1029         var raytracer = new Flog.RayTracer.Engine(
1030                 {
1031                     canvasWidth: imageWidth,
1032                     canvasHeight: imageHeight,
1033                     pixelWidth: pixelSize[0],
1034                     pixelHeight: pixelSize[1],
1035                     "renderDiffuse": renderDiffuse,
1036                     "renderHighlights": renderHighlights,
1037                     "renderShadows": renderShadows,
1038                     "renderReflections": renderReflections,
1039                     "rayDepth": rayDepth
1040                 }
1041                 );
1043         raytracer.renderScene(scene, null, 0);
1044     } catch(e) { }
1047 for (var i = 0; i < 6; ++i)
1048     renderScene();