Before we can represent 3D data we need to decide how we want to represent it.
Just like we can represent any point using a single number,
And we can represent onscreen using 2 numbers,
We can represent any point in 3D space using 3 numbers.
We'll call these
X
Y
& Z.
It works!
Adding a number to a vector Adds that number to each component.
And commutative operation...
Continue on for subtraction,
multiplication,
(As you can see operator overloading is very easy in [Julia], very legible. Which is one reason I chose this.)
(Often the temptation of operator overloading encourages devs to write less legible code)
(but defining new types of numbers like vectors is precisely what operator overloading is designed for.)
division,
& exponentiation.
Similarly we can add 2 vectors By pairing up their components, like so.
Continue on for subtraction,
multiplication,
division,
& exponentiation.
Negation applies to each invidual component.
We'll continue defining maths functions on vectors following the GLSL spec in alphabetical order.
Here we're defining some trigonometry.
We may explore how we'll actually implement trigonometry, but that will be out of scope for this video.
For now I'm just using [Julia]'s standard API for once. Technically all of this could be using the [Julia] standard API
But I wanted to show you how this works.
A floating operation... Rounding the number up.
A comparison operation...
Eee, O.k. got that syntax wrong.
Now I can actually define clamp on Vecs. Whether with floating point bounds or vector bounds, like so.
Back to some trigonometry...
& cross will return, given 2 vectors, the multiply-sum of their components.
This is actually a dot-product.
Distance will be the length of the difference.
Cross product is a bit more convoluted, which returns a vector pointing tangentially to the 2 given ones
by rearranging the components
Detecting whether an incident vector & normal vector faces forward, we take the dot-product of the reference & incident vectors returns either N or -N.
There's shortcuts that can be used to compute inverse squareroots but for now we'll simply take the square root & inverse it.
Then define the overload the function to operate componentwise on a vector as per usual.
Computing the length is trigonometry.
Logarithms... We can specify a 2nd argument to give a base.
More comparison functions...
We'll define a `mix` function operating on any numeric type to blend between 2 numbers.
Computes remainders...
We can normalize a vector to have length of 1, by deviding it by its length.
To simulate the path of lightrays it can be useful to simulate reflections
by doubling the dot-product & multiplying by N.
Simulating refractions involves a bit of conditionality.
Initial estimatation...
Depending on sign... If it's negative there's no refraction.
Otherwise, involving a squareroot
Now lets add a bit more rounding.
A floating point operation... to retrieve the sign.
More trigonometry...
Some blending... which smoothly transitions between the given bounds whether floating point or vector.
Compute position along the range...
Then square "t" multiply that for a smooth result.
Square root may be handy...
For a less-smooth transition lets start on floats.
Now we can define it for vectors on either a float edge or vector edge.
Yet more trigonometry...
& floating point.
& that pretty well covers Ooo, syntax error. Ah! Need an "end".
There we go. [Certain 1999 action music plays] That covers mostly covers the GLSL API.
Also we can abstract polynomial formulas into just 12 numbers
(I'll come back to why I'm giving these names) called a matrix.
Specifically this formula is x' = a.x*b.xx + a.y.xy + a.z*b.xz + b.x0
y' = a.x*b.yx + a.y*b.yy + a.z*b.yz + b.y0 z' = a.x*b.zx + a.y*b.zy + a.z*b.zz + b.z0
The benefit of this is that it makes it easy to combine 2 matrices. Let's take it that we're 2 dimensions for this algebra to be more legible.
So g of x dot x is x.x*g.x + x.y*g.xy + g.y0 g of x dot y is...
Similarly... would be...
Substituting one into the other this becomes...
Expanding that we get...
Unexpanding it... we can get a new matrix!
Ah, left off a component here...
This rearranges similarly.
Expanding... gives...
& factorizing by the fields of x gives...
Ah what, something not right.
Expanding this into 3 dimensions gives... (let's be more consistant)
Now to compute y...
I hope you can see a pattern forming in this. Usually, mathematicians matrices out in grids to make this is even more evident.
Put the z-axis in there...
Furthering the pattern to compute the Zs we get...
And it works!
We'll explore the full power of matrices in the next video, but first what might we want to do with them?
How about multiplying each field by the corresponding field in another matrix? Just like we do vectors?
Or how about computing the reverse operation which undoes whatever the input matrix does?
You can download this module at this video's webpage at https://gpu.adrian.geek.nz/s1e2