Initialize the graphics benchmark's Kalman filter with estimated 60 FPS
[WebKit-https.git] / PerformanceTests / Canvas / terrain.html
1 <!-- BSD License
2
3 Copyright (c) 2014, Hunter Loftis.
4  
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14  -->
15
16 <html>
17     <head>
18         <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
19         <title>Terrain Demo - PlayfulJS</title>
20         <script src="../resources/runner.js"></script>
21     </head>
22     <body>
23         <canvas id='display' style='background: #000'></canvas>
24         
25         <script>
26         Math.random = (function() {
27            var seed = 49734321;
28            return function() {
29                /* The Jenkins hash function:
30                    <http://en.wikipedia.org/wiki/Jenkins_hash_function>
31                    <http://burtleburtle.net/bob/hash/integer.html>
32                 */
33                seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
34                seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
35                seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
36                seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
37                seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
38                seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
39                return (seed & 0xfffffff) / 0x10000000;
40            };
41         })();
42        
43         function Terrain(detail) {
44            this.size = Math.pow(2, detail) + 1;
45            this.max = this.size - 1;
46            this.map = new Float32Array(this.size * this.size);
47         }
48         
49         Terrain.prototype.get = function(x, y) {
50             if (x < 0 || x > this.max || y < 0 || y > this.max)
51                 return -1;
52             return this.map[x + this.size * y];
53         };
54         
55         Terrain.prototype.set = function(x, y, val) {
56             this.map[x + this.size * y] = val;
57         };
58         
59         Terrain.prototype.generate = function(roughness) {
60             var self = this;
61             
62             this.set(0, 0, self.max);
63             this.set(this.max, 0, self.max / 2);
64             this.set(this.max, this.max, 0);
65             this.set(0, this.max, self.max / 2);
66             
67             divide(this.max);
68             
69             function divide(size) {
70                 var x, y, half = size / 2;
71                 var scale = roughness * size;
72                 if (half < 1)
73                     return;
74                 
75                 for (y = half; y < self.max; y += size) {
76                     for (x = half; x < self.max; x += size) {
77                         square(x, y, half, Math.random() * scale * 2 - scale);
78                     }
79                 }
80                 for (y = 0; y <= self.max; y += half) {
81                     for (x = (y + half) % size; x <= self.max; x += size) {
82                         diamond(x, y, half, Math.random() * scale * 2 - scale);
83                     }
84                 }
85                 divide(size / 2);
86             }
87             
88             function average(values) {
89                 var valid = values.filter(function(val) { return val !== -1; });
90                 var total = valid.reduce(function(sum, val) { return sum + val; }, 0);
91                 return total / valid.length;
92             }
93             
94             function square(x, y, size, offset) {
95                 var ave = average([
96                     self.get(x - size, y - size),   // upper left
97                     self.get(x + size, y - size),   // upper right
98                     self.get(x + size, y + size),   // lower right
99                     self.get(x - size, y + size)    // lower left
100                 ]);
101                 self.set(x, y, ave + offset);
102             }
103             
104             function diamond(x, y, size, offset) {
105                 var ave = average([
106                     self.get(x, y - size),      // top
107                     self.get(x + size, y),      // right
108                     self.get(x, y + size),      // bottom
109                     self.get(x - size, y)       // left
110                 ]);
111                 self.set(x, y, ave + offset);
112             }
113         };
114         
115         Terrain.prototype.draw = function(ctx, width, height) {
116             var self = this;
117             var waterVal = this.size * 0.3;
118             
119             for (var y = 0; y < this.size; y++) {
120                 for (var x = 0; x < this.size; x++) {
121                     var val = this.get(x, y);
122                     var top = project(x, y, val);
123                     var bottom = project(x + 1, y, 0);
124                     var water = project(x, y, waterVal);
125                     var style = brightness(x, y, this.get(x + 1, y) - val);
126                     
127                     rect(top, bottom, style);
128                     rect(water, bottom, 'rgba(50, 150, 200, 0.15)');
129                 }
130             }
131             
132             function rect(a, b, style) {
133                 if (b.y < a.y)
134                     return;
135                 ctx.fillStyle = style;
136                 ctx.fillRect(a.x, a.y, b.x - a.x, b.y - a.y);
137             }
138             
139             function brightness(x, y, slope) {
140                 if (y === self.max || x === self.max)
141                     return '#000';
142                 var b = ~~(slope * 50) + 128;
143                 return ['rgba(', b, ',', b, ',', b, ',1)'].join('');
144             }
145             
146             function iso(x, y) {
147                 return {
148                     x: 0.5 * (self.size + x - y),
149                     y: 0.5 * (x + y)
150                 };
151             }
152             
153             function project(flatX, flatY, flatZ) {
154                 var point = iso(flatX, flatY);
155                 var x0 = width * 0.5;
156                 var y0 = height * 0.2;
157                 var z = self.size * 0.5 - flatZ + point.y * 0.75;
158                 var x = (point.x - self.size * 0.5) * 6;
159                 var y = (self.size - point.y) * 0.005 + 1;
160                 
161                 return {
162                     x: x0 + x / y,
163                     y: y0 + z / y
164                 };
165             }
166         };
167         
168         var display = document.getElementById('display');
169         var ctx = display.getContext('2d');
170         var width = display.width = 1024;
171         var height = display.height = 768;
172         
173         PerfTestRunner.measureTime({
174             run: function() {
175                 var terrain = new Terrain(9);
176                 terrain.generate(0.5);
177                 ctx.clearRect(0, 0, width, height);
178                 terrain.draw(ctx, width, height);
179             }
180         });
181         </script>
182     </body>
183 </html>