24
\$\begingroup\$

I started watching the Handmade Hero stream, where Casey Muratori creates a game engine without using frameworks or such. Yesterday I got to the part where he showed how an image is drawn onto the screen. As far as I understood it he just allocated some memory as big as the size of the screen he wants to draw to. And then he created a bitmap which he passed to the buffer memory he allocated and drew it to the screen using a os specific function.

This seems quite straight forward. I used GameMaker, changed to Love2D, worked a little bit with Sprite Kit but I was always wondering what was really happening beneath this sometimes confusing layers.

Given that, why even bother using graphics libraries (OpenGL, SFML, SDL, …) when all you have to do is simply allocate some buffer, pass a bitmap and draw it to the screen?

If you then want to draw distinct things to you screen you just write them to your bitmap which then gets passed into the buffer. I'm quite new to programming, but this seems quite simple to me. Please correct me if I'm wrong.

\$\endgroup\$
  • 11
    \$\begingroup\$ later in his series (around episode 220) he will use opengl. The reason he does that is speed. \$\endgroup\$ – ratchet freak May 13 '16 at 10:29
  • 5
    \$\begingroup\$ The trick is determining what to draw to the screen. All of the GPU texture/shading stuff, triangles, camera projections, etc. need to be done first to decide what color each pixel should be. Pushing the pixel colors to the screen is the easy part. \$\endgroup\$ – user14146 May 13 '16 at 19:20
  • 2
    \$\begingroup\$ For the record, SDL and OpenGL aren't mutually exclusive. SDL is a "hardware abstraction layer" that also handles windows, events and input as opposed to being just a graphics library. SDL also has support to be used in conjunction with OpenGL so SDL can do all the non-graphics stuff while OpenGL handles the graphics. Also note that most often OpenGL works directly with the GPU whereas SDL may or may not depending on the version and system being compiled for. \$\endgroup\$ – Pharap May 14 '16 at 12:28
  • \$\begingroup\$ SFML uses OpenGL for rendering, so really all SFML does is provide a simpler interface for using OpenGL. \$\endgroup\$ – Cornstalks May 14 '16 at 19:03
  • 2
    \$\begingroup\$ Techcnailyl what Casey is doing is still using a graphics library. The library is called GDI, and although it's part of the OS's main API, it's still technically a graphics library. \$\endgroup\$ – Pharap May 15 '16 at 14:33
41
\$\begingroup\$

It's not just about speed of execution, but also about simplicity. Although the software rendering used in this example would be a lot slower than using hardware acceleration (i.e. a GPU), drawing a few bitmaps on screen is such a trivial task that you would not notice the performance drop.

However, low-level activity like triangle rasterisation, depth sort and the like are well-understood concepts that the GPU can handle implicitly with a few commands. Re-implementing those in software mode is essentially reinventing the wheel. This is fine if you want to gain a low-level understanding of how rendering is done, I myself wrote a 3D software renderer just to explore it a bit, but for most circumstances it's a waste of time when OpenGL can do it faster out of the box.

The example you've given sounds extremely basic, just drawing a single image on the screen, hence the implementation is easy. Once you start layering on complexity though, you'll find it becomes increasingly complicated to get everything rendering correctly. The stuff people had to do back in the Quake days of 3D software rendering was insane, though I appreciate you're not going THAT far (yet).

