64
HTML5 Gaming JAM40 Erik Oros & Jonathan Feldstein September 25-27, 2012

HTML5 Gaming - Mini Bandwidth Speed Test

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: HTML5 Gaming -   Mini Bandwidth Speed Test

HTML5 Gaming

JAM40

Erik Oros & Jonathan Feldstein

September 25-27, 2012

Page 2: HTML5 Gaming -   Mini Bandwidth Speed Test

Outline

WebWorks + HTML5

Canvas 2D

WebGL

How to draw a triangle

Frameworks

TunnelTilt

Peaks and Valleys

2

Page 3: HTML5 Gaming -   Mini Bandwidth Speed Test

WebWorks

3

Page 4: HTML5 Gaming -   Mini Bandwidth Speed Test

WebWorks + HTML5

Monetize Your Application

Create and deploy apps as .bar files

Hide Source

Useful APIs

Web Sockets

Device Motion

File Access

GPS

Payment

ActionScript Extensions

4

Page 5: HTML5 Gaming -   Mini Bandwidth Speed Test

Canvas 2D

5

Page 6: HTML5 Gaming -   Mini Bandwidth Speed Test

What is Canvas 2D?

A surface for programmatic rendering of shapes/images.

Unlike SVG, no scene graph.

<canvas id=“canvas2D” width=“640” height=“480”>

HTML5 canvas is not supported.

</canvas>

var canvas = document.querySelector(‘#canvas2d’);

var context = canvas.getContext(‘2d’);

6

Page 7: HTML5 Gaming -   Mini Bandwidth Speed Test

Canvas 2D Functionality

Rects, Paths, Images, Text, Transforms, Shadows, Line Caps and Joins, Colors and Styles, Animations, Clipping

All images attributed to Mozilla Contributors from https://developer.mozilla.org/en-US/docs/Canvas_tutorial and used under the Creative Commons Attribution-Sharealike license. 7

Page 8: HTML5 Gaming -   Mini Bandwidth Speed Test

Basic Example

function drawPath(context) {

context.beginPath();

context.moveTo(3, 0);

context.lineTo(10, 0);

context.quadraticCurveTo(30, 0, 20, 13);

context.quadraticCurveTo(0, 14, 0, 13);

context.closePath();

context.fillStyle = "#c0c0c0";

context.fill();

}

8

Page 9: HTML5 Gaming -   Mini Bandwidth Speed Test

Basic Example

function init() {

var elem = document.getElementById('myCanvas');

var canvasContext = elem.getContext('2d');

canvasContext.fillRect(0, 0, 125, 95);

var transX = [ 0.15, 0, 1.15, 1, 0.85, 2, 1.85 ];

var transY = [ 0.0, 0.7, 0, 0.7, 1.4, 0.5, 1.2 ];

canvasContext.translate(20,20);

for(var i=0; i<7; i++) {

canvasContext.save();

canvasContext.translate(30*transX[i], 30*transY[i]);

drawPath(canvasContext);

canvasContext.restore();

}

} 9

Page 10: HTML5 Gaming -   Mini Bandwidth Speed Test

Hardware Accelerated

BlackBerry PlayBook 2.0

Hardware acceleration through GPU.

Paths are tessellated and passed to OpenGL ES 2.0.

BlackBerry PlayBook 2.1

Updated graphics drivers for increased performance.

BlackBerry 10

Hardware and software improvements will continue the trend.

10

Page 11: HTML5 Gaming -   Mini Bandwidth Speed Test

Cocos2d-HTML5 Example

Custom ControlsOverlay.js created.

Joysticks and buttons.

Sprite art by Clint Bellanger

http://www.OpenGameArt.org

Tile art by Daniel Cook

http://www.LostGarden.com

Work In Progress

Documentation.

Open source.

11

Page 12: HTML5 Gaming -   Mini Bandwidth Speed Test

WebGL

12

Page 13: HTML5 Gaming -   Mini Bandwidth Speed Test

What is WebGL?

Khronos open standard

Brings 3D drawing to the HTML5 canvas tag

JavaScript bindings to OpenGL ES 2.0

13

Page 14: HTML5 Gaming -   Mini Bandwidth Speed Test

Pipeline Overview

14

Vertex Data Transformed Vertex Data

Triangle( , , );

Connectivity

Vertex Shader

Primitives

Rasterization

Fragments Colored Fragments

Fragment Shader

Assembly

Vertex Data Transformed Vertex Data

Page 15: HTML5 Gaming -   Mini Bandwidth Speed Test

WebGL – Big Picture

15

WebGL Program

GPU

Upload Data,

Modify State,

Run Commands

Query Data

CPU

Page 16: HTML5 Gaming -   Mini Bandwidth Speed Test

How To Draw In 5 “Easy” Steps!

1. Create Canvas

2. Setup Render Loop

3. Buffer Geometry

4. Setup Shaders

5. Render

16

Page 17: HTML5 Gaming -   Mini Bandwidth Speed Test

1. Create Canvas

It all starts with an HTML canvas

Say goodbye to EGL (yippie!)

17

Basic Canvas 2D Context Creation

<canvas id=“canvasId" width=“512” height=“512”>

</canvas>

<script type=“text/javascript”>

var canvas = document.getElementById(“canvasId”);

gl = canvas.getContext(“experimental-webgl”);

</script>

Page 18: HTML5 Gaming -   Mini Bandwidth Speed Test

2. Setup Render Loop

setTimeout(“render();”, 1000/60);

setInterval(“render();”, 1000/60);

window.requestAnimationFrame(“render();”, canvas);

18

Page 19: HTML5 Gaming -   Mini Bandwidth Speed Test

3. Buffer Geometry – Array Buffers

19

(-1, -1,0) (1, -1,0)

(0, 1,0)

x

y

Uploading Vertex Position Data to the GPU

var positionBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

var positions = [ -1, -1, 0, // Vertex 0

0, 1, 0, // Vertex 1

1, -1, 0 ]; // Vertex 2

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

positionBuffer.itemSize = 3; // (x, y, z)

positionBuffer.numItems = 3; // 3 vertices

Page 20: HTML5 Gaming -   Mini Bandwidth Speed Test

3. Buffer Geometry – Array Buffers (continued)

20

(-1, -1,0) (1, -1,0)

(0, 1,0)

x

y

Uploading Vertex Color Data to the GPU

colorBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

var colors = [ 1, 0, 0, 1, // Color 1 (Red)

0, 0, 1, 1, // Color 2 (Blue)

0, 1, 0, 1 ]; // Color 3 (Green)

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);

