Skip to content

Commit fa570c2

Browse files
committed
Finished chapter 7
1 parent 8ce0806 commit fa570c2

File tree

10 files changed

+503
-242
lines changed

10 files changed

+503
-242
lines changed

07-points.rst

Lines changed: 156 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,65 @@ above , we'll need to take care of pretty much everything.
1919
Dots, discs, circles
2020
-------------------------------------------------------------------------------
2121

22+
Raw points
23+
++++++++++
24+
25+
26+
.. figure:: images/chapter-07/points.png
27+
:figwidth: 30%
28+
:figclass: right
29+
30+
Figure
31+
32+
"Point" as drawn by OpenGL
33+
(see `points.py <code/chapter-07/points.py>`_).
34+
2235
The most straightforward way to display points is to use the `gl.GL_POINTS`
23-
primitive that display a quad that is always facing the camera
24-
(i.e. billboard). This is very convenient because a mathematical point has no
25-
dimension, even though we'll use this primite to draw discs and circles as
26-
well. The size of the quad must be specified within the vertex shader using the
27-
`gl_PointSize` variable (note that the size is expressed in pixels). As it has
28-
been explained in the previous chapter, the size of the quad must be slighlty
29-
larger than the actual diameter of the point because we need some extra space
30-
for the antialias area. Considering a point with a radius `r`, the size of the
31-
quad is thus `2+ceil(2*r)` if we consider using 1 pixel for the antalias
32-
area. Finally, considering a point centered at `center` with radius `radius`,
33-
our vertex shader reads:
36+
primitive that displays a quad that is always facing the camera
37+
(i.e. billboard). This is very convenient because a mathematical point has no
38+
dimension, even though we'll use this primitive to draw discs and circles in
39+
the next section. The size of the quad must be specified within the vertex
40+
shader using the `gl_PointSize` variable (note that the size is expressed in
41+
pixels). As shown on the figure, the result is quite ugly.
42+
43+
.. code:: python
44+
45+
import numpy as np
46+
from glumpy import app, gloo, gl
47+
48+
vertex = """
49+
attribute vec2 position;
50+
void main() {
51+
gl_PointSize = 5.0;
52+
gl_Position = vec4(position, 0.0, 1.0);
53+
} """
54+
55+
fragment = """
56+
void main() {
57+
gl_FragColor = vec4(vec3(0.0), 1.0);
58+
} """
59+
60+
window = app.Window(512, 512, color=(1,1,1,1))
61+
points = gloo.Program(vertex, fragment, count=1000)
62+
points["position"] = np.random.uniform(-1,1,(len(points),2))
63+
64+
@window.event
65+
def on_draw(dt):
66+
window.clear()
67+
points.draw(gl.GL_POINTS)
68+
69+
app.run()
70+
71+
72+
Antialiased points
73+
++++++++++++++++++
74+
75+
For drawing antialiased point, the size of the quad must be slighlty larger
76+
than the actual diameter of the point because we need some extra space for the
77+
antialias area. Considering a point with a radius `r`, the size of the quad is
78+
thus `2+ceil(2*r)` if we consider using 1 pixel for the antalias area. Finally,
79+
considering a point centered at `center` with radius `radius`, our vertex
80+
shader reads (see also previous chapter on signed distance field):
3481

3582
.. code:: glsl
3683
@@ -147,10 +194,84 @@ we simply have to get the absolute distance instead of the signed distance.
147194
}
148195
149196
197+
Ellipses
198+
-------------------------------------------------------------------------------
199+
200+
201+
.. figure:: movies/chapter-07/ellipses.mp4
202+
:loop:
203+
:autoplay:
204+
:controls:
205+
:figwidth: 30%
206+
:figclass: right
207+
208+
Figure
209+
210+
Perfectly antialiases ellipse made of two triangles
211+
(`ellipses.py <code/chapter-07/ellipses.py>`_)
212+
213+
214+
Rendering ellipses is harder than it seems because, as we've explained in a
215+
previous chapter, computing the distance from an arbitrary point to an ellipse
216+
is surprinsingly difficult if you compare it to the distance to a circle. The
217+
second difficulty for us is the fact that an ellipse can be very "flat" and if
218+
we use the gl.GL_POINTS primitive, a lot of useless fragment will be
219+
generated. This is the reason why we need to compute the bounding box
220+
(including thickness and antialias area) and use two triangles to actually
221+
display the ellipse. Last difficulty is that we cannot take advantage of the
222+
`gl_FragCoord` but we can now take advantage of the four vertices to have local
223+
coordinate interpolation in the fragment shader.
224+
225+
.. code:: glsl
226+
227+
uniform vec2 resolution;
228+
uniform float theta;
229+
attribute vec2 position;
230+
attribute float angle;
231+
varying vec2 v_position;
232+
void main() {
233+
v_position = position;
234+
vec2 p = position;
235+
p = vec2(p.x*cos(angle+theta) - p.y*sin(angle+theta),
236+
p.y*cos(angle+theta) + p.x*sin(angle+theta));
237+
p = p + resolution/2.0;
238+
gl_Position = vec4(2.0*p/resolution-1.0, 0.0, 1.0);
239+
}
240+
241+
Note that in the vertex shader above, we pass the non-rotated coordinates to
242+
the fragment shader. It makes things much simpler in the fragment shader that
243+
reads:
244+
245+
.. code:: glsl
246+
247+
float SDF_fake_ellipse(vec2 p, vec2 size) {
248+
float a = 1.0;
249+
float b = size.x/size.y;
250+
float r = 0.5*max(size.x,size.y);
251+
float f = length(p*vec2(a,b));
252+
return f*(f-r)/length(p*vec2(a*a,b*b));
253+
}
254+
255+
uniform vec2 size;
256+
varying vec2 v_position;
257+
void main() {
258+
float d = SDF_fake_ellipse(v_position, size) + 1.0;
259+
float alpha;
260+
if (abs(d) < 1.0) alpha = exp(-d*d)/ 4.0;
261+
else if (d < 0.0) alpha = 1.0/16.0;
262+
else alpha = exp(-d*d)/16.0;
263+
gl_FragColor = vec4(vec3(0.0), alpha);
264+
}
265+
266+
267+
150268
151269
Spheres
152270
-------------------------------------------------------------------------------
153271

