Hello there beautiful people, lets continue on this rasterizer.
So now we want to draw lines between points inside of our image. How do we do this? Well firstly lets talk about linear interpolation. It works like this
You take point A (origin point) and your point B (goal point), whats a point? well in 2D that comprises of a X and a Y coordinate.
You calculate the X and Y cooridnate seperately in functions. What you do is you take A’s x coordinate + (Bx - Ax) and * it by a scalar between 0 and 1. So in our example we use 0.02f which is 2% of the total lines length. So what this formula does is that we essentially calculate, what is 2% of the X value in the distance between our two Points (A and B). Then we store that and apply the same logic for our Y calculation. It…
Hello there beautiful people, lets continue on this rasterizer.
So now we want to draw lines between points inside of our image. How do we do this? Well firstly lets talk about linear interpolation. It works like this
You take point A (origin point) and your point B (goal point), whats a point? well in 2D that comprises of a X and a Y coordinate.
You calculate the X and Y cooridnate seperately in functions. What you do is you take A’s x coordinate + (Bx - Ax) and * it by a scalar between 0 and 1. So in our example we use 0.02f which is 2% of the total lines length. So what this formula does is that we essentially calculate, what is 2% of the X value in the distance between our two Points (A and B). Then we store that and apply the same logic for our Y calculation. Its important to note that we round to nearest our result for each X and Y value we achieve. Then we paint that pixel, then we move on until that scalar gets fully to 100%.
This is the result, it has faults. Because just declaring a 0.02f scalar will not accurately paint out pixels perfectly, I mean that makes sense right you can’t just decide that a random number will work perfectly for every instance of drawing a line. So lets try and fix this.
here we are changing the code to loop over the X values instead of the scalar we were using before. This ensures us that were going from the x coordinate of point A to the x coordinate of point B.
so the t float represents how far along the line we are, same as before 0.02 is 2% of the length of the line, were casting our A point and B points x valeus to floats because that’s we don’t want to lose any data on our calculations. Then were just doing the LERP calculation of Ax + (bx - Ax) * t);
However you might have noticed that we will get a bug here? I managed to evade the bug by the nature of which i decided to draw my triangle in my code as you can see here
So the green Line actually draws but lets say that bx is not bigger or equal to ax, then the condition for this loop would be false and that line wouldn’t be drawn, we can fix this with a simple swap function before checkign with the loop.
with this we should get this image.
well that blue line doesn’t look good, were missing a lot there. Sometimes a line is more vertical than it is horizontal and this could cause problems with our code, the way to fix this is by transposing the y value to an x value and then doing the calculation essentially treating our y value as our x value in our set function.
and with that we get our very nice loooking triangle here.
I changed our image files to bmp files instead because it was easier to get those uncompressed but the code is basically the same.
now it is time to do some otpimization, why you might ask? Because I want to learn.
so lets define some random lines in our code that set a random x and y paint and paints lines between them.
Our first optimization is to just statically add 1 to the y axis and or subtract 1 on the y axis depending on if the direction is up and down, since thats how th y line is always calculated, there is no reason to manually calculate the y position everytime with our scalar.
That divide part at the very end of y += is what gives us that either positive or negative number.
Time for our second optimization.
So before we declared a float for our y, this is however a little bit of wasted memory. This should make it so that we only use an int to store our y value but we correct it via a float that keeps our y aligned to the ration in which its increasing on the y. It does this by checking if the error is bigger than 0.5, this essentially means should it move up one more pixel and it does so accordingly.
were still however using a float for this so lets ditch that.
That does it for this part, in the next part we will implement our own geometry.h file. The one tinyrenderer uses I find confusing and not very c++ beginner friendly so I will make my own one that still works the same (essentially hopefully), then maybe if we have time we will finish the wireframe loading aswell.
were essentialy doing the same thing here but instead of dividing were multiplying because thats easier to do with integers right. So were performing the same mathematical calculation but just arriving their via integer instead.
So this code is actually slower on paper than what we began with beacause were using an if statement. Since this is coded on the CPU if statements with a conditional like > essentially slows down and boggs down the pipleline. Since the CPU has to check wether or not this statement is correct and does so repeatedly for every loop it guesses everytime it is run, however if it guesses wrong it has to flush its pipeline and reset from 0, this ofcourse takes a little bit mor time, this is unlike the GPU which can run multiple paths but masks the incorrect one. So lets do this code without any if statements.