colorBuffer.itemSize = 4; // (r, g, b, a)

colorBuffer.numItems = 3; // 3 vertices

Page 21: HTML5 Gaming -   Mini Bandwidth Speed Test

4. Setup Shaders – Ins and Outs

21

Attributes Uniforms Uniforms

gl_Position

Varyings

gl_FragColor

Page 22: HTML5 Gaming -   Mini Bandwidth Speed Test

4. Setup Shaders – Example

22

Vertex Shader

attribute vec4 aColor;

attribute vec4 aPosition;

uniform mat4 uTransformMatrix;

varying vec4 vColor;

void main() {

gl_Position = uTransformMatrix * aPosition;

vColor = aColor;

}

Fragment Shader

precision highp float;

varying vec4 vColor;

void main() {

gl_FragColor = vColor;

}

Page 23: HTML5 Gaming -   Mini Bandwidth Speed Test

4. Setup Shaders – Create Programs

23

Vertex Shader

Fragment Shader

Shader Program

gl.linkProgram

gl.useProgram

gl.attachShader

gl.attachShader

gl.createProgram

gl.createShader

gl.shaderSource

gl.compileShader

gl.createShader

gl.shaderSource

gl.compileShader

Page 24: HTML5 Gaming -   Mini Bandwidth Speed Test

4. Setup Shaders – Locations

24

uTransformMatrix

Shader Program

WebGL Program

aColor

aPosition

GPU

Connect Buffered Data to Shader Inputs

// Where to send our position attribute data

var posLoc = gl.getAttribLocation(shaderProgram, "aPosition");

// Where to send our transformation matrix uniform data

