48
Aro Wierzbowski Tomasz Szepczyński Making games in

Making Games in WebGL - Aro Wierzbowski & Tomasz Szepczyński

Embed Size (px)

Citation preview

Aro WierzbowskiTomasz Szepczyński

Making games in

try it yourself!

William’s Quest

Demo: https://goo.gl/Q7Ggih

•WebGL 1.0

• Typescript

•Math (a lot of Math)

• Passion 😄

How was it made

Demo: https://goo.gl/Q7Ggih

- MDN web docs

WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D and 2D graphics within any compatible web browser without the use of plug-ins. WebGL does so by introducing an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 <canvas> elements.

WebGL

Demo: https://goo.gl/Q7Ggih

HTML:

<body> <canvas id="webgl-canvas"></canvas> </body>

engine.ts:

let canvas = <HTMLCanvasElement>document.getElementById('webgl-canvas'); let gl = <WebGLRenderingContext>canvas.getContext("webgl"); if (gl == null) { throw "No WebGL support"; }

WebGL - initial setup

Demo: https://goo.gl/Q7Ggih

• WebGL is a state machine

• WebGL can draw primitive shapes (lines, points, triangles) based on supplied data

• WebGL can color every single pixel of a drawn primitive shape

• To draw and color things WebGL uses Shaders

WebGL - facts

Demo: https://goo.gl/Q7Ggih

WebGL - mesh

Demo: https://goo.gl/Q7Ggih