\$\endgroup\$
  • 12
    \$\begingroup\$ OpenGL knows terms like points, lines and triangles. Most of the time you'll work with triangles. To learn how to work with OpenGL I can recommend opengl-tutorial.org. To learn what OpenGL does under the hood take a look into the official wiki: opengl.org/wiki/Rendering_Pipeline_Overview \$\endgroup\$ – tkausl May 13 '16 at 16:06
  • 1
    \$\begingroup\$ I was going to +1 but I don't like the bit about "reinventing the wheel" because I feel it gives the wrong impression in terms of the history of computing. Bitmap rendering came first, hence OpenGL was the one "reinventing the wheel". They had two good reasons to do so however: 1) Standardisation and 2) GPU acceleration. Reinventing the wheel is not always a bad thing if the new version is an improvement (i.e. wheels with tyres vs wooden wagon wheels). The key point here should not be that software rendering is reinventing the wheel, it should be that it's inferior to GPU rendering. \$\endgroup\$ – Pharap May 14 '16 at 12:36
  • 4
    \$\begingroup\$ @Pharap except that now, writing a software renderer absolutely is reinventing the wheel, regardless of whether or not it was historically. \$\endgroup\$ – porglezomp May 14 '16 at 20:33
  • 1
    \$\begingroup\$ This is only half an answer. The next answer is the other half, but a complete answer (including a bit of an explanation of the difference between OpenGL and the other things he mentions) would be the proper answer to this question. \$\endgroup\$ – Jasper May 15 '16 at 8:50
  • 1
    \$\begingroup\$ @user148013 "Does opengl know terms like point, line, triangle?" Modern OpenGL deals exclusively with these primitives. You can't rasterize anything but them. \$\endgroup\$ – Nax May 16 '16 at 2:14
25
\$\begingroup\$

My question is: why even bother using something like open gl, sfml, sdl when all you have to do is simply allocate some buffer, pass a bitmap and draw it to the screen?

Short: Because its fast (OpenGL, DirectX).

Long:

You may think you can do this all yourself. Draw pixels to a screen. You might write a small library to draw shapes, like quads or triangles. This will work, of course. There are a lot of libraries out there to do exactly this. Some of them even implement the OpenGL-spec (so they are like a software-side for opengl) which will do exactly what Casey Muratori does. They calculate everything on software-side, set the pixels on software-side and write the result to the screen.

