Using Compute Shaders in Unity to Create a Basic Raycaster – Part 2: Sprites!

Hello Internet,

I have continued work on my raycaster.

First I fixed an issue I was seeing where walls towards the edge of the screen were not being drawn tall enough resulting in this odd bubbly look.

This was due to me using the distance that wall was from my camera. This seemed like the right thing to do, but the correct distance is that distance multiplied by cos(theta) where theta is the angle between the camera’s direction and the ray being cast (I’ve had to pull the trig book out a couple times during this project) I actually found a nice way to calculate the correct distance to avoid doing any trig functions in my shader.

Next on the list were sprites. I was debating on wether or not this should be done cpu side or in the compute shader. Seeing as this whole exercise was for me to get a grasp on compute shaders I decided I’d at least try to do this in the shader; I’m glad I went this route.

My first attempt was a fail. I spawned just a single thread per sprite. Then calculated the chunk of screen that needed to be written to and iterated over all those pixels to draw it. This worked fine if the sprite was far away and the amount of screen it took up was small, but once the sprite took up over half the screen my game was slowed to a crawl. I addressed this by spawning several threads (one for each pixel) per sprite and did the same calculations, but instead of iterating over a large chunk of pixels I only drew the pixel the current thread was dealing with.

This was a huge performance boost as now I could draw several hundred sprites at a time without seeing any changes to the frame rate. Knowing how to group your threads and adjust your algorithm accordingly helps a huge deal when writing compute shaders.

Then for fun I added a post process effect I found here, https://www.shadertoy.com/view/XsjSzR, to give a more retro look.

Enjoy a video of the ray caster in it’s current state. I loaded up the scene with sprites just as a little stress test.

If you’re wondering how I’m sorting the sprites… I’m not. I created a Structured Buffer of uints to act as my depth buffer and just do a depth check before I draw each pixel.

Next on the list is doors, animated sprites, and maybe the secret push walls you find in Wolfenstein 3D.

Until Next Time,
Alex Gilbert

Leave a Reply

Your email address will not be published. Required fields are marked *