Day 004 - Gradient renderer not working properly

I've recently started following along the Handmade Hero series to improve my programming knowledge and learn about game engines (I'm not a complete beginner when it comes to C but i can't say that i'm good with it, im able to follow along the series and read documentations in case i dont understand some stuff, but sometimes i find myself lost as english is not my primary language) and as i compiled and run the code after following along, i've noticed that my rendered is completely off.

image.png

I don't know if this is caused by my Laptop but it should atleast cover up the whole window.

If i shrink and resize the window enough, it gets like this: image.png

I've tried changing the code a bit by swapping Window and Bitmap (Which shouldnt work), and the rendering comes out like that:

image.png

image.png

This is still wrong since the rendering is now smeared and not just many squares filling up the window, but then if i resize:

image.png

I don't understand whats wrong in the code since i've followed along the video but i suppose it has something to do with the Width and Height of either the Window or Bitmap, or maybe it's just the Renderer's loop thats written wrong and i can't see where, this is the pastebin of the code:

https://pastebin.com/t59gXve9

Also i'd really appreciate it if any of you could better explain to me how the Renderer's loop works, i dont fully understand the whole Row and Pitch thing

Or like why the Bitmap is the destination and Window is the Source in this function image.png

Sorry in advance if my explanation isn't clear and thanks for the answers!


Edited by Ric on

There is an issue with the way you call Win32ResizeDIBSection. Your parameters are declared as int height, int width but you call it Win32ResizeDIBSection(width, height); (in WM_SIZE).

In case you thought C/Cpp would map the calling name to the function parameters name: it doesn't.

void fn( int a, int b, int c ) { ... }

...
int a = 1;
int b = 2;
int c = 3;

fn( a, b, c ); /* Inside fn, a == 1, b == 2, c == 3 */
fn( c, a, b ); /* Inside fn, a == 3, b == 1, c == 2 */

To find that issue I didn't do anything in particular, I just read the code and thought that it was odd to pass height before width. Most of the time I pass x before y, width before height. I always think of them as values about X and Y axis and I find that order more "natural".

One way you could have find out would be to step through the code using a debugger. But for a beginner it might be confusing how to follow messages and understand how/where the window proc is called (most of the time it's called by DispatchMessage, but it can be called by GetMessage and PeekMessage).

Setting a breakpoint in Win32ResizeDIBSection and verifying that you get the correct values would have help. But you need to know the correct value, or some properties of it. In this case that width should be bigger than height.

That is generally what you want to do, step though (part of) the code and never assume values are correct, always verify them. But there are always time where you'll not figure stuff out (especially at the beginning). I found that in those case it can help to take a long break (e.g. coming back to it the next day). If nothing helps, we are here to help.

Also i'd really appreciate it if any of you could better explain to me how the Renderer's loop works, i dont fully understand the whole Row and Pitch thing

Pitch is used because the number of byte you need to advance in memory to reach the next row might not be equal to the width times the number of bytes per pixels. It might be confusing in this case because pitch == width * bytesPerPixels. I know of two case where pitch != width * bytesPerPixels.

  • Sometimes the start of a row needs to be align to a specific value, and that could lead to having some padding (extra bytes) at the end of each rows (e.g. I think OpenGL textures by default need to be aligned to 4bytes, so if you've got an 1Bpp image with a width of 3 pixels (or any number not multiple of 4), you'll need add some padding at the end of each row).

  • If you want to have a sub rectangle in your bitmap (e.g. you've got a 512px * 512px image and you want to copy a 32px * 32px image in some part of it), when you finish writing the first row of the sub rectangle (32px), to get to the next location in big rectangle you need to advance by the pitch of the big rectangle.

Or like why the Bitmap is the destination and Window is the Source in this function

I think it's an error from Casey. ( https://hero.handmade.network/episode/code/day004/#1065 ). It may be fixed in a latter episode. Currently those size are always the same so it doesn't matter.


Edited by Simon Anciaux on

Casey fixes the bug in the next episode here: https://hero.handmade.network/episode/code/day005/#2675

Thank you for the answer, indeed i wrote the function with Height before Width and then i used it by passing Width and then Height which led to it giving me this weird rendering, honestly i don't know why i wrote the function with inverted values, now it works fine!

About the Pitch and Rows i kinda understand now, i guess i just have to repeat the concept many times till i fully understand but thanks for the examples aswell, really really helpful!


Replying to mrmixer (#29561)