Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Threedee Tales From Urban Bohemia
Search
Vicent Martí
July 07, 2013
Programming
950
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Threedee Tales From Urban Bohemia
An introduction to 3D graphics on the web using WebGL.
Vicent Martí
July 07, 2013
Transcript
111 slides
None
3D is hard
We’re building a videogame
We’re building a videogame
None
None
None
(You are being a smartass)
None
WHAT?
WebGL is A JavaScript API to render graphics accessing directly
the GPU
WebGL is not An API for 3D graphics
WebGL is not An OpenGL Wrapper
angle angle OpenGL ES 2.0 to DirectX 9 translation
angle angle OpenGL ES 2.0 to DirectX 9 translation
WHERE?
None
DIV
CANVAS DIV
WebGL context CANVAS “webgl” .getContext(“webgl”) WebGL context the
WebGL context WebGL context(s) a b a.getContext(“webg b.getContext(“webg
WHEN?
DRAW DRAW DRAW DRAW DRAW DRAW DRAW DRAW Not when
you want to
When the browser tells you to.
When the browser tells you to. requestAnimationFrame
BRO WHAT ABOUT DOUBLE BUFFERING
None
Tearing
Buffer A Buffer B
Buffer A Buffer B
Buffer A Buffer B
JavaScript doesn’t execute while the DOM is being rendered!
JavaScript doesn’t execute while the DOM is being rendered!
HOW?
Introducing... Jimmy the Vertex
I’m not looking forward to this...
(x, y, z)
+x +y +z RIGHT HAND REPRESENT
None
None
None
Local Space
World Space
Camera Space
Camera Space
Screen Space
xx xy xz Yx Yy Yz Zx Zy Zz {
} World Space Local Space Model Matrix
xx xy xz Yx Yy Yz Zx Zy Zz {
} Camera Space World Space View Matrix
xx xy xz Yx Yy Yz Zx Zy Zz {
} Screen Space Camera Space Projection Matrix
We could do the matrix operations in JavaScript
We could do the matrix operations in JavaScript BUT WE
DON’T
SHADER is a program that runs on the GPU. SHADER
a
(THAT WAS EASY)
N N It begins with an...
OT JAVASCRIPT N N It begins with an...
GLSL GLSL OpenGL Shader Language
precision highp float; varying vec2 t; varying vec2 pos; uniform
float time; uniform vec2 mouse; uniform int mouseLeft; uniform sampler2D tex0; void main() { float v1 = (sin(t.s+time) + 1.0) / 2.0; float v2 = (cos(t.t+time) + 1.0) / 2.0; float d = distance(mouse, pos); vec2 tt = vec2(t.s+sin(time/10.0), t.t+cos(time/10.0)); vec4 c1 = texture2D(tex0, tt) * 1.1; float avg = (c1.r+c1.g+c1.b)/3.0; float r = c1.r+v1*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float g = c1.g+v2*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float b = c1.g - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); gl_FragColor = vec4(r, g, b, 1.0); }
precision highp float; varying vec2 t; varying vec2 pos; uniform
float time; uniform vec2 mouse; uniform int mouseLeft; uniform sampler2D tex0; void main() { float v1 = (sin(t.s+time) + 1.0) / 2.0; float v2 = (cos(t.t+time) + 1.0) / 2.0; float d = distance(mouse, pos); vec2 tt = vec2(t.s+sin(time/10.0), t.t+cos(time/10.0)); vec4 c1 = texture2D(tex0, tt) * 1.1; float avg = (c1.r+c1.g+c1.b)/3.0; float r = c1.r+v1*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float g = c1.g+v2*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float b = c1.g - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); gl_FragColor = vec4(r, g, b, 1.0); } WELL THIS KINDA LOOKS LIKE JAVASCRIPT WELL THIS KINDA LOOKS LIKE JAVASCRIPT
precision highp float; varying vec2 t; varying vec2 pos; uniform
float time; uniform vec2 mouse; uniform int mouseLeft; uniform sampler2D tex0; void main() { float v1 = (sin(t.s+time) + 1.0) / 2.0; float v2 = (cos(t.t+time) + 1.0) / 2.0; float d = distance(mouse, pos); vec2 tt = vec2(t.s+sin(time/10.0), t.t+cos(time/10.0)); vec4 c1 = texture2D(tex0, tt) * 1.1; float avg = (c1.r+c1.g+c1.b)/3.0; float r = c1.r+v1*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float g = c1.g+v2*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float b = c1.g - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); gl_FragColor = vec4(r, g, b, 1.0); }
precision highp float; varying vec2 t; varying vec2 pos; uniform
float time; uniform vec2 mouse; uniform int mouseLeft; uniform sampler2D tex0; void main() { float v1 = (sin(t.s+time) + 1.0) / 2.0; float v2 = (cos(t.t+time) + 1.0) / 2.0; float d = distance(mouse, pos); vec2 tt = vec2(t.s+sin(time/10.0), t.t+cos(time/10.0)); vec4 c1 = texture2D(tex0, tt) * 1.1; float avg = (c1.r+c1.g+c1.b)/3.0; float r = c1.r+v1*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float g = c1.g+v2*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float b = c1.g - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); gl_FragColor = vec4(r, g, b, 1.0); } “
precision highp float; varying vec2 t; varying vec2 pos; uniform
float time; uniform vec2 mouse; uniform int mouseLeft; uniform sampler2D tex0; void main() { float v1 = (sin(t.s+time) + 1.0) / 2.0; float v2 = (cos(t.t+time) + 1.0) / 2.0; float d = distance(mouse, pos); vec2 tt = vec2(t.s+sin(time/10.0), t.t+cos(time/10.0)); vec4 c1 = texture2D(tex0, tt) * 1.1; float avg = (c1.r+c1.g+c1.b)/3.0; float r = c1.r+v1*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float g = c1.g+v2*pow(avg,4.0) - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); float b = c1.g - pow(d,pow(avg,2.0) +float(mouseLeft)*avg); gl_FragColor = vec4(r, g, b, 1.0); } <script id="fragment-shader" type="x-shader/x-fragment"> </script>
document.getElementById document.getElementById
GLSL GLSL GLSL compile compile compile link
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Perspective Matrix Model View Matrix
attribute vec3 aVertexPosition; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; void
main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); }
attribute vec3 aVertexPosition; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; void
main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); } Output
attribute vec3 aVertexPosition; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; void
main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); } Output Uniforms
attribute vec3 aVertexPosition; uniform mat4 uMVMatrix; uniform mat4 uPMatrix; void
main(void) { gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); } Output Uniforms Attribute
None
None
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Passing Uniforms var ptr = gl.getUniformLocation(shaderProgram, "uPMatrix") gl.uniformMatrix4fv( ptr, false, new Float32Array(vertexes));
None
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, Here come the vertices
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, Here come the vertices
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, Here come the vertices
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, Here come the vertices
-1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0,
1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, Here come the vertices
cubeVertices = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertices); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER,
cubeVertices); gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 Passing Vertices
cubeVertices = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertices); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER,
cubeVertices); gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 Passing Vertices
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Uniforms gl_Position 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 [aVertexPosition] drawArrays*
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Uniforms gl_Position 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 [aVertexPosition] drawArrays*
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Uniforms gl_Position 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 [aVertexPosition] drawArrays*
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Uniforms gl_Position 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 [aVertexPosition] drawArrays*
xx xy xz Yx Yy Yz Zx Zy Zz {
} xx xy xz Yx Yy Yz Zx Zy Zz { } Uniforms gl_Position 0,1,0 1,0,0 0,1,1 1,0,1 1,1,1 [aVertexPosition] drawArrays*
Rasterization
None
None
Fragments
Fragment Shader varying lowp vec4 vColor; void main(void) { gl_FragColor
= vColor; }
Fragment Shader varying lowp vec4 vColor; void main(void) { gl_FragColor
= vColor; } Output
Fragment Shader varying lowp vec4 vColor; void main(void) { gl_FragColor
= vColor; } Output Variant
Variants Vertex Shader Fragment Shader
None
None
Color
Color Texture
Color Texture Lighting
Color Texture Lighting Specularity
Color Texture Lighting Specularity Normal Mapping
Color Texture Lighting Specularity Normal Mapping ...
Clear Canvas Load Perspective M atrixes Load O bject M
atrixes Render O bject
None
Three.js https://github.com/mrdoob/three.js A.K.A. use
3D is hard
3D is hard hard to understand
3D is hard hard to understand hard to learn
Hard to get right
But we need to try
None
twitter.com/vmg github.com/vmg
With demos from: http://wagerfield.github.io/flat-surface-shader/ http://lab.aerotwist.com/webgl/surface/ http://www.mrdoob.com/lab/javascript/beachballs/ http://plumegraph.org/
More Decks by Vicent Martí
See All by Vicent Martí
Unicorns Die With Bullets Made of Glitter
tanoku
6
650
My Mom told me that Git doesn't scale
tanoku
28
2.2k
Intergalactic Javascript Robots from Outer Space
tanoku
273
28k
Ruby is Unlike a Banana
tanoku
97
11k
Oh, you're so random
tanoku
14
2.7k
A talk about libgit2
tanoku
11
1.8k
Other Decks in Programming
See All in Programming
Event is what happens
moro
2
4.5k
高橋メソッドでCVE解説シリーズ 〜CVE-2026-112816〜
hakkadaikon
0
250
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
3
1.7k
Crash Auto Pipelines
veronikapj
1
410
Lambda durable functionsでHuman in the Loopを楽に…楽に……
har1101
2
300
仕様駆動開発入門 (何を作るかを先に決めて渡す) | 目指せ Kiro マスター 05
inariku
PRO
2
130
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
280
Growing PicoRuby's Ecosystem on ESP32
yuuu
2
120
プロジェクトコードをキレイキレイしよう!暗黙的な参照を読み解く静的解析
ostk0069
0
210
動画プレイヤーはなぜカクつくのか 〜Flutterのレンダリングとネイティブの境界を解剖する〜
naruogram
0
330
SFCで実現する病院・医療システムの動的組み立て式UI
koukimiura
1
180
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
16
9.1k
Featured
See All Featured
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7.1k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
1
300
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.4k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.5k
Everyday Curiosity
cassininazir
0
400
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
300
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.9k
Balancing Empowerment & Direction
lara
6
1.4k
Practical Orchestrator
shlominoach
192
12k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k