var transLoc = gl.getUniformLocation(shaderProgram, “uTransformMatrix");

Page 25: HTML5 Gaming -   Mini Bandwidth Speed Test

5. Render

25

Render Frame

gl.clearColor(0, 0, 0, 1);

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.useProgram(shaderProgram);

// Setup Uniforms

gl.uniformMatrix4fv(transLoc, false, transMatrix);

// Setup Attributes

// Draw our primitives

Page 26: HTML5 Gaming -   Mini Bandwidth Speed Test

5. Render – With Array Buffers

26

Set Up Attributes and Draw Primitives

gl.enableVertexAttribArray(posLoc);

gl.enableVertexAttribArray(colorLoc);

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

gl.vertexAttribPointer(posLoc, positionBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);

gl.vertexAttribPointer(colorLoc, colorBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.drawArrays(gl.TRIANGLES, 0, positionBuffer.numItems);

gl.disableVertexAttribArray(colorLoc);

gl.disableVertexAttribArray(posLoc);

Page 27: HTML5 Gaming -   Mini Bandwidth Speed Test

Render – Primitive Types

27

Page 28: HTML5 Gaming -   Mini Bandwidth Speed Test

WebGL Frameworks

Page 29: HTML5 Gaming -   Mini Bandwidth Speed Test

WebGL Frameworks

J3D by Bartek Drozdz (Open source, MIT)

Leverage Unity3D scenes in your WebGL applications.

https://github.com/drojdjou/J3D

Inka3D (Closed source)

Leverage Maya scenes in your WebGL applications.

http://www.inka3d.com

CubicVR.js by Charles Cliffe (Open source, MIT)

Full-fledged WebGL framework, JSON/Collada imports, physics.

https://github.com/cjcliffe/CubicVR.js

Page 30: HTML5 Gaming -   Mini Bandwidth Speed Test

Three.js

Created by Ricardo Cabello as a 3D JavaScript library.

One of the most popular WebGL frameworks in use.

Large community involvement.

Under active development.

Distributed under MIT license.

https://github.com/mrdoob/three.js

Images from: http://mrdoob.github.com/three.js/ 30

Page 31: HTML5 Gaming -   Mini Bandwidth Speed Test

Pure WebGL vs. Three.js

Exercise: Drawing a square in 6 steps.

31

Pure WebGL Three.js

Create a Canvas. Import Three.js.

Get a WebGL context. Setup scene.

Setup a GLSL program. Setup camera.

Setup geometry. Add geometry with material.

Setup shaders.

Render. Render

Page 32: HTML5 Gaming -   Mini Bandwidth Speed Test

32

Step 1 of 6

Pure WebGL (Lines: 1) Create canvas.

<canvas id=“myCanvas” width=“1024” height=“512”></canvas>

Three.js (Lines: 1) Import Three.js.

<script src=“js/Three.js”></script>

Page 33: HTML5 Gaming -   Mini Bandwidth Speed Test

33

Step 2 of 6

Pure WebGL (Lines: 3) Get WebGL context.

var canvas = document.querySelector(“#myCanvas”); var gl = canvas.getContext(“experimental-webgl”);

Three.js (Lines: 2) Setup scene.

scene = new THREE.Scene();

Page 34: HTML5 Gaming -   Mini Bandwidth Speed Test

34

Step 3 of 6

Pure WebGL (Lines: 8) Setup GLSL program.

var vertexShader = createShaderFromScriptElement(gl, “2d-vertex-shader”); var fragmentShader = createShaderFromScriptElement(gl, “2d-fragment-shader”); var program = createProgram(gl, [vertexShader, fragmentShader]); gl.useProgram(program); var positionLocation = gl.getAttribLocation(program, “a_position”);

Three.js (Lines: 5) Setup camera.

camera = new THREE.PerspectiveCamera(FOV, ASPECT_RATIO, NEAR_PLANE, FAR_PLANE); camera.position.z = 1000.0; scene.add(camera);

Page 35: HTML5 Gaming -   Mini Bandwidth Speed Test

35

Step 4 of 6

Pure WebGL (Lines: 13) Buffer geometry.

var buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(

[-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0] ), gl.STATIC_DRAW);

gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

Three.js (Lines: 9) Add geometry with material.

geometry = new THREE.CubeGeometry(1024, 600, 0); material = new THREE.MeshBasicMaterial({color: 0x00FF00, wireframe: false}); mesh = new THREE.Mesh(geometry, material); scene.add(mesh);

Page 36: HTML5 Gaming -   Mini Bandwidth Speed Test

36

Step 5 of 6

Pure WebGL (Lines: 24) Setup shaders.

<script id=“2d-vertex-shader” type=“x-shader/x-vertex”> attribute vec2 a_position; void main() {

gl_Position = vec4(a_position, 0.0, 1.0); }

</script> <script id=“2d-fragment-shader” type=“x-shader/x-fragment”>

void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // Green.

} </script>

Page 37: HTML5 Gaming -   Mini Bandwidth Speed Test

37

Step 6 of 6

Pure WebGL (Lines: 25) Render.

gl.drawArrays(gl.TRIANGLES, 0, 6);

Three.js (Lines: 13) Render.

renderer = new THREE.CanvasRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); renderer.render(scene, camera);

