Skip to content

Commit 5ae986b

Browse files
committed
Add next version of 3d mesh intro
1 parent 8aa2966 commit 5ae986b

2 files changed

Lines changed: 45 additions & 55 deletions

File tree

next/basic-3d-rendering/3d-meshes/a-simple-example.md

Lines changed: 34 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
A simple example <span class="bullet">🟠</span>
1+
A simple example <span class="bullet">🟢</span>
22
================
33

44
```{lit-setup}
@@ -10,7 +10,6 @@ A simple example <span class="bullet">🟠</span>
1010
```{lit-setup}
1111
:tangle-root: 050 - A simple example - Next
1212
:parent: 043 - More uniforms - Next
13-
:debug:
1413
```
1514

1615
````{tab} With webgpu.hpp
@@ -92,7 +91,7 @@ bool ResourceManager::loadGeometry(
9291
}
9392
```
9493

95-
```{lit} C++, Public ResourceManager members (hidden, replace)
94+
```{lit} C++, Declaration of ResourceManager::loadGeometry (hidden, replace, also for tangle root "Vanilla")
9695
/**
9796
* Load a file from `path` using our ad-hoc format and populate the `pointData`
9897
* and `indexData` vectors.
@@ -103,35 +102,6 @@ static bool loadGeometry(
103102
std::vector<uint16_t>& indexData,
104103
int dimensions // <-- new argument
105104
);
106-
/**
107-
* Create a shader module for a given WebGPU `device` from a WGSL shader source
108-
* loaded from file `path`.
109-
*/
110-
static wgpu::ShaderModule loadShaderModule(
111-
const std::filesystem::path& path,
112-
wgpu::Device device
113-
);
114-
```
115-
116-
```{lit} C++, Public ResourceManager members (hidden, replace, for tangle root "Vanilla")
117-
/**
118-
* Load a file from `path` using our ad-hoc format and populate the `pointData`
119-
* and `indexData` vectors.
120-
*/
121-
static bool loadGeometry(
122-
const std::filesystem::path& path,
123-
std::vector<float>& pointData,
124-
std::vector<uint16_t>& indexData,
125-
int dimensions // <-- new argument
126-
);
127-
/**
128-
* Create a shader module for a given WebGPU `device` from a WGSL shader source
129-
* loaded from file `path`.
130-
*/
131-
static WGPUShaderModule loadShaderModule(
132-
const std::filesystem::path& path,
133-
WGPUDevice device
134-
);
135105
```
136106

137107
```{lit} C++, Implementation of ResourceManager::loadGeometry (hidden, replace, also for tangle root "Vanilla")
@@ -313,11 +283,11 @@ Basic transform
313283

314284
**WIP**
315285

316-
*This is a gentle introduction to trigonometry. If you are familiar with the concept, you may jump ahead.*
286+
*This is a gentle introduction to **trigonometry**. If you are familiar with the concept, you may jump ahead.*
317287

318-
Seen from above, this pyramid boringly looks like an square. Could we **rotate** this? A very basic way to change the view angle is to swap axes:
288+
Seen from above, this pyramid boringly looks like an square. Could we **rotate** this? A very basic way to change the view angle is to **swap axes**:
319289