However this is slow. The CPU which will eventually execute all these things wasn't made for this scenario. Thats what GPUs are for. What OpenGL does (unless it's a software-implementation of course) is take everything you tell it to do and push all data, all draw-calls, almost everything to the graphics-card and tell the GPU to do the work. The GPU is made specifically for this kind of job. Multiplying floating point numbers (Thats what you do a lot when drawing a 3D-scene) and executing shaders. And this in parallel. Just to get you a sense of how fast the GPU is, think about a simple scene in 3D in fullscreen with 1920x1080 pixels. These are, multiplied, 2,073,600 pixels to draw. For every single pixel, the GPU will run the fragment-shader at least once, most of the times more than once. Now, lets say we run at 60 frames per second. This means, the GPU runs the fragment-shader 2,073,600 * 60 = 124,416,000 times per second. Do you think you can do something like this on your CPU? (Thats a pretty simplified explanation, there are a lot more things to consider like how many pixels you overdraw by nearer objects, how much MSAA you use and so on, however the 124,416,000 times per second are probably the lowest you can get, and you'll easily have a lot more than 60fps with a simple scene)

Thats what OpenGL and Direct3D do, for what engines do see @Uri Popovs answer.

\$\endgroup\$
  • 8
    \$\begingroup\$ He's creating a 2D game, thats another topic as 3D is. And when I say slow it doesn't necessarily mean that it has less than 60 fps but it means that the graphics-card will do the same job in a fraction of the time the CPU needs, at least when it comes to 3D space. \$\endgroup\$ – tkausl May 13 '16 at 10:28
  • 4
    \$\begingroup\$ Well the reason GPUs are better at it is because they are set up to parallelize the shader invocations. \$\endgroup\$ – ratchet freak May 13 '16 at 10:31
  • 4
    \$\begingroup\$ @user148013 From what I've seen from this guy, I'd say he's an exact opposite of "very wise". \$\endgroup\$ – Bartek Banachewicz May 13 '16 at 17:36
  • 4
    \$\begingroup\$ It's not just that it's slower to render (Casey's software renderer was surprisingly quick). It that it's also a lot of data to keep pushing from general RAM to video RAM. Pushing a giant bitmap to the video card, depending on the type of bus, can take a significant chunk of a frame time. Using the GPU, you push textures occasionally, and use them for frame after frame. \$\endgroup\$ – Adrian McCarthy May 13 '16 at 18:10
  • 2
    \$\begingroup\$ @user148013 There's a difference between flashy and good programming. They can overlap, but often they are in conflict. I'd put "I can render in software [just like MESA can...]" under flashy and most certainly not good. \$\endgroup\$ – user59192 May 13 '16 at 19:21
11
\$\begingroup\$

What he does is called software rendering, what OpenGL does is called GPU rendering

What's the difference between them? Speed and memory.

Rasterization (filling out triangles on screen) takes some time. If you do it on the CPU, you essentially take that time away from game logic, especially if it's not optimized well.

And doesn't matter, how small the image is, he needs to allocate certain amount of memory for it. GPUs have a video memory for this.

\$\endgroup\$
  • \$\begingroup\$ Is software rendering possible on OS X too? Because it seems everything which has to do with graphics was done by OpenGl now Metal. \$\endgroup\$ – user148013 May 13 '16 at 14:24
  • 2
    \$\begingroup\$ @user148013 You have some missunderstandings. OpenGL is a multiplatform API, so it can run on OS X, in fact it can run on everything with a "modern" (post 2000) GPU. Metal is a separate API for Apple devices only. Software rendering is also a separate thing from both of them, and yes, it can be done on OS X too. It's basically just setting pixels manually on the screen with the CPU. \$\endgroup\$ – Bálint May 13 '16 at 14:44
  • \$\begingroup\$ Thats exactly why I asked because as far as I know software rendering can't be done on OS X. Cocoa reaches out to OpenGl, Quarz uses OpenGl, Core Framework uses OpenGl. They all now use Metal as its way faster. But i haven't found a single function that draws a buffer to the screen without the use of the GPU (OpenGl, Metal). \$\endgroup\$ – user148013 May 13 '16 at 14:51
  • 1
    \$\begingroup\$ @user148013 Because it's not specific to an OS, nor implementations. Let's say you want to implement it in java, because that's a famous choice for multi-platform developement. With java, you can do it by first creating a window (JFrame), then instead of straight drawing on it, you draw on an image, then you put this image on the frame. It however won't know the terms "triangle" or "line". Only colors. You need to implement that yourself with a rasterization algorithm. This is why we prefer OpenGL, it's faster, and a bit easier to use. It's basically a rasterization API. \$\endgroup\$ – Bálint May 13 '16 at 14:56
  • 2
    \$\begingroup\$ @user148013 Why couldn't they? If they can open a window, and they can draw 1 image on it without an API, then they can. \$\endgroup\$ – Bálint May 13 '16 at 17:36
8
\$\begingroup\$

While the answers from others are more correct than any answer I could give, I want to point out the fundamental misunderstanding about how software development works that I think underlies your question. While it's always possible to do things "by yourself" without a framework, and there's often great educational benefit from doing so, the reality is that's not how modern software is created.

Somebody created the hardware and the machine languages that run on it. Somebody else creates higher level languages and compilers, drivers and operating systems, graphics libraries and on and on. We each build upon the work of our predecessors. That's not only "okay", it's a requirement.

You're drawing the line of what's "acceptable" or not at an arbitrary point in the toolchain. You could just as easily say "why use C++ when you could do the same thing in assembly?", or "why rely on the keyboard drivers when you could just as easily read the voltages coming off its wires and calculate it yourself?" There aren't enough hours in the day, or years in a lifetime for everyone to do everything themselves.

This doesn't apply just to software development, but to modern life in general. Have you ever heard of the guy that built a toaster himself, from scratch? http://www.thomasthwaites.com/the-toaster-project/. It took a really long time and a whole lot of effort. For a toaster. Try building everything that's required to actualize a video game out of the ether all on your own!

\$\endgroup\$
  • 2
    \$\begingroup\$ I think this is a good answer because it states why using frameworks is good without belittling the idea of reinventing the wheel for educational purposes. \$\endgroup\$ – Pharap May 14 '16 at 13:10
3
\$\begingroup\$

Engines do much more that just draw a picture to the screen. They handle lighting, shadows, input , collision detection. Even just the rendering part is way more complex than just pushing a buffer onto the screen. For 3d scenes especially you need to do a lot of calculations on far more complex data than a bitmap. Let me give you a analogy with a car: What you are describing as simple is the exhaust of the car. You just make a pipe with the right size and then you push the gas from one end to the other. However this is far from the only thing happening in the mechanism of the car.

\$\endgroup\$
3
\$\begingroup\$

The above answers are excellent, but none really goes over the most important reason as to why OpenGL and such are preferred. The main reason is to make use of dedicated hardware designed especially to work with things like rendering millions of pixels on a screen, the GPU.

With software rendering, using the CPU, the renderer will be looping, one by one, over all the pixels on a bitmap and issue orders to show each on the screen. So if you're rendering a 1000x1000 sized image, that 1,000,000 loops for your CPU to go over. They are designed with control in mind after all; lots of if conditions, jumping from one set of instructions to another and a strict direction of flow of control. However, a GPU is designed with knowledge that it'll be doing a lot of similar looping over pixels on the screen. A GPU would take a for loop with a 1000000 iterations and divide the work over its huge number of cores for each to work** in parallel, and independent from one another**. So unlike the CPU, every time a GPU comes across an if-else condition, it'll handle both code branches to two cores of itself AND THEN, at the very end, it'll look at what the condition evaluates to and discards the result of the unneeded branch (that's why lots of if-else conditions in GPU shaders are frowned upon; they're always responsible for a waste).

So yes, GPUs are built around parallelism. That makes working on pixels for them much faster compared to CPUs.

\$\endgroup\$
0
\$\begingroup\$

See Do I really need to use a graphics API?

Sure, you can ask for a buffer, set some bits in it and write it to the screen. That was essentially the only way to do graphics programming on the PC until the availability of graphics accelerators in the mid-90s from 3DFX. Even in Windows, DirectX was developed to give direct access to video memory.

But on non-PC hardware, dedicated games machines, there have always been techniques for speeding up graphics by offloading work from the processor. Even the Atari 2600 had "hardware sprites", partly because it didn't have enough RAM for a framebuffer.

Later (mid 80s) games consoles were optimised for platform games. Again, no framebuffer; instead the programmer could specify grids of tiles:

The Genesis graphics hardware consists of 2 scrollable planes. Each plane is made up of tiles. Each tile is an 8x8 pixel square with 4 bits per pixel. Each pixel can thus have 16 colors. Each tile can use 1 of 4 color tables, so on screen you can get 64 colors at once, but only 16 in any specific tile. Tiles require 32 bytes. There is 64K of graphics memory. This would allow for 2048 unique tiles if memory were used for nothing else.

\$\endgroup\$
-2
\$\begingroup\$

Modern CPUs are fast enough to do any 2d game in software, so for 2d graphics OpenGL/DirectX would offer no advantages, beside adding yet another dependence and a layer of complexity to your project, like i.e. setting a 3d projection matrix to draw a bunch of sprites and uploading data to GPU.

OpenGL would also force you to pack all your sprites inside 512x512 textures (an artifact of old consoles, like PSX, packing graphics into video memory pages), requiring you to write rather complex sprite packing code.

On the other hand, if you're doing 3d, rendering millions of triangles with complex shading, then GPU is unavoidable. Long ago there was simpler 2d only version of Direct3d, called DirectDraw, which GPU accelerated sprite drawing, but now Microsoft no longer supports it, possibly because CPUs are fast enough to do 2d without any acceleration, if you don't care about energy saving.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.