Result:

Page 38: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt

38

Page 39: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt - Goals

Showcase our WebGL platform

Compelling piece of content

Leverage WebWorks + HTML5

Audio

Accelerometer

Package into .bar file

39

Page 40: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – SlipStream was born!

Model loading with JSON + XMLHttpRequest

Vertex positions, texture coords, normals, indices

Model from: http://www.psionic3d.co.uk

40

Page 41: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – A New Look

Curved tunnels

Light at the end of the tunnel

Higher frame rate

41

Page 42: HTML5 Gaming -   Mini Bandwidth Speed Test

Simple level.json File

{ “data” : [

{“angles” : [90, 270], “position” : 100}

]}

Loaded Level With XMLHttpRequest

var JSONobj = {};

var request = new XMLHttpRequest();

request.open(“GET”, “level.json”);

request.onreadystatechange = function(){

if(request.readyState == 4) {

JSONobj = JSON.parse(request.responseText);

}

};

TunnelTilt – SlipStream (continued)

42

90°

270°

Page 43: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt - Texturing

43

Load Image

Texture = function(filename) {

this.texId = gl.createTexture();

var image = new Image();

image.onload = function() {

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

gl.bindTexture(gl.TEXTURE_2D, this.texId);

gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);

};

image.src = filename;

};

Page 44: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt - Demo

Page 45: HTML5 Gaming -   Mini Bandwidth Speed Test

Useful Debugging Technique

1. Create glDebug to hold our debug context

2. Get WebGL Context

3. Iterate over WebGL context attributes

4. If the attribute is a function add a new function to glDebug

context that wraps the function and then calls getError()

5. If the attribute is not a function, copy it to glDebug

TunnelTilt - Debugging

45

Useful Debugging Technique

glDebug = {};

glDebug.gl = canvas.getContext(“experimental-webgl”);

for (var attr in glDebug.gl) {

var method = eval(“glDebug.gl.” + attr);

if (typeof(attr) == ‘function’) {

glDebug[attr] = function() {

var result = arguments.callee.realFunc.apply(this.gl, arguments);

var error = this.gl.getError();

if (error != 0) {

console.debug(arguments.callee.realFunc);

debugger;

}

return result;

}

} else {

glDebug[attr] = gl[attr];

}

} 29

Page 46: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt - Geometry

Use triangle strips

Better still use degenerate triangles

46

(with anti-aliasing)

Triangles

Triangle Strips

Degenerate Triangles

2k 20k Number of Triangles

32

32

34

26

27

29

Page 47: HTML5 Gaming -   Mini Bandwidth Speed Test

Triangles: 3 * number of triangles worth of vertices

Triangle strips: 2 + 2 * number of triangles worth of vertices

TunnelTilt – Geometry (continued)

47

A

B

C D

E F

A

B

C

D E G

F H

DE

Triangles Triangle Strips (Degenerate Triangles)

Page 48: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt - Precision

48

Reduce precision where possible

Samplers default to lowp

Query GL_FRAGMENT_PRECISION_HIGH for highp

Page 49: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – Precision (continued)

49

PlayBook Desktop

Precision Problem

uniform sampler2D uSampler;

void main(void) {

mediump float t = 255.0;

shininess = texture2D(uSampler, vTexCoords) * t;

}

Precision Problem

uniform mediump sampler2D uSampler;

void main(void) {

shininess = texture2D(uSampler, vTexCoords) * 255.0;

}

Precision Problem

uniform sampler2D uSampler;

void main(void) {

shininess = texture2D(uSampler, vTexCoords) * 255.0;

}

Page 50: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – Quality vs. Performance

50

Use Smaller Canvases

<canvas id=“canvasId" width=“512px” height=“300px” style=“width: 1024px;

height: 600px”>

</canvas>

Turn Off Anti-aliasing

<script type=“text/javascript”>

var canvas = document.getElementById(“canvasId”);

gl = canvas.getContext(“experimental-webgl”, {antialias:false});

</script>

Page 51: HTML5 Gaming -   Mini Bandwidth Speed Test

Point Sprites

Require less data

Beware: max size!

Move work to the GPU

Use the vertex shader

TunnelTilt - Particles

51

Page 52: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – WebWorks Tips

52

To Prevent Scrolling

