ssloy / tinyrenderer

A brief computer graphics / rendering course
https://github.com/ssloy/tinyrenderer/wiki
Other
20.29k stars 1.97k forks source link

Interesting Conclusion #30

Open yasirtug opened 5 years ago

yasirtug commented 5 years ago

Here is a quote from lesson 1:

We should note that each division has the same divisor. Let’s take it out of the loop. [...]

I can't understand how noting that each division has the same divisor helps us for making next improvements.

vchizhov commented 4 years ago

The idea is to make the code not use divisions and float. Note that if you have an inequality: a*b/c + d >= 0, then as long as c>0 you can turn it into: a*b + c*d >=0.

yasirtug commented 4 years ago

I remember having a hard time trying to grasp that part until eventually losing my trust to the writer and opening this issue angrily. Now I look again, I understand how the improvement is made and unfortunately, the explanation is really shallow and somewhat irrelevant to the change that is made.

'Taking the division out of the loop', after 'noticing that each division has the same divisor', would be just by calculating 1/{common divisor} beforehand and then multiplying the dividend with this value in the loop. Something like this (compare with 3rd attempt):

float divisor = 1/(float)(x1-x0);
for (int x=x0; x<=x1; x++) { 
    float t = (x-x0)*divisor;
}

But the change writer made (4th attempt) does this:

float derror = std::abs(dy/float(dx));
float error = 0;
for (int x=x0; x<=x1; x++) {
    error += derror;
} 

The improvement made here (not multiplying at every step) is possible not only because of the common divisor, also because of unmentioned proportional increase of dividend(x-x0) in the loop. Actually, it is more about the latter and one only needs to see that t variable in 3rd attempt is increasing by the same amount on every iteration, to easily implement the same optimization.

Whatever. My guess is, writer already had the resulting snippets (maybe from classes) and showed some impatience while filling the gaps. I also think the resulting explanation has something to do with trying to be smart (sorry, this costed me too much time and i am angry again).

vchizhov commented 4 years ago

While I do agree with your general feeling, we should also be fair considering who this tutorial was supposedly meant for. The important point being that the algorithm was most likely meant to be derived by readers (you can find my derivation here: https://github.com/vchizhov/ssloy_software_renderer/blob/master/src/line_bresenham.hpp). The algorithm description in wikipedia is also quite helpful (a bit different from mine, but ultimately equivalent): https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Algorithm_for_integer_arithmetic