Menu
Grend's Dev Blog
  • Advancement Plaques
  • Anthony Hilyard
  • Berry Season Reminder
  • Blog
  • Complex
  • Contact Me
  • Cooperative Advancements
  • Cross Section
  • Dungeon Defender
  • Dunwich
  • Equipment Compare
  • Improved Tracker
  • Stampede
    • Stampede Credits
    • Stampede Privacy Policy
  • Upgradable Pan
  • Weapons on Display
Grend's Dev Blog

Blog

Framerate Optimization and Simplifying Shaders

Posted on March 20, 2021May 27, 2021 by Grend

This post is going to get a bit into the weeds, so strap in. Over the last few weeks, when working on my still unnamed game project, I noticed that framerates were getting rather sluggish as I continued to add more and more dynamic entities, especially when I turned on all the "bells and whistles" and my debug overlay, which includes showing bounding boxes for everything in the game. This was especially apparent on my Linux machine with integrated graphics, where framerates could get as low as 25-30fps while displaying the debug overlay. I decided to take some time to investigate the cause and see what could be done about it.

Investigation

The rendering of the game is done in a few stages, composed of layers of static tiles and dynamic entities. Tiles are always in the same positions and generally don't change much, so rendering them is quite efficient, whereas entities can have dynamic positions and change all the time. I focused my attention first on the entities, since I suspected their additional complexity meant their rendering logic was more likely to be coded inefficiently.

I looked over my shaders, which had been written months ago at this point, and realized that in many of the fragment shaders, I was passing in information via data textures and looping over it to effectively support rendering overlapping entities.

Fragment Shader Pseudocode

// First data texture contains tile position and sprite coordinates.
sampler entityValues1

// Second data texture contains entity pixel offset and size.
sampler entityValues2


void main()
{
	foreach (entity)
	{
		get_data_from_textures()

		calculate_entity_position()

		get_entity_sprite()
		get_entity_size()


		calculate_pos_in_sprite()


		color = get_color_at_pos()

		if (color_is_visible)
		{
			break
		}

	}

	return color
}

It should be clear that this is incredibly inefficient. Fragment shaders are run by the GPU for every single pixel on the screen, every frame, so this is clearly contributing to the slowdown. This style of shader was likely a side-effect of the way I had developed the entire rendering framework in the engine. Everything was being rendered onto the same quad that covered the window, drawn multiple times with different shaders supplied with different data. Think of it like layers of transparencies on an overhead projector--simple, but it works (albiet inefficiently). In order to be able to use simpler shaders that don't require loops, I would have to split up the entities up front, having the shader take care of a single entity instead of the whole screen. And in order to do that, I would need to have each entity have its own dynamically-positioned quad.

The Process

I begun the long task of rewriting the rendering engine from the ground up, which required touching almost every piece of code that dealt with rendering. It also meant writing support for a few OpenGL features I hadn't had to worry about before, like a Vertex Array wrapper class. I rewrote the camera manager so I could more easily get the proper perspective view matrix for the new quads, simplified my texture handler class, since I didn't have to worry about data textures any more, and wrote a low-level quad handler. During the process, I even stumbled upon something surprising. From my C++ work, I've always learned to try to minimize branching where possible for time-critical code. When writing the quad handler (which converts entity quads to floating point values that OpenGL can use), my first attempt had a few if statements and a switch statement. I thought I could do better, so I worked to format the code in a way so there was absolutely no branching. I managed this by using a delegate map and calling these functions based on the "switched" value. Despite my efforts, I found that it was slower than before I had removed the branching. Stumped, I did a little digging and found that C#, unlike C++, is very unlikely to inline function calls and the overhead of actually calling these functions turned out to be more costly than some branching! Who knew?

Anyways, I eventually finished the process off by writing a much more elegant entity shader that only deals with a single entity at a time, and has all the data it needs from vertex attributes. Here's the actual GLSL code for the new shader:

#version 130

uniform sampler2DArray entitySheet;

in vec4 texCoordV;
out vec4 fragcolor;