320-
```rust
290+
```{lit} rust, Set vertex out position (also for tangle root "Vanilla")
321291
var position = vec3f(
322292
in.position.x,
323293
in.position.z, // swap axis Y and Z
@@ -326,6 +296,22 @@ var position = vec3f(
326296
out.position = vec4f(position.x, position.y * ratio, 0.0, 1.0);
327297
```
328298

299+
````{admonition} Where to insert this?
300+
:class: foldable
301+
302+
We place this in the **vertex shader**:
303+
304+
```{lit} Vertex shader (replace, also for tangle root "Vanilla")
305+
fn vs_main(in: VertexInput) -> VertexOutput {
306+
var out: VertexOutput;
307+
let ratio = 640.0 / 480.0;
308+
{{Set vertex out position}}
309+
out.color = in.color;
310+
return out;
311+
}
312+
```
313+
````
314+
329315
```{figure} /images/pyramid-side.png
330316
:align: center
331317
:class: with-shadow
@@ -334,7 +320,7 @@ The pyramid seen from the side (still no perspective).
334320

335321
What about in-between rotations? The idea is to **mix axes**, adding a little bit of z in the y coordinates and a little bit of y in the z coordinates.
336322

337-
```rust
323+
```{lit} rust, Set vertex out position (replace, also for tangle root "Vanilla")
338324
var position = vec3f(
339325
in.position.x,
340326
in.position.y + 0.5 * in.position.z, // add a bit of Z in Y...
@@ -349,7 +335,7 @@ out.position = vec4f(position.x, position.y * ratio, 0.0, 1.0);
349335
The pyramid from a tilted view angle.
350336
```
351337

352-
Of course at some point we have to remove some of `in.position.y` from Y so that after a quarter of turn we reach `Y = 0.0 * in.position.y + 1.0 * in.position.z`, as in the example above. So more generally our transform writes like this, where `alpha` and `beta` depend on the rotation angle:
338+
Of course at some point we have to remove some of `in.position.y` from Y so that after a quarter of turn we reach `Y = 0.0 * in.position.y + 1.0 * in.position.z`, as in the example above. So **more generally** our transform writes like this, where `alpha` and `beta` depend on the **rotation angle**:
353339

354340
```rust
355341
let angle = uMyUniforms.time; // you can multiply it go rotate faster
@@ -364,12 +350,12 @@ out.position = vec4f(position.x, position.y * ratio, 0.0, 1.0);
364350
```
365351

366352
```{note}
367-
If you payed close attention to the snippet above, you should have noticed **a minus sign** `-` before the second `beta`. It is not visible on our pyramid because it is symmetrical but swapping axes also flips the object. To **counter-balance** this, we can change the sign of one of the dimensions. Hence the Z coordinate after a quarter of turn must be `-in.position.y` instead of `in.position.y`.
353+
If you pay close attention to the snippet above, you can notice **a minus sign** `-` before the second `beta`. It is not visible on our pyramid because it is symmetrical but swapping axes also flips the object. To **counter-balance** this, we can change the sign of one of the dimensions. Hence the Z coordinate after a quarter of turn must be `-in.position.y` instead of `in.position.y`.
368354
```
369355

370-
It turns out that these weights `alpha` and `beta` are not easy to express in terms of basic operations with respect to the angle. So mathematicians came up with a dedicated name for them: **cosine** and **sine**! And the good news is that these are **built-in operations** in WGSL:
356+
It turns out that these **weights** `alpha` and `beta` are not easy to express in terms of basic operations **with respect to the angle**. So mathematicians came up with a dedicated name for them: **cosine** and **sine**! And the good news is that these are **built-in operations** in WGSL:
371357

372-
```rust
358+
```{lit} rust, Set vertex out position (replace, also for tangle root "Vanilla")
373359
let angle = uMyUniforms.time; // you can multiply it go rotate faster
374360
let alpha = cos(angle);
375361
let beta = sin(angle);
@@ -383,27 +369,23 @@ out.position = vec4f(position.x, position.y * ratio, 0.0, 1.0);
383369

384370
<figure class="align-center">
385371
<video autoplay loop muted inline nocontrols style="width:100%;height:auto;max-width:642px">
386-
<source src="../../_static/pyramid-ryz.mp4" type="video/mp4">
372+
<source src="../../../_static/pyramid-ryz.mp4" type="video/mp4">
387373
</video>
388374
<figcaption>
389375
<p><span class="caption-text">Rotation in the YZ plane</span></p>
390376
</figcaption>
391377
</figure>
392378

393-
```{image} /images/trigo-light.svg
379+
```{themed-figure} /images/trigo-{theme}.svg
394380
:align: center
395-
:class: only-light
396-
```
397381

398-
```{image} /images/trigo-dark.svg
399-
:align: center
400-
:class: only-dark
382+
A side-view of the pyramid. The (signed) length of the green vertical and horizontal lines give the value of `alpha` and `beta` respectively.
401383
```
402384

403385
Congratulations, you have learned most of what there is to know about **trigonometry** for computer graphics!
404386

405387
```{hint}
406-
**If you cannot remember** which one is the $cos$ and which one is the $sin$ among `alpha` and `beta` (don't worry! It happens to everyone), **just take an example** of very simple rotation: `angle = 0`. In such a case, we need `alpha = 1` and `beta = 0`. If you look at a plot of the $sin$ and $cos$ functions you'll quickly see that $cos(0) = 1$ and $sin(0) = 0$
388+
**If you cannot remember** which one is the $cos$ and which one is the $sin$ among `alpha` and `beta` (don't worry! It happens to everyone), **just take an example** with very simple rotation: `angle = 0`. In such a case, we need `alpha = 1` and `beta = 0`. If you look at a plot of the $sin$ and $cos$ functions you'll quickly see that $cos(0) = 1$ and $sin(0) = 0$
407389
```
408390

409391
```{important}
@@ -413,7 +395,7 @@ $$
413395
\frac{r \text{ radians}}{d \text{ degrees}} = \frac{2\pi \text{ radians}}{360 \text{ degrees}}
414396
$$
415397
416-
So to convert an angle $d$ in degrees into its equivalent $r$ in radians, we simply do:
398+
So to convert an angle $d$ in **degrees** into its equivalent $r$ in **radians**, we simply do:
417399
418400
$$
419401
r = d \times \frac{\pi}{180}
@@ -425,9 +407,9 @@ Conclusion
425407

426408
We have a beginning of something. With this rotation, it starts looking like 3D, but there remains some important points to be concerned about:
427409

428-
- **Depth fighting** As highlighted in the image below, the triangles do not overlap in the correct order.
429-
- **Transform** We have the basics, but it is a bit manual, and there is still **no perspective**!
430-
- **Shading** The trick of setting the tip of the pyramid to a darker color was good for starting, but we can do much better.
410+
- **Depth fighting:** As highlighted in the image below, the triangles do not overlap in the correct order.
411+
- **Transform:** We have the basics, but it is a bit manual, and there is still **no perspective**!
412+
- **Shading:** The trick of setting the tip of the pyramid to a darker color was good for a start, but we can do much better.
431413

432414
These points are, in this order, the topic of the next 4 chapters (transforms are split in 2 chapters).
433415

next/basic-3d-rendering/input-geometry/loading-from-file.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,11 @@ We do not have any `private` member for now, but we will later on.
354354
355355
We can declare in `public` members our `loadGeometry` function:
356356
357-
```{lit} C++, Public ResourceManager members (also for tangle root "Vanilla")
357+
```{lit} C++, Public ResourceManager members (hidden, also for tangle root "Vanilla")
358+
{{Declaration of ResourceManager::loadGeometry}}
359+
```
360+
361+
```{lit} C++, Declaration of ResourceManager::loadGeometry (also for tangle root "Vanilla")
358362
/**
359363
* Load a file from `path` using our ad-hoc format and populate the `pointData`
360364
* and `indexData` vectors.
@@ -516,8 +520,12 @@ Now that we have a basic resource management mechanism, I strongly suggest we al
516520
517521
Let us first declare it in `ResourceManager.h`:
518522
523+
```{lit} C++, Public ResourceManager members (append, also for tangle root "Vanilla")
524+
{{Declaration of ResourceManager::loadShaderModule}}
525+
```
526+
519527
````{tab} With webgpu.hpp
520-
```{lit} C++, Public ResourceManager members (append)
528+
```{lit} C++, Declaration of ResourceManager::loadShaderModule
521529
/**
522530
* Create a shader module for a given WebGPU `device` from a WGSL shader source
523531
* loaded from file `path`.
@@ -530,7 +538,7 @@ static wgpu::ShaderModule loadShaderModule(
530538
````
531539

532540
````{tab} Vanilla webgpu.h
533-
```{lit} C++, Public ResourceManager members (append, for tangle root "Vanilla")
541+
```{lit} C++, Declaration of ResourceManager::loadShaderModule (for tangle root "Vanilla")
534542
/**
535543
* Create a shader module for a given WebGPU `device` from a WGSL shader source
536544
* loaded from file `path`.

0 commit comments

Comments
 (0)