272+
Flat sphere
273+
+++++++++++
274+
154275
.. figure:: images/chapter-07/sphere.png
155276
:figwidth: 30%
156277
:figclass: right
@@ -248,6 +369,9 @@ below, this is quite easy and the result is flawless.
248369
249370
----
250371

372+
True sphere
373+
+++++++++++
374+
251375
.. figure:: images/chapter-07/spheres-no-depth.png
252376
:figwidth: 30%
253377
:figclass: right
@@ -256,8 +380,8 @@ below, this is quite easy and the result is flawless.
256380

257381
A bunch of fake spheres.
258382

259-
We can now use this technique to display several "spheres" having different
260-
sizes and positions as shown on the figure on the right. This can be used to
383+
We can use this technique to display several "spheres" having different sizes
384+
and positions as shown on the figure on the right. This can be used to
261385
represent molecules for examples. Howewer, we have a problem with sphere
262386
intersecting each other. If you look closely the figure, you might have notices
263387
that no sphere intersect any sphere. This is due to the depth testing of the
@@ -295,6 +419,8 @@ the `gl_FragDepth` variable (that must be between 0 and 1):
295419
float specular = pow(diffuse, 24.0);
296420
gl_FragColor = vec4(max(diffuse*color, specular*vec3(1.0)), 1.0);
297421
}
422+
423+
You can see on the figures that the spheres now intersect each other correctly.
298424

299425

300426
Exercises
@@ -318,6 +444,21 @@ disc...
318444
Solution: `spiral.py <code/chapter-07/spiral.py>`_
319445

320446

447+
----
448+
449+
.. figure:: movies/chapter-07/triangles.mp4
450+
:loop:
451+
:autoplay:
452+
:controls:
453+
:figwidth: 30%
454+
:figclass: right
455+
456+
Antialiased triangles
457+
458+
Try to adapt the code from the ellipses section to remake the animation on the
459+
right. Be careful with the computation of the bouding box.
460+
461+
Solution: `triangles.py <code/chapter-07/triangles.py>`_
321462

322463
----
323464

@@ -330,33 +471,9 @@ Solution: `spiral.py <code/chapter-07/spiral.py>`_
330471
A voronoi diagram computed on the GPU.
331472

332473

333-
We've seen when rendering sphere that the individual depth of eahc fragment can
474+
We've seen when rendering sphere that the individual depth of each fragment can
334475
be controled withing the fragment shader and we computed this depth by taking
335476
the distance to the center of each disc/sphere. The goal of this exercise is
336-
thus to adapt this method to render a Voronoi diagram as shonw on the right.
477+
thus to adapt this method to render a Voronoi diagram as shown on the right.
337478

338479
Solution: `voronoi.py <code/chapter-07/voronoi.py>`_
339-
340-
..
341-
.. figure:: movies/chapter-07/triangles.mp4
342-
:loop:
343-
:autoplay:
344-
:controls:
345-
:figwidth: 30%
346-
:figclass: right
347-
348-
Figure
349-
350-
351-
352-
.. figure:: movies/chapter-07/ellipses.mp4
353-
:loop:
354-
:autoplay:
355-
:controls:
356-
:figwidth: 30%
357-
:figclass: right
358-
359-
Figure
360-
361-
362-

08-markers.rst

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,11 @@ __ https://www.shadertoy.com/view/4llyWn
159159
Some example of markers constructed using CSG.
160160

161161

162-
Arrows
162+
Markers
163163
-------------------------------------------------------------------------------
164164

165+
Arrows
166+
-------------------------------------------------------------------------------
165167

166-
167-
168-
169-
Boundings boxes
168+
Texture based
170169
-------------------------------------------------------------------------------

17-bibliography.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Articles
7676
.. _article-1: http://jcgt.org/published/0002/01/04/
7777

7878
.. |article-2|
79-
replace:: Shader-based Antialiased Dashed Stroke Poylines
79+
replace:: Shader-based Antialiased Dashed Stroke Polylines
8080
.. _article-2: http://jcgt.org/published/0002/02/08/
8181

8282
.. |article-3|

book.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ a:active {
477477
}
478478
.chapter-08 .topic-title {
479479
background: url("images/chapter-08/toc.png") no-repeat center;
480-
background-size: 120%;
480+
background-size: 100%;
481481
}
482482
.chapter-09 .topic-title {
483483
background: url("images/chapter-09/toc.png") no-repeat center;

0 commit comments

Comments
 (0)