void main()
{
	fragcolor = texelFetch(entitySheet, ivec3(texCoordV.xyz), 0);
}

Really doesn't get any simpler than that!

So, what now?

Rewriting the entity shader was just the first step, but it was probably the longest and most impactful change. I used the same techniques to dynamically create quads for everything except tiles, such as UI elements and text as well. It was a long learning process but the results were immediately apparent. I now get a consistent 300fps (when v-sync is disabled of course), even on the slow integrated graphics. Now that I don't have any concerns with the performance of rendering, I am happy to be able to move back onto working on game content and assets instead.

+

Cooperative Advancements 1.15.2 & 1.16.5

Posted on February 3, 2021February 15, 2021 by Grend

It was recently requested of me to update my Minecraft mod Cooperative Advancements to version 1.15.2, which actually surprised me a bit--I didn't think anyone really used the mod. I hadn't touched that code since I originally wrote it, and I found that there was a bit of a painful re-learning process to get it to build. I had to wrangle lots of different error messages (I prefer using Visual Studio Code, which still is not fully supported by Forge to this day), but I eventually got the mod building properly in it's original state. After that point it was smooth sailing porting it to both 1.15.2 and 1.16.5.

I wrote the mod originally for personal usage in custom mod packs, where there were huge collections of advancements that are daunting alone but make for a fun cooperative experience once you can work together with friends to work at them. For those of you reading that use the mod, I hope you enjoy using it in more modern Minecraft modpacks! Check out the new versions at CurseForge here.

+

Updates and More

Posted on July 19, 2020February 15, 2021 by Grend

Progress is still coming along steadily in the still-(officially)unnamed game I have been spending most of my free time working on. I have a lot of details fleshed out (in planning) about the world, including locations, characters, story elements, items, and more with the game itself coming along nicely. Many of the main parts of the game's engine are functional, though there is still work to be done and a lot of content to be added.

I haven't shared many details about the game anywhere yet, but it is a game that starts with you moving to a new town full of unique people. These people hold some strange traditions and can be reticent or abrasive, but it's best not to judge them based on first impressions. Everyone has a past. It's up to you to get to know these people, and perhaps improve the town and the lives of your fellow residents. How you go about accomplishing that is something I will dive into deeper in the future. The game is made in the style of SNES-era 16-bit games, with some modern game features and influences. It has role-playing and adventure elements, as well as multiple storylines. I hope to give the player a feeling of importance, with clear progression over time, not just progression of the player's character, but of the whole game world.

I was encouraged to share my development process as I work, and I think it would be cool to have others have an inside look, so I have started occasionally streaming on Twitch as I work on the game. You can watch it here, I am going to try to stream at least once a week, with the most likely day being Saturday. I will be streaming some of the more interesting parts of my development process, such as coding, creating art assets, and more, but I will try to keep things like story details and secrets out of the stream.

+

A Quick Update

Posted on January 8, 2020February 15, 2021 by Grend

Happy new year! I'm just posting to give a quick update on the game I mentioned a while back, one that I had been planning off and on for over a year. I have moved on from the planning stage and actually started working on the game! I have been very busy in my spare time coding a from-scratch custom engine for it, which is coming along nicely, and I now have also started adding assets and game elements.

I have made games in the past, but this time feels different. I am learning a lot, and I am hopeful that this will turn out special. I want to create a world that people will want to sink into and care about, all the while having fun. I don't want to overshare so early, so I'll just leave you with this small teaser. Until next time.

+

Cooperative Advancements

Posted on November 25, 2019February 15, 2021 by Grend

Just a quick update to talk about a small mod I wrote for Minecraft 1.14, Cooperative Advancements.

In my spare time, I have been playing Minecraft with the Valhelsia modpack, but I found that having separate advancement progress between players was a regression from other modpacks I've played in the past. Having multiple players on the server be able to work towards a common goal of completing advancements is pretty fun! In older versions of Minecraft, the Together Forever mod could be used to synchronize advancements, but this mod has not yet been updated to the latest version. I decided to write a quick mod (my first time doing so), that helps share advancement progress for all players on a server. It's seriously simple--took me about an hour to throw together, and you can check it out here, if you're interested.

