
Simple software rasterizer in a single C++11 header file - StylifyYourBlog
https://github.com/Steve132/uraster
======
ykl
I TA'd a rendering course once and wound up assigning a homework where the
students implemented their own software rasterizers in CUDA. Before that
homework, a lot of students didn't really understand what a rasterizer did.
Afterwards, everyone got it.

~~~
lfowles
Do you have links to any resources the students found handy? I'm not very
familiar with anything to do with the graphics stack other than familiarity
with some of the words.

~~~
nitrogen
I'm not the author of the original comment, but when I was in high school I
found the Graphics Programming Black Book to be useful for understanding
graphics primitives and how they can be implemented in software. It's
available for free online:
[http://www.gamedev.net/page/resources/_/technical/graphics-p...](http://www.gamedev.net/page/resources/_/technical/graphics-
programming-and-theory/graphics-programming-black-book-r1698)

Maybe start with chapter 38:
[http://downloads.gamedev.net/pdf/gpbb/gpbb38.pdf](http://downloads.gamedev.net/pdf/gpbb/gpbb38.pdf)

~~~
lfowles
Thanks, this is a great read (even though parts seem dated, for example, the
TOC has chapters on the 386 and 486), I'm surprised that I haven't stumbled
upon it before.

~~~
nitrogen
The latest Core i7 still has all the same instructions as a 386 or 486, so
while these days you'd probably use SIMD instructions, the code will still run
and run _very, very fast_.

------
ricket
I'm not a C++11 developer, I've done a little C++ in the past. What is the
pride in putting all the code in the header file? Shouldn't the declarations
be there, and the definitions be pulled out into a .cpp file? Is it somehow
smaller, faster, more convenient to have it all in a header file?

~~~
jgh
Header libraries are easier to add to your project because there are no build
scripts to figure out or cross-compiling to do or whatever. A lot of Boost is
header-only, for example. GLM (OpenGL Mathematics), too, is header-only. OTOH
if you end up modifying a header that's included in a whole bunch of places,
woe unto you.

~~~
TheDong
The reason Boost is headers only is you have to be a header to be generic.
Implementations outside of headers have to friend / otherwise be not truly
generic.

~~~
theyoungestgun
Assuming you mean friend in the standard cpp way, that's not exactly correct.

[http://stackoverflow.com/questions/495021/why-can-
templates-...](http://stackoverflow.com/questions/495021/why-can-templates-
only-be-implemented-in-the-header-file)

------
rian
Why aren't you using nullptr instead of casting NULL to your pointer type?

------
madsravn
What exactly is the difference between this and for example a simple ray
tracer? Seems like it takes a lot of the same steps.

~~~
joeld42
This loops over the triangles and converts them to screen pixels. A ray tracer
loops over screen pixels and checks if there are any triangles that overlap
it.

~~~
Keyframe
More or less this. To expand a bit - rasterization converts lines or polygons
to pixels via hidden line removal techniques
([http://en.wikipedia.org/wiki/Hidden_line_removal](http://en.wikipedia.org/wiki/Hidden_line_removal))
and/or hidden surface techniques
([http://en.wikipedia.org/wiki/Hidden_surface_determination](http://en.wikipedia.org/wiki/Hidden_surface_determination))
while ray tracing can mean a lot of different things, where most common and
basic form is Whitted's ray tracing where final image is a grid of pixels with
from each one there is a 'ray' shot towards the scene and checking if there is
a collision with the object (polygon) and then turned towards each light
source. In normal world, model is that light travels from light source,
bounces from objects and comes to the camera - Whitted's algorithm is opposite
where rays are shot from camera towards objects (modified by surface
properties there) and towards light sources (less computation that way).
Modern ray tracers involve Kajiya's equations and other fancy stuff.

~~~
alok-g
Thanks for the explanation. How are multiple hops in light path handled
without having the computational complexity go insane?

~~~
beagle3
They aren't.....

Some popular shortcuts include:

\- Cut at n hops (with n=4 or n=8 popular choices), defaulting to "ambient"
light after that

\- Give each material an "ambient" color, so that you don't actually need to
trace every pixel back into every light source (just into e.g. spotlights)

\- Solve a radiosity equation for the surface colors, and trace rays for
textures/reflections.

Complete ray tracing is, indeed, insane - in fact, to get high quality
pictures and avoid aliasing, most ray tracers send multiple rays through every
picture and average the result.

~~~
beagle3
(too late to edit:) that was supposed to be "multiple rays through every
_pixel_ "

------
pjc50
I recently unearthed the code I wrote at school in 1996 which implemented a 3D
Gouraud-shaded renderer that managed ~1000 triangles/sec on a 33MHz 486. It's
a great learning experience doing this from scratch.

Mine did Bresenham's algorithm for pixel fill rather than the winding approach
used here.

------
AshleysBrain
Very cool - any perf stats though? Would be interesting to see how this
compares to other software renderers.

