EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 14: Transparency in Meshes

This week’s game: simple one-click download below, unzip, play, enjoy!

NancyNewren_ExampleGame 14

What’s new
I added two transparent objects!

Controls
Main object: Use arrow keys to move main object left/right/up/down
Camera:  
Left/Right (A/D), Up/down (W/S), Zoom in/out (Q/E)

(When moving the camera things in the world will appear to move opposite. Thus when you move camera left, the world will appear to move right.)

 About the Project

This time around I added the ability to become transparent to my meshes! It was fun.

First thing was to create a shader and an effect to allow for transparency. Next I created two objects drawn with them, but drew the meshes in whatever order they were submitted to the render thread. This works fine for opaque objects, However for transparent objects when a transparent object is drawn in before an object behind it is drawn, the object behind it isn’t drawn properly (as expected that is) to the screen. I.E. you can’t see the object behind a transparent object if that object isn’t drawn before it.

This means that all transparent objects have to be drawn back to front. The order of the opaque objects doesn’t matter though (with depth buffering on at least), as long as they are drawn before all transparent objects.

So what I did to order the draw calls is: after submission to the render thread is over and and before the swap, I ordered the draw calls. How? First thing: I added the index of all opaque objects (I just asked the mesh’s effect if it was opaque, nicely of course) to a vector in the order they were submitted, and then put the transparent meshes in a separate vector with their index and their camera space z value. This is the key to quickly sorting these meshes: in camera space I immediately know which meshes are in the back and in the front based solely on their z values since camera space is when the camera is at the origin and is facing forward. Then a simple std::sort with a lambda function that orders the z’s based on z forward being negative z (i.e. larger values of z aren’t closer to the camera, they are the farthest away), quickly sorts those values. Once sorted I added the index values of the sorted transparent meshes to the end of the previously mentioned vector (the one with the opaque meshes all in front to be drawn first.) Then in the rendering of the meshes I draw them in the order of the sorted draw calls.

I chose the render thread because with my game it doesn’t really matter which thread does the sorting because it’s such a small game. However, in a real game I would profile both threads and then choose the thread that takes the least amount of time.

 Acknowledgements

I asked my brother how to use the std::sort with my vector<struct> as I hadn’t done a templated sort before . He set me on the path with the google search I needed and I whipped out a lambda compare for my sort in no time.  Thanks bro!

Advertisement
EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 4: Utilizing Game and Render Threads for Improved Performance

NancyNewren_ExampleGame 4

Now we’re getting somewhere! The game can now render an arbitrary amount of sprites per frame. In this instance there are four. I think it’s pretty. 😉 (Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)

About the Project

The simplest part of this project was letting the game submit to the graphics a different background color. This data is cached until the renderer is ready to render.

eae6320::Graphics::SubmitBackgroundColor(eae6320::Graphics::DefaultColor::lightGray);

I moved all the sprites and effects out of the graphics class and created them in the game. Because rendering takes a significant portion of time in games, we utilize threads to render while the game computes data. In this implementation the game submits to the render data it wants rendered, which is then cached by the renderer until it’s ready to render. When the game is done submitting it lets the render thread know. When the renderer has finished rendering all the previously submitted data it cleans up that data and let’s the game know when it can start submitting again. This is the point where the threads sync, which is done each frame. At sync the render thread swaps the submitted cache and the cache it just cleaned. It then uses this data to render, and the game has a clean cache to submit data too. Submitting to the render thread is simple, just send over the sprite with its corresponding effect:

eae6320::Graphics::SubmitToRender(m_sprite[0], m_effect[0]);

Each rectangle needs it’s own sprite, but an effect can be used multiple times. So the second sprite uses the same effect:

eae6320::Graphics::SubmitToRender(m_sprite[1], m_effect[0]);

I am using the stl’s vector to create as many (up to the maximum number that a vector can hold that is) sprites and effects as I want. It’s then fairly trivial to submit sprites and effects to be rendered to the render thread.

Even though we are passing reference pointers around for all the sprites and effects, since we can send an arbitrary amount of sprites and effects to render the memory overhead can get large if we haven’t optimized their size. I had previously optimized the sprite and effect size by ordering member variables from largest to smallest. However when I saw the sEffect size I realized I was passing around unnecessary data. I removed it and the size dropped by the size of the variables I removed.

OpenGL
sizeof(sSprite): 12
sizeof(sEffect): 24, 16

D3D
sizeof(sSprite): 24
sizeof(sEffect): 64, 48

I’d only ever looked at the size of objects via code, so it was interesting to me to look at it during compile time. I opened the Debug->Windows->Immediates window in Visual Studio, put in an obvious breakpoint and when the debugger paused, I typed in “sizeof(ObjectName)” and the immediates window printed it out. Thanks to Mark Smith for helping me find the Immediates window.

I am having a recurring Visual Studio run bug. I spent quite some time trying to resolve it. J.P. tried to help as well for a while with no luck. I finally reverted all our changes, closed VS, and rebuilt and the bug went away. The thing is that I’ve done this multiple times and it keeps coming back. Running and building in Visual Studio haunt me and give me terrible nightmares.