forked from martinlaxenaire/curtainsjs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
get-started.html
376 lines (331 loc) · 12.5 KB
/
get-started.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- Metas -->
<title>curtains.js | Get Started</title>
<meta name="description" content="curtains.js is a lightweight vanilla WebGL javascript library that turns HTML elements into interactive textured planes." />
<link rel="canonical" href="https://www.martin-laxenaire.fr/libs/curtainsjs/get-started.html" />
<!-- Facebook OG -->
<meta property="og:title" content="curtains.js | Get Started" />
<meta property="og:type" content="website" />
<meta property="og:description" content="curtains.js is a lightweight vanilla WebGL javascript library that turns HTML elements into interactive textured planes." />
<meta property="og:url" content="https://www.martin-laxenaire.fr/libs/curtainsjs/get-started.html" />
<meta property="og:image" content="https://www.martin-laxenaire.fr/libs/curtainsjs/images/intro-background.jpg"/>
<!-- Twitter card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@webdesign_ml">
<meta name="twitter:creator" content="@webdesign_ml">
<meta name="twitter:title" content="curtains.js | Get Started" />
<meta name="twitter:description" content="curtains.js is a lightweight vanilla WebGL javascript library that turns HTML elements into interactive textured planes." />
<meta name="twitter:image" content="https://www.martin-laxenaire.fr/libs/curtainsjs/images/intro-background.jpg" />
<link href="https://fonts.googleapis.com/css?family=PT+Sans:400,700" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Abril+Fatface" rel="stylesheet">
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<div id="page-wrap">
<div id="canvas"></div>
<div id="content">
<header id="header">
<div class="wrapper">
<div id="header-wrapper" class="flex-wrapper">
<div id="header-title">
<a href="index.html" title="Home">curtains.js</a>
</div>
<nav id="main-menu">
<ul class="flex-wrapper">
<li>
<a href="get-started.html" class="active">Get started</a>
</li>
<li>
<a href="documentation.html">Docs</a>
</li>
<li>
<a href="download.html">Download</a>
</li>
</ul>
</nav>
</div>
</div>
</header>
<section class="content-section">
<div class="wrapper">
<div class="text-section inner-section">
<h1>Get started</h1>
</div>
<nav class="text-section inner-section">
<ol>
<li>
<a href="#basic-setup" title="Basic setup example">Basic setup example</a>
</li>
<li>
<a href="#image-uniform-sampler" title="Images uniform sampler names">Images uniform sampler names</a>
</li>
<li>
<a href="#performance-tips" title="Performance tips">Performance tips</a>
</li>
<li>
<a href="#useful-examples" title="Useful examples">Useful examples</a>
</li>
</ol>
</nav>
<div id="basic-setup" class="text-section inner-section">
<h2>Basic setup example</h2>
<p>
<a href="examples/basic-plane/index.html" title="See it live" target="_blank">See it live</a>
</p>
<h3>HTML</h3>
<p>
The HTML set up is pretty easy. Just create a div that will hold your canvas and a div that will hold your images.
</p>
<p>
<pre>
<code>
<body>
<!-- div that will hold our WebGL canvas -->
<div id="canvas"></div>
<!-- div used to create our plane -->
<div class="plane">
<!-- image that will be used as texture by our plane -->
<img src="path/to/my-image.jpg" />
</div>
</body>
</code>
</pre>
</p>
<h3>CSS</h3>
<p>
The CSS is also very easy. Make sure the div that will wrap the canvas fits the document, and apply any size you want to your plane div element.
</p>
<p>
<pre>
<code>
body {
/* make the body fits our viewport */
position: relative;
width: 100%;
height: 100vh;
margin: 0;
overflow: hidden;
}
#canvas {
/* make the canvas wrapper fits the document */
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.plane {
/* define the size of your plane */
width: 80%;
height: 80vh;
margin: 10vh auto;
}
.plane img {
/* hide the img element */
display: none;
}
</code>
</pre>
</p>
<h3>Javascript</h3>
<p>
There's a bit more work in the javascript part : we need to instanciate our WebGL context, create a plane with basic uniforms parameters and use it.
</p>
<p>
<pre>
<code>
window.onload = function() {
// get our canvas wrapper
var canvasContainer = document.getElementById("canvas");
// set up our WebGL context and append the canvas to our wrapper
var webGLCurtain = new Curtains("canvas");
// get our plane element
var planeElement = document.getElementsByClassName("plane")[0];
// set our initial parameters (basic uniforms)
var params = {
vertexShaderID: "plane-vs", // our vertex shader ID
fragmentShaderID: "plane-fs", // our framgent shader ID
uniforms: {
time: {
name: "uTime", // uniform name that will be passed to our shaders
type: "1f", // this means our uniform is a float
value: 0,
},
}
}
// create our plane mesh
var plane = webGLCurtain.addPlane(planeElement, params);
// use the onRender method of our plane fired at each requestAnimationFrame call
plane.onRender(function() {
plane.uniforms.time.value++; // update our time uniform value
});
}
</code>
</pre>
</p>
<h3>Shaders</h3>
<p>
Here are some basic vertex and fragment shaders. Just put it inside your body tag, right before you include the library.
</p>
<p>
<pre>
<code>
<!-- vertex shader -->
<script id="plane-vs" type="x-shader/x-vertex">
#ifdef GL_ES
precision mediump float;
#endif
// those are the mandatory attributes that the lib sets
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
// those are mandatory uniforms that the lib sets and that contain our model view and projection matrix
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
// if you want to pass your vertex and texture coords to the fragment shader
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
void main() {
vec3 vertexPosition = aVertexPosition;
gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);
// set the varyings
vTextureCoord = aTextureCoord;
vVertexPosition = vertexPosition;
}
</script>
<!-- fragment shader -->
<script id="plane-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
// get our varyings
varying vec3 vVertexPosition;
varying vec2 vTextureCoord;
// the uniform we declared inside our javascript
uniform float uTime;
// our texture sampler (default name, to use a different name please refer to the documentation)
uniform sampler2D uSampler0;
void main() {
vec2 textureCoord = vec2(vTextureCoord.x, vTextureCoord.y);
// displace our pixels along the X axis based on our time uniform
// textures coords are ranging from 0.0 to 1.0 on both axis
textureCoord.x += sin(textureCoord.y * 25.0) * cos(textureCoord.x * 25.0) * (cos(uTime / 50.0)) / 25.0;
gl_FragColor = texture2D(uSampler0, textureCoord);
}
</script>
</code>
</pre>
</p>
<p>
Et voilà !
</p>
</div>
<div id="images-uniforms-samplers" class="text-section inner-section">
<h2>Images uniform sampler names</h2>
<p>
Let's say you want to build a slideshow with 3 images and a displacement image to create a nice transition effect.<br />
By default, the textures uniforms sampler will be named upon their indexes inside your plane element. If you got something like that :
</p>
<p>
<pre>
<code>
<!-- div used to create our plane -->
<div class="plane">
<!-- images that will be used as textures by our plane -->
<img src="path/to/displacement.jpg" />
<img src="path/to/my-image-1.jpg" />
<img src="path/to/my-image-2.jpg" />
<img src="path/to/my-image-3.jpg" />
</div>
</code>
</pre>
</p>
<p>
Then, in your shaders, your textures samplers would have to be declared that way :
</p>
<p>
<pre>
<code>
uniform sampler2D uSampler0 // bound to displacement.jpg
uniform sampler2D uSampler1 // bound to my-image-1.jpg
uniform sampler2D uSampler2 // bound to my-image-2.jpg
uniform sampler2D uSampler3 // bound to my-image-3.jpg
</code>
</pre>
</p>
<p>
It is handy but you could also get easily confused.<br />
By using a data-sampler attribute on the <img /> tag, you could specify a custom uniform sampler name to use in your shader. With the example above, this would become :
</p>
<p>
<pre>
<code>
<!-- div used to create our plane -->
<div class="plane">
<!-- images that will be used as textures by our plane -->
<img src="path/to/displacement.jpg" data-sampler="uDisplacement" />
<img src="path/to/my-image-1.jpg" data-sampler="uSlide1" />
<img src="path/to/my-image-2.jpg" data-sampler="uSlide2" />
<img src="path/to/my-image-3.jpg" data-sampler="uLastSlide" />
</div>
</code>
</pre>
</p>
<p>
<pre>
<code>
uniform sampler2D uDisplacement // bound to displacement.jpg
uniform sampler2D uSlide1 // bound to my-image-1.jpg
uniform sampler2D uSlide2 // bound to my-image-2.jpg
uniform sampler2D uLastSlide // bound to my-image-3.jpg
</code>
</pre>
</div>
<div id="performance-tips" class="text-section inner-section">
<h2>Performance tips</h2>
<ul>
<li>
Be careful with each plane definition. A lot of vertices implies a big impact on performance. If you plan to use more than one plane, try to reduce the number of vertices.
</li>
<li>
Large images have a bigger impact on performance. Try to scale your images so they will fit your plane maximum size.
</li>
<li>
Try not to use too much uniforms as they are updated at every draw call.
</li>
<li>
If you use multiple planes with multiple textures, you should set the dimensions of your plane to fit the aspect ratio of your images in CSS (you could use the padding-bottom hack, see the <a href="examples/multiple-planes/index.html" title="Multiple planes" target="_blank">multiple planes</a> example HTML & CSS) and set the imageCover plane property to false when adding it.
</li>
</ul>
</div>
<div id="useful-examples" class="text-section inner-section">
<h2>Useful examples</h2>
<p>
Check their source code :
</p>
<p>
<a href="examples/vertex-coords-helper/index.html" title="Simple plane" target="_blank">Vertex coordinates helper</a><br />
<a href="examples/simple-plane/index.html" title="Simple plane" target="_blank">Simple plane</a><br />
<a href="examples/multiple-textures/index.html" title="Multiple textures" target="_blank">Multiple textures</a><br />
<a href="examples/multiple-planes/index.html" title="Multiple planes" target="_blank">Multiple planes</a><br />
<a href="examples/asynchronous-textures/index.html" title="Asynchronous textures loading" target="_blank">Asynchronous textures loading</a><br />
<a href="examples/ajax-navigation/index.html" title="Asynchronous textures loading" target="_blank">AJAX navigation</a>
</p>
</div>
</div>
</section>
</div>
</div>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-29368338-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-29368338-1');
</script>
</body>
</html>