Hacker News new | ask | show | jobs
by dancodes 2634 days ago
I found it surprisingly hard to get access to the primitives mentioned in the intro, on a modern pc. How does one draw a pixel on a specific coordinate in a modern OS?
9 comments

SDL is generally the most painless way to get a framebuffer you can draw in, cross-platform, and it also handles creating windows, reading input and playing sounds if you want to. You can use it from C and pretty much any other language has bindings. Also any GUI toolkit will have a widget that is a blank canvas (Qt and Wx both do, GTK should as well, but I haven't used it much). Or you can write in javascript and use canvas.
the best/easiest way is still use opengl/directx/etc but draw your texture in software, and then draw the texture full screen.

This is the approach I used to teach software rendering in gameswithgo.org we make a putpixel function as in the old days, and use it to build up a texture, which we draw each frame. The texture becomes what used to be the framebuffer.

Copying the entire framebuffer over the PCI bus makes me sad, though it's obviously way faster than when you could memory-map the framebuffer. These days you can't map texture objects in memory because texture storage on GPUs is its own black magic and textures are not stored as simple linear framebuffers. It would be fun to restrict yourself to a well-documented architecture, e.g. give everyone a cheap intel-based notebook and write out commands directly for the graphics chip. I guess while fun that would teach more about doing low-level hardware access than graphics themselves.

And while on the topic of changing hardware forcing us to change our algorithms, I wonder if teaching scanline rendering is even worth it these days. Every CPU supports SIMD and a SIMD-optimised software rasteriser is a very different beast than the classic scanline triangle rasterisers of old.

Probably the fastest software rasteriser for modern CPUs is OpenSWR [0], written by Intel mostly to keep themselves relevant in the data visualisation space until GPUs eat HPCs (GPUs still can't help you when your dataset is measured in hundreds of gigabytes of graphics data), but it scales perfectly fine down to desktop CPUs. The code for it is in the Mesa tree [1]. I wish I could explain exactly how it works, but it's a pretty big beast and I haven't had the time to read and understand all of it. Intel gave a presentation on it at the HPC developers conference back in 2015 [2]

[0] http://openswr.org/index.html

[1] https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/driv...

[2] https://youtu.be/gpYd18E3TWc?t=1531

Here's the sample code I pass around for doing that. It's a minimal example using SDL. AFAICT, it's pretty much the fastest way to get graphics from the CPU RAM to the screen.

https://gist.github.com/CoryBloyd/6725bb78323bb1157ff8d4175d...

Not quite "writing a pixel to the screen", but to play around, you can use a <canvas> tag in HTML, like my demos do; you can use SDL, as another poster commented; or you can write some trivial code to write a PPM file to disk (or use something like libpng) to create image files on disk.
A lot of proof-of-concept code renders to memory (and putpixel becomes screen[y*width+x]=pixel) and then saves the memory to a graphics file. If you've already been motivated to work with graphics you probably already know how to save a PNG file. If you have ImageMagick you can even render to a raw, uncompressed, non-standard graphics file and describe the format of the file in the 'display' command when you want to view the file. Also standard formats like BMP and TGA can be pretty easy to use without a library.
It never was that easy (hang on, were there BIOS functions for that?). Anything that requires drilling down to draw a dot is too slow anyway. Obviously blitting an offscreen bitmap just leaves you the problem of dealing with pitch.

It was even more exciting dealing with rendering high resolution images with only a single line of bitmap. #thegoodolddays

MOV AX, 13h; INT 10h :)
JS canvas has a great and very basic api, and golangs image packages let you set pixels pretty well too
PyGame is a really approachable way to play around with 2d graphics. I believe it's based on SDL.
Delphi makes it easy
Canvas in a browser