Currently, the mod simply grants an advancement to each player on the server whenever someone earns one. It also synchronizes all player advancements whenever someone logs in. Currently, it does not synchronize advancement progress between players, but that is a potential future feature.

+

Stampede v0.42 is Live!

Posted on October 28, 2019February 15, 2021 by Grend

Happy (almost) Halloween!

After a long period of testing (thank you testers), the new update for Stampede is live. During this testing period, some very serious bugs were found and fixed, so hopefully the wait was worth it. Some of these bugs may have existed in the game since day one, such as certain Samsung devices falling asleep while playing. It feels good to clean those up!

Grab the new version here!

In the meantime, while waiting for feedback from testers, I have spent my free time working on the new project I mentioned in my last post. Lately, I have actually been studying music a lot, since it is something I would like to create on my own from now on in my games. I don't have a lot of musical background, so wrapping my head around some concepts is a hard task, but I am determined.

Until next time.

+

Stampede 0.42 Update

Posted on October 2, 2019February 15, 2021 by Grend
Something seems different about that pig...

A new update for Stampede is coming soon, which will be version 0.42. This update contains a lot of improvements, basically touching on every aspect of the game. It improves graphics across the board, adds a ton of new sound effects, and even music!

I've added a lot of new game content, such as plants and rocks, and a new infinite final wave for each level. Now, when you beat all 99 standard waves of a level, you unlock "Wave ☆". This special wave is the most difficult, but yields the greatest rewards. This final wave will also have some unique content that you can't experience in any of the previous waves. I also decided I wasn't happy with how bonus waves worked, and so now they are completely different. Instead of randomly occurring, bonus waves will now always occur on certain waves and will include new environmental effects or gameplay mechanics you won't find in normal waves.

In addition to all the obvious improvements, there was a lot of overhauled backend code that may not result in noticeable changes (though the performance on older hardware should have improved). Also, I am now calibrating the accelerometer differently, allowing the game to be played the same from any starting position (in other words, you can play in bed more easily now).

This is the biggest update Stampede has ever had, and I am pretty happy with how it has come together. It should be hitting the Google Play store within the next few days. I'm finally starting to feel like the game is getting fleshed out pretty well, and though there are still a few weak spots, I have decided that this will probably be Stampede's final update. At least for a while.

I am ready to start a new adventure.

I've actually already started developing a new game that I have been dreaming of making for a few years now, and I'd like to shift all of my efforts towards that going forward (if possible). I won't reveal much about it yet, but I will say that unlike Stampede, it is not going to be a mobile game. I'm making a game I want to play. I'm very excited about this new project.

+

Website is up!

Posted on October 1, 2019 by Grend

I've been working on getting this website up and running for a while now, and I think it's finally at a state I am happy with. I am hoping to use this site to mostly document my game development efforts, possibly with a little personal blogging mixed in.

I've currently got the blog set up, as well as a menu with pages for each game I hope to feature on the site. The home page will eventually be fleshed out (I have some plans), but for now I'm just going to leave an ugly "under construction" note.

If you're wondering who I am, my name is Anthony Hilyard. I go by Grend online. I am a software engineer with a great interest in game design. In my free time, I like to make games and some day I hope to be able to do it full-time. As of writing this post, I have released one game (Stampede), and have finished a handful of unreleased ones.

Check back periodically, hopefully there will be something interesting to see. Until then, thanks for reading!

+
MENUMENU
  • Home
  • Games
    • Stampede
    • Cross Section
    • Dunwich
    • Complex
    • Dungeon Defender
  • Mods
    • Minecraft
      • Advancement Plaques
      • Cooperative Advancements
      • Equipment Compare
    • Stardew Valley
      • Improved Tracker
      • Berry Season Reminder
      • Upgradable Pan
      • Weapons on Display
  • Blog
  • Contact