function handleTouchMove(event) {

… // Do stuff

event.preventDefault();

}

document.ontouchmove = handleTouchMove;

To Prevent Zooming

<meta name="viewport" content="width=device-width,user-scalable=no"/>

To Lock the Orientation Add to config.xml

<rim:orientation mode=“landscape”/>

Page 53: HTML5 Gaming -   Mini Bandwidth Speed Test

TunnelTilt – Audio + Accelerometer

53

Audio HTML5 or Flash Audio

function playSoundHTML5(file, loops, volume) {

var audio = new Audio(file);

if (loops)

audio.loop = “true”;

audio.volume = volume;

audio.preload = “auto”;

audio.play();

}

Accelerometer DeviceMotion API

var accelX = 0;

window.addEventListener(“devicemotion”, function(event){

accelX = event.accelerationIncludingGravity.x;

}, true);

Page 54: HTML5 Gaming -   Mini Bandwidth Speed Test

TunneltTilt - Online

Play

Online at http://blackberry.github.com/WebGL-Samples/tunneltilt/

Free from BlackBerry App World (~73k downloads)

Download the source

https://github.com/blackberry/WebGL-Samples/

54

Page 55: HTML5 Gaming -   Mini Bandwidth Speed Test

Peaks and Valleys

Page 56: HTML5 Gaming -   Mini Bandwidth Speed Test

What Is Peaks and Valleys?

WebGL learning sample.

Combines a number of concepts:

Terrain generation

Skybox

Colour and texture blending

Ambient and directional lighting

Dual virtual joysticks for controls

Camera movement and rotation

www.github.com/blackberry/WebGL-Samples

Page 57: HTML5 Gaming -   Mini Bandwidth Speed Test

Diamond-Square Fractal Algorithm

http://www.gameprogrammer.com/fractal.html

Fault Algorithm

http://www.lighthouse3d.com/opengl/terrain/index.php3?fault

Raised Zones

Generate a square.

Raise all included vertices.

Repeat.

Average with neighbours.

Generating the Landscape

57

Page 58: HTML5 Gaming -   Mini Bandwidth Speed Test

Generating the Skybox

Two easy steps:

Paint the inside of a box.

Place box on head/camera.

Size limitations: 1024 x 1024

The magic happens with:

gl.disable(gl.DEPTH_TEST);

Don’t forget to turn this back on. 58

Page 59: HTML5 Gaming -   Mini Bandwidth Speed Test

Blending Colours and Textures

Fragment shader blends colours and textures.

vec4 diffuseSand = vec4(0.8, 1.0, 0.0, 1.0);

vec4 diffuseGrass = texture2D(texture1, vec2(vTextureCoord.s, vTextureCoord.t));

vec4 diffuseRock = vec4(0.5, 0.5, 0.5, 1.0);

vec4 diffuseSnow = vec4(1.0, 1.0, 1.0, 1.0);

vec4 color = vec4(1.0, 1.0, 1.0, 1.0);

color = mix(diffuseSand, color, min(abs( 400.0 - vPosition.y) / 500.0, 1.0));

color = mix(diffuseGrass, color, min(abs( 800.0 - vPosition.y) / 200.0, 1.0));

color = mix(diffuseRock, color, min(abs(1000.0 - vPosition.y) / 300.0, 1.0));

color = mix(diffuseSnow, color, min(abs(1200.0 - vPosition.y) / 300.0, 1.0));

gl_FragColor = vec4(color.rgb * vLightWeighting, color.a);

59

Page 61: HTML5 Gaming -   Mini Bandwidth Speed Test

Traversing Peaks and Valleys

Expanded on virtualjoystick.js by Jerome Etienne for multi-touch controls.

Minimize triangles via gl.TRIANGLE_STRIP.

61

Page 62: HTML5 Gaming -   Mini Bandwidth Speed Test

Let’s Talk More

Join the roundtable for this session at 6:00pm in Exhibit Hall 1

Continue the conversation on Twitter using the hashtag #BBJam and the session ID, #JAM40

62

Page 63: HTML5 Gaming -   Mini Bandwidth Speed Test

Don’t Forget

Download the BlackBerry Jam Americas Mobile Conference Guide from BlackBerry App World

Give us your Reasons to Believe at the 10k Reasons to Believe booth in the Jam Space

63

Page 64: HTML5 Gaming -   Mini Bandwidth Speed Test

THANK YOU

JAM40

Erik Oros & Jonathan Feldstein

September 25-27, 2012