finished appendix

git commit -m finished
pull/80/head
nicolas barradeau 8 years ago
parent 86eb812e7d
commit 83485dc276

@ -1,8 +1,145 @@
Vectors are fun, they're the meat of your shader.
There are other primitives such as Matrices and Texture samplers which will be covered later in the book.
### matrix
We can also use Arrays. Of course they have to be typed and there are *twists*:
* they have a fixed size
* you can't push(), pop(), splice() etc. and there is no ```length``` property
* you can't initialize them immediately with values
* you have to set the values individually
Vectors are fun, they're the meat of your shader and soon enough you'll to have transform them.
this won't work:
```glsl
int values[3] = [0,0,0];
```
but this will:
```glsl
int values[3];
values[0] = 0;
values[1] = 0;
values[2] = 0;
```
This is fine when you know your data or have small arrays of values.
If you want a more expressive way of declaring a variable,
there is also a ```struct``` type. These are like _objects_ without methods ;
they allow to store and access multiple variables inside the same object
```glsl
struct ColorStruct {
vec3 color0;
vec3 color1;
vec3 color2;
}
```
then you can set and retrieve the values of _colors_ by doing:
```glsl
//initialize the struct with some values
ColorStruct sandy = ColorStruct( vec3(0.92,0.83,0.60),
vec3(1.,0.94,0.69),
vec3(0.95,0.86,0.69) );
[to be continued]
//access a values from the struct
sandy.color0 // vec3(0.92,0.83,0.60)
```
This is syntactic sugar but it can help you write cleaner code, at least code you're more familiar with.
### statements & conditions
Data structures are nice as such but we _might_ need to iterate or perform conditional tests at some point.
Fortunately for us, the syntax is very close to the JavaScript.
A condition is like:
```glsl
if( condition ){
//true
}else{
//false
}
```
A for loop is usually:
```glsl
const int count = 10;
for( int i = 0; i <= count; i++){
//do something
}
```
or with a float iterator:
```glsl
const float count = 10.;
for( float i = 0.0; i <= count; i+= 1.0 ){
//do something
}
```
Note that ```count``` will have to be defined as a ```constant```.
This means prefixing the type with a ```const``` **qualifier**, we'll cover this in a second.
we also have the ```break``` and ```continue``` statements:
```glsl
const float count = 10.;
for( float i = 0.0; i <= count; i+= 1.0 ){
if( i < 5. )continue;
if( i >= 8. )break;
}
```
note that on some hardware, ```break``` does not work as expected and the loop doesn't bail out early.
In genearal, you'll want to keep the iteration count as low as possible and avoid the loops and the conditionals as often as you can.
### qualifiers
On top of the variable types, GLSL uses **qualifiers**.
Long story short, qualifiers help the compiler know which variable is what.
For instance some data can only be provided by the CPU to the GPU, those are called **attributes** and **uniforms**.
The **attributes** are reserved for the vertex shaders, the **uniforms** can be used in both the vertex and the fragment shaders.
There's also a ```varying``` **attributes** used to pass variables between the vertex and the fragment shader.
I won't go too much into details here as we're mostly focused on the **fragment shader** but later in the book, you'll see sometihng like:
```glsl
uniform vec2 u_resolution;
```
See what we did here? we stuck a ```unifrom``` qualifier before the type of the variable
This means that the resolution of the canvas we're working on is passed to the shader from the CPU.
The width of the canvas is stored in the x and the height in the y component of the 2D vector.
When the compiler sees a variable preceded by this qualifier, it will make sure that you can't *set* those values at runtime.
The same applied to our ```count``` variable which was the limit of our ```for``` loop:
```glsl
const float count = 10.;
for( ... )
```
When we use a ```const``` qualifier, the compiler will make sure that we set the variable's value only once, otherwise it's not a constant.
There are 3 extra qualifiers that are used in the functions signatures : ```in```, ```out``` and ```inout```.
In JavaScript, when you pass scalar arguments to a function, their value is read-only and if you change their values inside the function,
the changes are not applied to the variable outside the function.
```glsl
function banana( a ){
a += 1;
}
var value = 0;
banana( value );
console.log( value );// > 0 ; the changes are not taken into account outside the function
```
With argumnts qualifiers, you can specify the behaviour of the the arguments:
* ```in``` will be read-only ( default )
* ```out``` write-only: you can't read the value of this argument but you can set it
* ```inout``` read-write: you can both get and set the value of this variable
rewriting the banana method in GLSL would look like
```glsl
void banana( inout float a ){
a += 1.;
}
float A = 0.;
banana( A ); //now A = 1.;
```
This is very different from JS and quite powerful too but you don't have to specify the signature qualifiers (the default is read-only).
### And we're done!
Of course we could have gone deeper into the various concepts but as mentioned earlier, this is meant to give a BUG HUG to the newcomers.
It's a quite a lot to ingest but with patience and practice, this will become more and more natural.
I hope you found some of this useful, now [what about starting your journey through the book?]("https://thebookofshaders.com/")

@ -1,5 +1,5 @@
### uniforms & unicorns
### unicorns
[to be started]

@ -0,0 +1,53 @@
## An introduction for those coming from JS
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.
Last note, a **shader** is made of 2 programs, the **vertex shaderr** and the **fragment shader**.
In a nutshell, the **vertex shader**, the first programm, recieves a *geometry* as an input and turns it into series of **pixels** (or *fragments*) then hands it over to the
**fragment shader**, the second program, that will decide which color to paint the pixels.
This book is mostly focused on the latter, in all the examples, the geometry is a simple quadrilateral that covers the whole screen.
SO! ready?
off we go!
* [types](./01/)
* [vectors](./02/)
* [unicorns](./03/)

