mirror of
https://github.com/patriciogonzalezvivo/thebookofshaders
synced 2024-11-03 23:15:23 +00:00
Merge pull request #79 from nicoptere/master
appendix: coming from JS +types +vectors
This commit is contained in:
commit
d8b2ff51d5
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,4 +9,5 @@ log/*
|
||||
.idea/
|
||||
idea/
|
||||
/07/test.html
|
||||
/appendix/04/index.html
|
||||
/09/test.html
|
||||
|
78
appendix/04/01/README.md
Normal file
78
appendix/04/01/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
![first search result for 'strong type' on Google Image, on the 2016/05/20](strong_type.jpg)
|
||||
### strong types
|
||||
|
||||
When you come from JS or any untyped language, **typing** your variables is an alien concept, making **typing** the hardest step to take towards GLSL.
|
||||
**Typing**, as the name suggests, means that you'll give a **type** to your variables (and functions of course).
|
||||
This basically means that the word **`var`** doesn't exist anymore.
|
||||
The GLSL thought-police erased it from the common tongue and you're not able to speak it because, well... it doesn't exist.
|
||||
|
||||
Instead of using the magic word **`var`**, you'll have to _explicitly specify the type of each variable_ you use, then the compiler will only see objects and primitives it knows how to handle efficiently.
|
||||
The downside when you can't use the **`var`** keyword and must _specify everything_, is that you'll have to know the type of all the variables and know them well.
|
||||
Rest assured, there are few and they're fairly simple (GLSL is not a Java framework).
|
||||
|
||||
Might sound scary but all in all, it's not very different from what you're doing when you code JavaScript ; if a variable is a `boolean`, you'll expect it to store `true` or `false` and nothing else.
|
||||
If a variable is called `var uid = XXX;`, chances are that you'll store an integer value in there and a `var y = YYY;` _might_ be a reference to a floating point value.
|
||||
Even better, with **strong types**, you won't waste time wondering if `X == Y` (or was it `typeof X == typeof Y` ? .. or `typeof X !== null && Y...` ... anyway) ; you'll just *know* it and if you don't, the compiler will.
|
||||
|
||||
Here are the **scalar types** (a **scalar** describes a quantity) you can use in GLSL: `bool` (Boolean), `int`(Integer), `float`(floating point Number).
|
||||
There are other types but let's take it easy, the following snippet shows how to declare **`vars`** (yes, I spoke the forbidden word) in GLSL:
|
||||
```glsl
|
||||
//a Boolean value:
|
||||
JS: var b = true; GLSL: bool b = true;
|
||||
|
||||
//an Integer value
|
||||
JS: var i = 1; GLSL: int i = 1;
|
||||
|
||||
//a Float value (a Number)
|
||||
JS: var f = 3.14159; GLSL: float f = 3.14159;
|
||||
```
|
||||
Not that hard right? as mentioned above, it even makes things easier when it comes to coding as you don't waste your time checking the type of a given variable.
|
||||
When in doubt, remember that you're doing this for your program to run immensely faster than in JS.
|
||||
|
||||
#### void
|
||||
There is a `void` type that roughly cooresponds to `null`, it is used as the return type of a method that doesn't return anything.
|
||||
you can't assign it to a variable.
|
||||
|
||||
#### boolean
|
||||
As you know, Booleans are mostly used in conditional tests ; `if( myBoolean == true ){}else{}`.
|
||||
If the conditional branching is a valid option on the CPU, [the parallel nature](http://thebookofshaders/01/) of GLSL makes it less true.
|
||||
Using conditionals is even discouraged most of the time, the book explains a couple of alternative techniques to solve this.
|
||||
|
||||
#### type casting
|
||||
As [Aragorn](https://en.wikipedia.org/wiki/Aragorn) put it, "One does not simply combine Typed primitives". Unlike JavaScript, GLSL will not allow you to perform operations between variables of different types.
|
||||
|
||||
This for instance:
|
||||
```glsl
|
||||
int i = 2;
|
||||
float f = 3.14159;
|
||||
|
||||
//trying to multiply an integer by a float value
|
||||
float r = i * f;
|
||||
```
|
||||
will not play nice because you're trying to crossbreed a **_cat_** and a **_giraffe_**.
|
||||
The solution to this is to use **type casting** ; it will _make the compiler believe_ that *`i`* is of type `float` without actually changing the type of *`i`*.
|
||||
```glsl
|
||||
//casting the type of the integer variable 'i' into float
|
||||
float r = float( i ) * f;
|
||||
```
|
||||
and this will work as expected ( `r` will store the result of `i` x `f`).
|
||||
|
||||
It is possible to **cast** any of the above types into any other type, note that casting a `float` to `int` will behave like a `Math.floor()` as it will remove the values behind the floating point.
|
||||
Casting a `float` or a `int` to `bool` will return `true` if the variable is not equal to zero.
|
||||
|
||||
#### constructor
|
||||
The variable **types** are also their own **class constructor** ; in fact a `float` variable can be thought of as an _`instance`_ of a _`Float`_ class.
|
||||
|
||||
This declarations are equally valid:
|
||||
|
||||
```glsl
|
||||
int i = 1;
|
||||
int i = int( 1 );
|
||||
int i = int( 1.9995 );
|
||||
int i = int( true );
|
||||
```
|
||||
This may not sound like much for `scalar` types, it's not very different from **casting**, but it will make sense when adressing the *overload* section.
|
||||
|
||||
Ok, so these three are the `primitive types`, things you can't live without but of course, GLSL has more to offer.
|
||||
|
||||
|
28
appendix/04/01/index.php
Normal file
28
appendix/04/01/index.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$path = "../../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
echo '
|
||||
<div class="header"><p><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div>
|
||||
<hr>
|
||||
<div id="content">
|
||||
';
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
|
||||
include($path."/footer.php");
|
||||
?>
|
BIN
appendix/04/01/strong_type.jpg
Normal file
BIN
appendix/04/01/strong_type.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
167
appendix/04/02/README.md
Normal file
167
appendix/04/02/README.md
Normal file
@ -0,0 +1,167 @@
|
||||
![first search result for 'vector villain' on Google Image, on the 2016/05/20](vector.jpg)
|
||||
### Vectors
|
||||
|
||||
In Javascript like in GLSL, you'll need more sophisticated ways of handling data, that's where **`vectors`** come in handy.
|
||||
I suppose that you've already coded a `Point` class in JavaScript to hold together a `x` and a `y` value, the code for this would go like:
|
||||
```glsl
|
||||
// 'class' definition:
|
||||
var Point = function( x, y ){
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
}
|
||||
|
||||
//and you would instantiate it like:
|
||||
var p = new Point( 100,100 );
|
||||
```
|
||||
|
||||
As we've just seen, this is SO wrong at SO many levels! That **`var`** keyword for one, then the horendous **`this`**, then again **untyped** `x` and `y` values...
|
||||
No, this is not going to work in shaderland.
|
||||
|
||||
Instead, GLSL exposes built-in data structures to hold data together, namely:
|
||||
|
||||
* `bvec2`: a 2D Boolean vector, `bvec3`: a 3D Boolean vector, `bvec4`: a 4D Boolean vector
|
||||
* `ivec2`: a 2D Integer vector, `ivec3`: a 3D Integer vector, `ivec4`: a 4D Integer vector
|
||||
* `vec2`: a 2D Float vector, `vec3`: a 3D Float vector, `ivec4`: a 4D Float vector
|
||||
|
||||
You immediately noticed that there's a type of **vector** for each primitive type, clever bunny.
|
||||
From what we just saw, you can deduce that a `bvec2` will hold two values of type `bool` and a `vec4` will hold four `float` values.
|
||||
|
||||
Another thing introduced by vectors is a number of **dimensions**, it doesn't mean that a 2D vector is used when you render 2D graphics and a 3D vector when you do 3D.
|
||||
What would a 4D vector represent then? (actually a 4 diemnsional space is called a tesseract or hypercube)
|
||||
|
||||
No, the **dimensions** represent the number and the type of **components** or **variables** stored into the **vector**:
|
||||
```glsl
|
||||
// let's create a 2D Boolean vector
|
||||
bvec2 b2 = bvec2 ( true, false );
|
||||
|
||||
// let's create a 3D Integer vector
|
||||
ivec3 i3 = ivec3( 0,0,1 );
|
||||
|
||||
// let's create a 4D Float vector
|
||||
vec4 v4 = vec4( 0.0, 1.0, 2.0, 1. );
|
||||
```
|
||||
`b2` stores two different boolean values, `i3` stores 3 different integer values and `v4` stores 4 different float values.
|
||||
|
||||
but how to retrieve those values?
|
||||
in the case of `scalars`, the answer is obvious ; with `float f = 1.2;`, the variable `f` holds the value `1.2`.
|
||||
With **vectors** it's a bit different and quite beautiful.
|
||||
|
||||
#### accessors
|
||||
There are different ways of accessing the values
|
||||
```glsl
|
||||
// let's create a 4D Float vector
|
||||
vec4 v4 = vec4( 0.0, 1.0, 2.0, 3.0 );
|
||||
```
|
||||
to retrieve the 4 values, you can do the following:
|
||||
```glsl
|
||||
float x = v4.x; // x = 0.0
|
||||
float y = v4.y; // y = 1.0
|
||||
float z = v4.z; // z = 2.0
|
||||
float w = v4.w; // w = 3.0
|
||||
```
|
||||
nice and easy ; but the following are equally valid ways of accessing your data:
|
||||
```glsl
|
||||
float x = v4.x = v4.r = v4.s = v4[0]; // x = 0.0
|
||||
float y = v4.y = v4.g = v4.t = v4[1]; // y = 1.0
|
||||
float z = v4.z = v4.b = v4.p = v4[2]; // z = 2.0
|
||||
float w = v4.w = v4.a = v4.q = v4[3]; // w = 3.0
|
||||
```
|
||||
|
||||
And the clever bunny you are already noticed three things:
|
||||
* `X`, `Y`, `Z` & `W` are used in 3D programs to represent 3D vectors
|
||||
* `R`, `G`, `B` & `A` are used to encode colors and alpha
|
||||
* `[0]`, `[1]`, `[2]` & `[3]` mean that we have a random access array of values
|
||||
|
||||
So depending on wether you're manipulating 2D or 3D coordinates, a color with or without an alpha value or simply some random variables, you can pick the most suited **vector** type and size.
|
||||
Typically 2D coordinates and vectors (in the geometric sense) are stored as a `vec2`, `vec3` or `vec4`, colors as `vec3` or `vec4` if you need opacity but htere is no restriction on how to use the vectors.
|
||||
For instance, if you want to store only one boolean value in a `bvce4`, it's possible, it's just a waste of memory.
|
||||
|
||||
**note**: in a shader, color values (`R`, `G`, `B` & `A`) are normalised, they range from 0 to 1 and not from 0 to 0xFF, so you'd rather use a Float `vec4` than an Integer `ivec4` to store them.
|
||||
|
||||
Nice already, but there's more!
|
||||
|
||||
#### swizzle
|
||||
|
||||
It is possible to return more than one value at once ; say you need only the `X` and `Y` values of a `vec4`, in JavaScript, you'd have to write something like:
|
||||
```glsl
|
||||
var needles = [0, 1]; // location of 'x' & 'y' in our data structure
|
||||
var a = [ 0,1,2,3 ]; // our 'vec4' data structure
|
||||
var b = a.filter( function( val, i, array ) {
|
||||
return needles.indexOf( array.indexOf( val ) ) != -1;
|
||||
});
|
||||
// b = [ 0, 1 ]
|
||||
|
||||
//or more literally:
|
||||
var needles = [0, 1];
|
||||
var a = [ 0,1,2,3 ]; // our 'vec4' data structure
|
||||
var b = [ a[ needles[ 0 ] ], a[ needles[ 1 ] ] ]; // b = [ 0, 1 ]
|
||||
```
|
||||
Ugly. In GLSL you can retrieve them like so:
|
||||
```glsl
|
||||
// create a 4D Float vector
|
||||
vec4 v4 = vec4( 0.0, 1.0, 2.0, 3.0 );
|
||||
|
||||
//and retrieve only the X & Y components
|
||||
vec2 xy = v4.xy; // xy = vec2( 0.0, 1.0 );
|
||||
```
|
||||
What just happened?! when you **concatenate accessors**, GLSL gracefully returns a subset of the values you asked for, in the best suited **vector** format.
|
||||
Indeed, the vector is a **random access** data structure, like an array in JavaScript if you want.
|
||||
So not only can you retrieve a subset of your data, but you can also specify the **order** in which you need it, this will invert the values of the components of a vector:
|
||||
```glsl
|
||||
// create a 4D Float vector: R,G,B,A
|
||||
vec4 color = vec4( 0.2, 0.8, 0.0, 1.0 );
|
||||
|
||||
//and retrieve the color components in the A,B,G,R order
|
||||
vec4 backwards = v4.abgr; // backawrds = vec4( 1.0, 0.0, 0.8, 0.2 );
|
||||
```
|
||||
And of course, you can ask the same component multiple times:
|
||||
```glsl
|
||||
// create a 4D Float vector: R,G,B,A
|
||||
vec4 color = vec4( 0.2, 0.8, 0.0, 1.0 );
|
||||
|
||||
//and retrieve a GAG vec3 based on the G & A channels of the color
|
||||
vec3 GAG = v4.gag; // GAG = vec4( 0.8, 1.0, 0.8 );
|
||||
```
|
||||
|
||||
This is extremely handy to combine parts of vectors together, extract only the rgb channels of a RGBA color etc.
|
||||
|
||||
|
||||
#### overload everything!
|
||||
|
||||
In the [types section](../01/), I mentioned something about the **constructor** and that's yet again a great feature of GLSL ; **overloading**.
|
||||
For those who don't know, **overloading** an operator or a function roughly means: _'changing the behaviour of said operator or function depending on the operands/arguments'_.
|
||||
Overloading is not allowed in JavaScript, so this may be a bit strange at first but I'm sure that once you get used to it, you'll wonder why it is not implemented in JS (short answer, *typing*).
|
||||
|
||||
the most basic example of operator overloading goes as follow:
|
||||
|
||||
```glsl
|
||||
vec2 a = vec2( 1.0, 1.0 );
|
||||
vec2 b = vec2( 1.0, 1.0 );
|
||||
//overloaded addition
|
||||
vec2 c = a + b; // c = vec2( 2.0, 2.0 );
|
||||
```
|
||||
WHAT? so you can add things that are not numbers?!
|
||||
|
||||
Yes, precisely. Of course this applies to all operators (`+`, `-`, `*` & `/`) but that's only the beginning.
|
||||
Consider the following snippet:
|
||||
```glsl
|
||||
vec2 a = vec2( 0.0, 0.0 );
|
||||
vec2 b = vec2( 1.0, 1.0 );
|
||||
//overloaded constructor
|
||||
vec4 c = vec4( a , b ); // c = vec4( 0.0, 0.0, 1.0, 1.0 );
|
||||
```
|
||||
We built a `vec4` out of two `vec2`, by doing so, the new `vec4` used the `a.x` and `a.y` as the `X`, `Y` components of `c`.
|
||||
Then it took `b.x` and `b.y` and used them as the `Z` and `W` components of `c`.
|
||||
|
||||
This is what happens when a **function** is overloaded to accept different arguments, in this case, the `vec4` **constructor**.
|
||||
It means that many **vesrions** of the same method with a different signature can coexist in the same program, for instance the following declarations are all valid:
|
||||
```glsl
|
||||
vec4 a = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
vec4 a = vec4(1.0);// x, y, z, w all equel 1.0
|
||||
vec4 a = vec4( v2, float, v4 );// vec4( v2.x, v2.y, float, v4.x );
|
||||
vec4 a = vec4( v3, float );// vec4( v3.x, v3.y, v3.z, float );
|
||||
etc.
|
||||
```
|
||||
the only thing you should make sure of is to provide enough arguments to feed your **vector**.
|
||||
|
||||
Last thing, you are allowed to overload the built-in functions in your program so they can take arguments they were not designed for (this shouldn't happen too often though).
|
28
appendix/04/02/index.php
Normal file
28
appendix/04/02/index.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$path = "../../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
echo '
|
||||
<div class="header"><p><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div>
|
||||
<hr>
|
||||
<div id="content">
|
||||
';
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
|
||||
include($path."/footer.php");
|
||||
?>
|
BIN
appendix/04/02/vector.jpg
Normal file
BIN
appendix/04/02/vector.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
8
appendix/04/03/README.md
Normal file
8
appendix/04/03/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
### matrix
|
||||
|
||||
Vectors are fun, they're the meat of your shader and soon enough you'll to have transform them.
|
||||
|
||||
[to be continued]
|
||||
|
||||
|
28
appendix/04/03/index.php
Normal file
28
appendix/04/03/index.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$path = "../../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
echo '
|
||||
<div class="header"><p><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div>
|
||||
<hr>
|
||||
<div id="content">
|
||||
';
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
|
||||
include($path."/footer.php");
|
||||
?>
|
13
appendix/04/04/README.md
Normal file
13
appendix/04/04/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
### textures and space
|
||||
|
||||
Let's start with a gentle one ; the Y axis is flipped.
|
||||
Y points 'up', to the sky, while in the DOM & Canvas worlds, we're used to having the Y pointing 'down'.
|
||||
This makes sense in the context of a DOM as it follows the way a web page would unroll(the navbar at the top, content at the bottom),
|
||||
but if you were to tell where is the 'up' direction of a piece of paper, I'm sure you'd point 'up''.
|
||||
|
||||
This implies that the point 0,0, which is located in the top left corner of a canvas element will be located in the bottom right corner of a WebGL context.
|
||||
The textures coordinates also will follow this rule which might be counter-intuitive but soon you'll get used to it.
|
||||
|
||||
[to be continued]
|
28
appendix/04/04/index.php
Normal file
28
appendix/04/04/index.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$path = "../../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
echo '
|
||||
<div class="header"><p><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div>
|
||||
<hr>
|
||||
<div id="content">
|
||||
';
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
|
||||
include($path."/footer.php");
|
||||
?>
|
5
appendix/04/05/README.md
Normal file
5
appendix/04/05/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
### uniforms & unicorns
|
||||
|
||||
[to be started]
|
28
appendix/04/05/index.php
Normal file
28
appendix/04/05/index.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
$path = "../../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
echo '
|
||||
<div class="header"><p><a href="https://thebookofshaders.com/">The Book of Shaders</a> by <a href="http://patriciogonzalezvivo.com">Patricio Gonzalez Vivo</a></p></div>
|
||||
<hr>
|
||||
<div id="content">
|
||||
';
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
|
||||
include($path."/footer.php");
|
||||
?>
|
@ -1,2 +1,49 @@
|
||||
## An introduction for those coming from JS
|
||||
by ....
|
||||
by Nicolas Barradeau
|
||||
|
||||
|
||||
If you're a JavaScript developer, chances are you'll be a bit puzzled when reading the book.
|
||||
Indeed, there are many differences between manipulating high-level JS and getting down and dirty with shaders.
|
||||
Yet, as opposed to the underlying assembly language, GLSL is human readable and I'm sure that, once you acknowledge its specificities, you'll quickly be up and running.
|
||||
|
||||
I assume you have a prior (be it shallow) knowledge of JavaScript of course, but also of the Canvas API.
|
||||
If not, don't worry, you'll still be able to get most of this section.
|
||||
|
||||
Also, I won't go too much into details and some things may be _half true_, don't expect a "definitive guide" but rather
|
||||
|
||||
### A BIG HUG
|
||||
|
||||
JavaScript is great at quick prototyping ; you throw a bunch of random, untyped variables and methods, you can dynamically add and remove class members, refresh the page and see if it works,
|
||||
make changes accordingly, refresh the page, repeat, life is easy.
|
||||
So you may wonder what is the difference between JavaScript and GLSL.
|
||||
After all, both run in the browser, both are used to draw a bunch of funky stuff on a screen and to that extent, JS is easier to use.
|
||||
|
||||
Well, the main difference is that Javascript is an **interpreted** language while GLSL is a **compiled** language.
|
||||
A **compiled** program is executed natively on the OS, it is low level and generally fast.
|
||||
An **interpreted** program requires a [Virtual Machine](https://en.wikipedia.org/wiki/Virtual_machine) (VM) to be executed, it is high level and generally slow.
|
||||
|
||||
|
||||
When a browser (the _JavaScript **VM**_) **executes** or **interprets** a piece of JS, it has no clue about which variable is what and which function does what (with the notable exception of **TypedArrays**).
|
||||
Therefore it can't optimize anything _upfront_, so it takes some time to read your code, to **infer** (deduce from the usage) the types of your variables and methods
|
||||
and when possible, it will convert _some_ of your code into assembly code that will execute much faster.
|
||||
|
||||
It's a slow, painstaking and insanely complex process, if you're interested in the details, I'd recommend watching how [Chrome's V8 engine works](https://developers.google.com/v8/).
|
||||
The worst is that every browser optimizes JS its way and the process is _hidden_ from you ; you are powerless.
|
||||
|
||||
A **compiled** program is not interpreted ; the OS runs it, if the program is valid, the program is executed.
|
||||
That's a big change ; if you forget a semicolon at the end of line, your code is invalid, it will not compile: your code won't turn into a program at all.
|
||||
|
||||
That's cold but that's what a **shader** is: _a compiled program executed on the GPU_.
|
||||
Fear not! a **compiler**, the piece of program that makes sure your code is valid, will become your best friend.
|
||||
The examples of this book and the [companion editor](http://editor.thebookofshaders.com/) are very user friendly.
|
||||
They'll tell you where and why your program failed to compile, then you'll have to fix things and whenever the shader is ready to compile, it will be displayed instantly.
|
||||
That's a great way of learning as it's very visual and you can't really break anything.
|
||||
|
||||
SO, ready?
|
||||
off we go, jump to one of the sections below!
|
||||
|
||||
* [types](./01/)
|
||||
* [vectors](./02/)
|
||||
* [matrices](./03/)
|
||||
* [textures](./04/)
|
||||
* [uniforms & unicorns](./05/)
|
||||
|
@ -1,5 +1,10 @@
|
||||
<?php
|
||||
<?php
|
||||
|
||||
$path = "../../";
|
||||
$subtitle = "learning to fly";
|
||||
$language = isset( $_GET[ 'lan' ] ) ? $_GET[ 'lan' ] : "";
|
||||
$README = "README";
|
||||
|
||||
include($path."/header.php");
|
||||
include($path."/src/parsedown/Parsedown.php");
|
||||
|
||||
@ -11,15 +16,16 @@
|
||||
|
||||
$Parsedown = new Parsedown();
|
||||
echo $Parsedown->text(file_get_contents ('README.md'));
|
||||
|
||||
/*
|
||||
echo '
|
||||
</div>
|
||||
<hr>
|
||||
<ul class="navigationBar" >
|
||||
<li class="navigationBar" onclick="previusPage()">< < Previous</li>
|
||||
<!--li class="navigationBar" onclick="previusPage()">< < Previous</li /-->
|
||||
<li class="navigationBar" onclick="homePage()"> Home </li>
|
||||
<li class="navigationBar" onclick="nextPage()">Next > ></li>
|
||||
</ul>';
|
||||
//*/
|
||||
|
||||
include($path."/footer.php");
|
||||
include($path."/footer.php");
|
||||
?>
|
||||
|
Loading…
Reference in New Issue
Block a user