WebGL - mesh representation in fileGeometryObject $geometry1 {

Mesh (primitive = "triangles") {

VertexArray (attrib = "position") {

float[3] // 3623 {

{-2.2362539768218994, 5.515564441680908, 12.59365177154541}, {-2.12605881690979, 4.948864459991455, 11.504551887512207}, {-2.521761178970337, 3.9739651679992676, 13.54375171661377}, {4.045838832855225, -4.078834056854248, 2.3464717864990234}, {4.3393378257751465, -4.510035991668701, 22.21135139465332}, {2.264341115951538, -4.585536479949951, 6.199451446533203}, {1.5406397581100464, -5.000636577606201, 10.583052635192871}, {0.363237202167511, -5.689136028289795, 21.08005142211914},

{0.363237202167511, -5.689136028289795, 21.08005142211914}, {4.3393378257751465, -4.510035991668701, 22.21135139465332}, {4.157639980316162, -4.222136974334717, 22.212251663208008}, {6.5994391441345215, -3.316436290740967, 23.439550399780273}, {6.417638301849365, -3.0286364555358887, 23.4405517578125}, {6.5994391441345215, -3.316436290740967, 23.439550399780273}, {8.894240379333496, -1.9856371879577637, 22.21755027770996}, {6.417638301849365, -3.0286364555358887, 23.4405517578125},

{8.712542533874512, -1.6977343559265137, 22.218551635742188}, {11.588839530944824, 0.532265305519104, 21.095550537109375}, {11.588839530944824, 0.532265305519104, 21.095550537109375}, {8.894240379333496, -1.9856371879577637, 22.21755027770996}, {10.65034008026123, 0.04806584119796753, 10.595551490783691}, {10.253241539001465, -0.15873652696609497, 6.450220108032227}, {8.600741386413574, -1.5544352531433105, 2.352720260620117}, {6.5994391441345215, -3.316436290740967, 23.439550399780273},

{6.50433874130249, -3.0976366996765137, -0.0046596527099609375}, {1.970239520072937, 4.9177632331848145, 0.44479942321777344}, {1.2974413633346558, 3.160862445831299, 0.4396800994873047}, {2.3366410732269287, 5.037765979766846, 1.3988895416259766}, {1.374841570854187, 3.062065601348877, -0.12100028991699219}, {1.5675410032272339, 1.5510642528533936, 0.44030189514160156}, {2.02243971824646, 4.753563404083252, -0.11606025695800781}, {2.02243971824646, 4.753563404083252, -0.11606025695800781},

{1.970239520072937, 4.9177632331848145, 0.44479942321777344}, {3.96343731880188, 4.822266101837158, -0.11646080017089844}, {3.9862377643585205, 4.989162921905518, 0.44439125061035156}, {2.3366410732269287, 5.037765979766846, 1.3988895416259766}, {4.052037715911865, 5.091564655303955, 1.406270980834961}, {2.416738271713257, 4.575165271759033, 4.059070587158203}, {3.5210397243499756, 4.6211628913879395, 4.16963005065918}, {2.045438528060913, 5.279263019561768, 9.835280418395996},

{2.416738271713257, 4.575165271759033, 4.059070587158203}, {1.6227396726608276, 2.6208655834198, 5.369930267333984}, {2.045438528060913, 5.279263019561768, 9.835280418395996}, {1.6047381162643433, 1.876763105392456, 1.8999900817871094}, {1.8072413206100464, 0.2383657991886139, 1.5104618072509766}, {1.2648409605026245, 2.5120627880096436, 2.0103302001953125}, {1.2648409605026245, 2.5120627880096436, 2.0103302001953125}, {1.7093409299850464, 2.7398648262023926, 3.6971702575683594},

{1.7093409299850464, 2.7398648262023926, 3.6971702575683594}, {2.7904412746429443, 1.585564374923706, 4.851861953735352}, {1.6227396726608276, 2.6208655834198, 5.369930267333984}, {2.567739248275757, 1.8070647716522217, 6.24104118347168}, {2.7904412746429443, 1.585564374923706, 4.851861953735352}, {3.75003981590271, 1.9715659618377686, 6.206731796264648}, {3.6324403285980225, 1.6986663341522217, 4.916341781616211}, {2.7904412746429443, 1.585564374923706, 4.851861953735352}, …

Demo: https://goo.gl/Q7Ggih

WebGL - texture

Demo: https://goo.gl/Q7Ggih

WebGL - combining texture and mesh

Demo: https://goo.gl/Q7Ggih

Shaders

• WebGL uses small programs called Shaders to draw geometry and colors onto the screen

• These programs are written in GLSL (GL Shading Language)

• The most used types of Shaders are: Vertex Shader and Fragment Shader

• Two Shaders are linked in a Shader Program

Shaders

Demo: https://goo.gl/Q7Ggih

Shaders - data flow

Demo: https://goo.gl/Q7Ggih

• Attributes and Buffers

• Uniforms

• Textures

• Varyings

Passing data to shaders

Demo: https://goo.gl/Q7Ggih

• Buffers are arrays of binary data uploaded to the GPU

• Usually they contain things like: positions, normals, texture coordinates, etc.

• But they can have anything that can be useful in Vertex Shader

Attributes and buffers

Demo: https://goo.gl/Q7Ggih

• There can be many buffers

• Buffer must be set (bind) as the current to be able use its content (e.g. draw objects)

• Buffer binding is a costly operation !Optimize!

• We need to tell WebGL how the data is positioned in the buffer

Attributes and buffers

Demo: https://goo.gl/Q7Ggih

// Create an empty buffer let vertexBuffer = gl.createBuffer();

// Pass down the vertices data gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

Buffers - example

Demo: https://goo.gl/Q7Ggih

// Get location of a_position variable placed in the shader program let positionAttributeLocation = gl.getAttribLocation(program, "a_position");

// Bind the position buffer. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

// Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) var size = 2; // 2 components per iteration var type = gl.FLOAT; // the data is 32bit floats var normalize = false; // don't normalize the data var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position var offset = 0; // start at the beginning of the buffer gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);

Attributes

Demo: https://goo.gl/Q7Ggih

• Allow to pass data to the shader program

• Passed data is not stored in any buffer (e.g. this could be a ordinary property like position in the game’s code)

• They can be understood as global variables set before execution of shader program

Uniforms

Demo: https://goo.gl/Q7Ggih

let someFloatLocation = gl.getUniformLocation(program, "u_some_float_location"); gl.uniform1f(someFloatLocation, 1.0);

Uniforms - example

Demo: https://goo.gl/Q7Ggih

• To draw images in WebGL we need to use textures

• Texture coordinates must be provided (0.0 to 1.0)

• To be able to use Texture it must be set as current and made active

• Single reference to a Texture is called texture unit

• There is a limitation of number of texture units active at the same time

Textures

Demo: https://goo.gl/Q7Ggih

let image = new Image(); image.src = "some_url.png" image.onload = () => {

var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, // type of data

0, // level of details gl.RGBA, // internal color components in the texture gl.RGBA, // color components in the texture gl.UNSIGNED_BYTE, // data type image); // the image

textures.push(texture);

}

Textures - creation example

Demo: https://goo.gl/Q7Ggih

var u_image0Location = gl.getUniformLocation(program, "u_image0"); var u_image1Location = gl.getUniformLocation(program, "u_image1"); // set which texture units to render with. gl.uniform1i(u_image0Location, 0); // texture unit 0 gl.uniform1i(u_image1Location, 1); // texture unit 1

gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, textures[0]); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, textures[1]);

Textures - usage example

Demo: https://goo.gl/Q7Ggih

• Varying variables are used to pass data from Vertex Shader to Fragment Shader

• Data from buffers cannot be passed directly to Fragment Shader

• The most common case is extracting texture coordinates in Vertex Shader and passing it to Fragment Shader

Varyings

Demo: https://goo.gl/Q7Ggih

attribute vec2 a_position;  attribute vec2 a_texCoord;

 varying vec2 v_texCoord;

void main() { gl_Position = vec4(a_position, 0, 1);

   // pass the texCoord to the fragment shader // The GPU will interpolate this value between points. v_texCoord = a_texCoord; }

Vertex Shader - example

Demo: https://goo.gl/Q7Ggih

uniform sampler2D u_image0; uniform sampler2D u_image1;

// the texCoords passed in from the vertex shader. varying vec2 v_texCoord;

void main() { vec4 color0 = texture2D(u_image0, v_texCoord); vec4 color1 = texture2D(u_image1, v_texCoord); gl_FragColor = color0 * color1; }

Fragment shader - example

Demo: https://goo.gl/Q7Ggih

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

Final step - making draw call

⚠ Very costly operation ⚠

Demo: https://goo.gl/Q7Ggih

*

Shaders - result

Demo: https://goo.gl/Q7Ggih

Game Architecture

Engine

Master renderer

RayCaster

Scene navigation controller

Game architecture

Sprite render 3D renderer

[Scene controllers]

Scene

Sprites 3D objects

Get current scene from Scene Navigation Controller

Draw call is requested

Get All 3D objects added to scene

Pass the 3d objects to Master

renderer

Master renderer sets the 3d shader and renders the models using object 3d

renderer

Get All 2D objects (Sprites) added to

scene

Master renderer sets the 2d shader and renders the

Sprites using Sprite renderer

Clear the screen and repeat

Rendering

Demo: https://goo.gl/Q7Ggih

Rendering - Shared geometry

SharedGeometry (static instance)

Knight vertices + texture coords

Create vertices + texture coords

Grass vertices + texture coords

Register

Model

Model

Model

models = Map<string, Model>

Demo: https://goo.gl/Q7Ggih

Rendering - Shared texture

SharedTexture (static instance)

Knight texture image data

Create texture image data

Grass texture image data

Register

textures = Map<string, Texture>

Demo: https://goo.gl/Q7Ggih

Rendering - Object3D

Knight

SharedGeometry (static instance) SharedTexture (static instance)

Get texture with key “knight”Get Model with key “knight”

Demo: https://goo.gl/Q7Ggih

Rendering - Object2D

Spritebatch

Texture referenceRegister vertices

Demo: https://goo.gl/Q7Ggih

• Main game loop

• Colliders representation

• Movement

Collision system

Demo: https://goo.gl/Q7Ggih

Clear screen

Get user input

Update world

Render

Repeat

Main loop

Demo: https://goo.gl/Q7Ggih

• Fluid time step

• Fixed time step

Main loop models

Demo: https://goo.gl/Q7Ggih

Process input Update game Render

• Too fast or too slow

• Better experience for high-end devices

• Non-deterministic

Fluid time step

Demo: https://goo.gl/Q7Ggih

Process input Update game Render

• Deterministic

• Framerate drops

• Requires tuning for high-end and low-end devices

Fixed time step

Demo: https://goo.gl/Q7Ggih

V V

S

V

V

S S

Fluid time step Fixed time step

Main loops

Demo: https://goo.gl/Q7Ggih

X

ZY

World coordinates

Colliders representation

Demo: https://goo.gl/Q7Ggih

Colliders coordinates

Colliders representation - 2D boxes

X

Z

Demo: https://goo.gl/Q7Ggih

• Raycasting

• Movement update loop

• Enemies

Movement

Demo: https://goo.gl/Q7Ggih

Source: http://pievisdev.blogspot.com/2015/05/survival-shooter-in-unity.html

Raycasting

dv

Movement update loop

Demo: https://goo.gl/Q7Ggih

dv

Enemies

Demo: https://goo.gl/Q7Ggih

Thank you

Demo: https://goo.gl/Q7Ggih