Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Threedee Tales From Urban Bohemia
Search
Vicent Martí
July 07, 2013
Programming
930
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
More Decks by Vicent Martí
See All by Vicent Martí
Unicorns Die With Bullets Made of Glitter
tanoku
6
620
My Mom told me that Git doesn't scale
tanoku
28
2.2k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Ruby is Unlike a Banana
tanoku
97
11k
Oh, you're so random
tanoku
14
2.7k
A talk about libgit2
tanoku
11
1.7k
Other Decks in Programming
See All in Programming
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
810
その節約、円になってますか?
isamumumu
1
680
Foundation Models frameworkで画像分析
ryodeveloper
1
510
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
130
「人を評価する AI」の設計と実装
ryoyanara
0
140
php-fpmのプロセスが枯渇した日-調査・対処・そして本当にやるべきだったこと-
shibuchaaaan
0
210
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
160
為什麼你並不需要ViewModel / No, you don't need a ViewModel
lovee
1
480
yield再入門 #phpcon
o0h
PRO
0
930
5分で問診!Composer セキュリティ健康診断
codmoninc
0
850
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
240
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
310
Featured
See All Featured
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
890
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
230
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
330
Into the Great Unknown - MozCon
thekraken
41
2.7k
Faster Mobile Websites
deanohume
310
32k
Building Applications with DynamoDB
mza
96
7.2k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.6k
Agile that works and the tools we love
rasmusluckow
331
22k
Embracing the Ebb and Flow
colly
88
5.1k
Facilitating Awesome Meetings
lara
57
7.1k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
240
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
420
Transcript
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/