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
630
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
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
210
Hono + Inertia + React で LP を構築した話
oukayuka
2
170
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
500
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
1.1k
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
720
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
5
530
TSX の <Hoge<Fuga>> という構文に驚いた話 / tsx-type-argument-syntax
kanaru0928
0
240
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
160
メールのエイリアス機能を履き違えない
isshinfunada
0
250
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.8k
My Marp Sample
sinoue0108
0
120
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
210
Featured
See All Featured
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.9k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
480
Designing for Timeless Needs
cassininazir
1
450
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
420
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.5k
YesSQL, Process and Tooling at Scale
rocio
174
15k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Why Our Code Smells
bkeepers
PRO
340
58k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
220
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/