@ -39,11 +39,404 @@ The examples of this book and the [companion editor](http://editor.thebookofshad
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/)
Last note, a **shader** is made of 2 programs, the **vertex shaderr** and the **fragment shader**.
In a nutshell, the **vertex shader**, the first program, recieves a *geometry* as an input and turns it into series of **pixels** (or *fragments*) then hands them over to the
**fragment shader**, the second program, that will decide which color to paint the pixels.
This book is mostly focused on the latter, in all the examples, the geometry is a simple quadrilateral that covers the whole screen.
SO! ready?
off we go!
### strong types
![first search result for 'strong type' on Google Image, on the 2016/05/20](strong_type.jpg)
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;
```
Which is strictly equivalent to dressing up a **_cat_** in a **_giraffe_ outfit** and 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.
### Vectors
![first search result for 'vector villain' on Google Image, on the 2016/05/20](vector.jpg)
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? (well, actually it 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, 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 equal 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).
### more types
Vectors are fun, they're the meat of your shader.
There are other primitives such as Matrices and Texture samplers which will be covered later in the book.
We can also use Arrays. Of course they have to be typed and there are *twists*:
* they have a fixed size
* you can't push(), pop(), splice() etc. and there is no ```length``` property
* you can't initialize them immediately with values
* you have to set the values individually
this won't work:
```glsl
int values[3] = [0,0,0];
```
but this will:
```glsl
int values[3];
values[0] = 0;
values[1] = 0;
values[2] = 0;
```
This is fine when you know your data or have small arrays of values.
If you want a more expressive way of declaring a variable,
there is also a ```struct``` type. These are like _objects_ without methods ;
they allow to store and access multiple variables inside the same object
```glsl
struct ColorStruct {
vec3 color0;
vec3 color1;
vec3 color2;
}
```
then you can set and retrieve the values of _colors_ by doing:
```glsl
//initialize the struct with some values
ColorStruct sandy = ColorStruct( vec3(0.92,0.83,0.60),
vec3(1.,0.94,0.69),
vec3(0.95,0.86,0.69) );
//access a values from the struct
sandy.color0 // vec3(0.92,0.83,0.60)
```
This is syntactic sugar but it can help you write cleaner code, at least code you're more familiar with.
### statements & conditions
Data structures are nice as such but we _might_ need to iterate or perform conditional tests at some point.
Fortunately for us, the syntax is very close to the JavaScript.
A condition is like:
```glsl
if( condition ){
//true
}else{
//false
}
```
A for loop is usually:
```glsl
const int count = 10;
for( int i = 0; i <= count; i++){
//do something
}
```
or with a float iterator:
```glsl
const float count = 10.;
for( float i = 0.0; i <= count; i+= 1.0 ){
//do something
}
```
Note that ```count``` will have to be defined as a ```constant```.
This means prefixing the type with a ```const``` **qualifier**, we'll cover this in a second.
we also have the ```break``` and ```continue``` statements:
```glsl
const float count = 10.;
for( float i = 0.0; i <= count; i+= 1.0 ){
if( i < 5. )continue;
if( i >= 8. )break;
}
```
note that on some hardware, ```break``` does not work as expected and the loop doesn't bail out early.
In general, you'll want to keep the iteration count as low as possible and avoid the loops and the conditionals as often as you can.
### qualifiers
On top of the variable types, GLSL uses **qualifiers**.
Long story short, qualifiers help the compiler know which variable is what.
For instance some data can only be provided by the CPU to the GPU, those are called **attributes** and **uniforms**.
The **attributes** are reserved for the vertex shaders, the **uniforms** can be used in both the vertex and the fragment shaders.
There's also a ```varying``` qualifier used to pass variables between the vertex and the fragment shader.
I won't go too much into details here as we're mostly focused on the **fragment shader** but later in the book, you'll see sometihng like:
```glsl
uniform vec2 u_resolution;
```
See what we did here? we stuck a ```unifrom``` qualifier before the type of the variable
This means that the resolution of the canvas we're working on is passed to the shader from the CPU.
The width of the canvas is stored in the x and the height in the y component of the 2D vector.
When the compiler sees a variable preceded by this qualifier, it will make sure that you can't *set* those values at runtime.
The same applied to our ```count``` variable which was the limit of our ```for``` loop:
```glsl
const float count = 10.;
for( ... )
```
When we use a ```const``` qualifier, the compiler will make sure that we set the variable's value only once, otherwise it's not a constant.
There are 3 extra qualifiers that are used in the functions signatures : ```in```, ```out``` and ```inout```.
In JavaScript, when you pass scalar arguments to a function, their value is read-only and if you change their values inside the function,
the changes are not applied to the variable outside the function.
```glsl
function banana( a ){
a += 1;
}
var value = 0;
banana( value );
console.log( value );// > 0 ; the changes are not taken into account outside the function
```
With argumnts qualifiers, you can specify the behaviour of the the arguments:
* ```in``` will be read-only ( default )
* ```out``` write-only: you can't read the value of this argument but you can set it
* ```inout``` read-write: you can both get and set the value of this variable
rewriting the banana method in GLSL would look like
```glsl
void banana( inout float a ){
a += 1.;
}
float A = 0.;
banana( A ); //now A = 1.;
```
This is very different from JS and quite powerful too but you don't have to specify the signature qualifiers (the default is read-only).
## And we're done!
Of course we could have gone deeper into the various concepts but as mentioned earlier, this is meant to give a BUG HUG to the newcomers.
It's a quite a lot to ingest but with patience and practice, this will become more and more natural.
I hope you found some of this useful, now [what about starting your journey through the book?]("https://www.thebookofshaders.com/")

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Loading…
Cancel
Save