Sign in

Vercidium

@vercidium.com
330 followers 66 following 106 posts

Game engine developer from Australia, I’m keen to share what I’ve learned about optimising games. youtube.com/vercidium

PostsRepliesMedia
Vercidium @vercidium.com · 09/05/2025
store.steampowered.com/app/2800900/...
store.steampowered.com
Rift Riff on Steam
Jump a rift, fight off monsters, plunder their world. A strategic mix of juicy tower loadouts, varied monster behaviors, and forgiving mechanics.
020 2
Vercidium @vercidium.com · 09/05/2025
I was lucky enough to help playtest Rift Riff and I loved it. It releases tomorrow, I’m keen for my third playthrough!
120 2
Vercidium @vercidium.com · 09/05/2025
My life changed when I discovered block select and multiple cursors
010 1
Vercidium @vercidium.com · 26/04/2025
Thank you for sharing!
110 1
Vercidium @vercidium.com · 19/04/2025
Thank you!
110 1
Vercidium @vercidium.com · 25/01/2025
This looks incredible! I love skyboxes like this
010 1
Vercidium @vercidium.com · 25/01/2025
All of this was rendering incredibly slowly, so I switched to an instanced rendering system. This was also initially buggy, producing some strange images:
The same isometric world as before but everything is grass and all the blocks are the same sizeIsometric view of the world appearing from the void below, but the opacity of each block appears to be randomIsometric view of the world, but only grass is visibleIsometric view of the world, but the wooden buildings are 'cutting' holes into the dirt/grass behind them
030 3
Vercidium @vercidium.com · 25/01/2025
Shadows were finally working, and I also fixed specular lighting
Isometric view of a blocky world with a dirt path, grass, a wooden building and shiny sunlight
120 2
Vercidium @vercidium.com · 25/01/2025
I then enabled shadows. Initially my engine only supported Cascaded shadows, which is overkill for this. I added a new 'Spotlight' shadow system, which only renders the scene to one depth texture. I messed up some OpenGL calls which led to these strange glitches:
Isometric view of the same blocky world with shadows incorrectly darkening each block in a strange patternBirds eye view of the same blocky world with shadows incorrectly darkening each block in a strange pattern, and a huge hole in the middleIsometric view of the same blocky world with shadows nearly applied correctlyIsometric view of the same blocky world with shadows applied in inverse (shadows are brighter)
100 1
Vercidium @vercidium.com · 25/01/2025
I then animated it appearing from the void below. All these blocks were being rendered one at a time, which was very slow! I changed to an instanced rendering system, which brought it up from 48 up to 560 FPS.
The isometric world falling away into the void below, one block at a time
110 1
Vercidium @vercidium.com · 25/01/2025
Started very basic with a smaller world
An isometric world with blocky dirt, grass and a basic wood building
110 1
Vercidium @vercidium.com · 25/01/2025
Here's a sneak peek of the animations for my next YouTube video on Raytraced Audio. I'm using these wooden buildings to highlight issues with classic 'room-based' audio environments. Check out the thread for the making-of:
2202 20
Vercidium @vercidium.com · 19/01/2025
My engine now supports multiple point-shadows Now you can grab a torch and explore the darkness #gamedev
A panoramic shot of a forest, with a wood cabin on the left and a player venturing into the woods on the right. Light is emitting from the cabin and the player
0121 12
Vercidium @vercidium.com · 18/01/2025
Destroying the lootboxes looks so satisfying! Added to my wishlist
120 2
Vercidium @vercidium.com · 18/01/2025
Really starting to think I should turn this into a game 😅 Ready for the new Valheim? #gamedev
A wide shot of a cabin in the woods after sunset, with a dark turquoise sky behind it. The cabin has a nice orange glow coming from inside itAn isometric shot of a cabin in the woods after sunset, with a dark turquoise sky behind it. The cabin has a nice orange glow coming from inside itA long shot of a cabin in the woods after sunset, with a dark turquoise sky behind it. The cabin has a nice orange glow coming from inside it
1110 11
Vercidium @vercidium.com · 18/01/2025
Smaller clovers are darker to create the illusion of depth
A field of green clovers
050 5
Vercidium @vercidium.com · 18/01/2025
Each clover is constructed of 20 vertices and sways in the wind.
140 4
Vercidium @vercidium.com · 18/01/2025
It's not realistic but they also look great underwater. I'll definitely need to add some underwater vegetation next
Fallen trees poking out of the water, with large clovers underwaterFallen trees poking out of the water, with large clovers underwaterClose up of underwater clovers
100 1
Vercidium @vercidium.com · 18/01/2025
Before and after adding small clovers. Small details like this make the world feel more full and interesting #gamedev
A patch of grass in a forest with no clovers. Looks a bit emptyA patch of grass in a forest with small 4-leaf clovers
1143 14
Vercidium @vercidium.com · 14/01/2025
Wishlisted and signed up for the playtest. Keen to try it out and share my feedback!
010 1
Vercidium @vercidium.com · 14/01/2025
New sunset colours and shadows. Before the world was going completely dark at the same time the sun set, when in reality that doesn't happen until after sunset. #gamedev
0193 19
Vercidium @vercidium.com · 06/01/2025
Hot off the press! Watching now
020 2
Vercidium @vercidium.com · 06/01/2025
Here's another before and after - I love these streaks of light
Before - incorrect shadows applied to a grassy forest at sunsetAfter - correct shadows applied to a grassy forest at sunset
060 6
Vercidium @vercidium.com · 06/01/2025
I fixed grass shadows recently and the difference is night and day. Lighting makes such a difference #gamedev
Before - incorrect shadows applied to a grassy landscape at sunsetAfter - correct shadows applied to a grassy landscape at sunset
2181 18
Vercidium @vercidium.com · 23/12/2024
Here's another mind bending animation about how 3D rendering works (it's all an illusion) I talk about it more in this free article: www.patreon.com/posts/118330... #gamedev
0141 14
Vercidium @vercidium.com · 07/12/2024
Performance is decent, the whole bloom process takes 0.4ms on a 3440x1440px screen with my RTX 3070. Using a forward renderer (no more deferred rendering!) and the improved shadows from my last post, I’m at around 370 FPS on average
Image of the NVIDIA performance overlay, showing 373 FPS, 232 99% FPS, 7.8ms render latency, 13% CPU and 91% GOU utilisation
020 2
Vercidium @vercidium.com · 07/12/2024
I love the soft glow effect it has on these metal textures:
An isometric image of a yellow forklift with no bloom applied. On the left are the 8 bloom textures, each of which are half the resolution of the lastAn isometric image of a yellow forklift with 10% bloom applied. On the left are the 8 bloom textures, each of which are half the resolution of the lastAn isometric image of a yellow forklift with 100% bloom applied (my eyes!!). On the left are the 8 bloom textures, each of which are half the resolution of the last
100 1
Vercidium @vercidium.com · 07/12/2024
Previously I used separate gColour and gBloom buffers and only wrote to gBloom if I wanted bloom applied to that part of the screen. I changed it to use one HDR gColour buffer like in this article: learnopengl.com/Guest-Articl...
An isometric image of a game level with no bloom applied. On the left are the 8 bloom textures, each of which are half the resolution of the lastAn isometric image of a game level with 10% bloom applied. On the left are the 8 bloom textures, each of which are half the resolution of the lastAn isometric image of a game level with 100% bloom applied (ow my eyes). On the left are the 8 bloom textures, each of which are half the resolution of the last
110 1
Vercidium @vercidium.com · 07/12/2024
Check out these bloom effects It uses a HDR colour buffer, which can store colours greater than 255. If a colour is 300 or brighter, it is extracted into a separate buffer, then downsampled 8 times and upsampled 8 times When applied to the scene at 10% strength, metal surfaces are nice and shiny:
291 9
Vercidium @vercidium.com · 07/12/2024
Thank you for the explanation! For a voxel map it would work great, as the shadows only need to update when the map changes. Player + particles change every frame so I would update their shadows every frame. Found this great writeup too: www.reddit.com/r/GraphicsPr...
reddit.com
From the GraphicsProgramming community on Reddit: WIP Sparse Virtual Shadowmapping (with tech writeup!)
Explore this post and more from the GraphicsProgramming community
010 1
Vercidium @vercidium.com · 07/12/2024
Tell me more 👀 I’m ready for the next step!
110 1
Vercidium @vercidium.com · 06/12/2024
After spending 7 years learning OpenGL, I finally have stable shadows. No more flickering! Shadows and clip/light/view space have always confused me. And they still do. #gamedev
1152 15
Vercidium @vercidium.com · 02/12/2024
Block select is so useful. Use Shift + Alt to select multiple lines, then Home, End and Ctrl + Arrow Keys to navigate left and right. This refactor would take so long without it! #gamedev
191 9
Vercidium @vercidium.com · 02/12/2024
The TextureUnitHelper just keeps track of a counter that resets when a shader is bound, to ensure two different textures / sampler types aren't using the same texture unit. Bindless textures would also solve this, but I'd like to maintain support for older GPUs
A C# class with the following code:

public static class TextureUnitHelper
{
    static int TextureBinding = 0;

    public static int GetAvailableTextureUnit() => TextureBinding++;

    public static void OnShaderBound()
    {
        TextureBinding = 0;
    }
}
020 2
Vercidium @vercidium.com · 02/12/2024
The best change is that textures are now bound at the same time uniforms are set. This uniform class is the only time that glActiveTexture is called, which means uniforms and textures will never be out of sync.
A C# class with the following code:

public abstract class ShaderUniformSamplerBase(string name) : ShaderUniform(name)
{
    protected TextureTarget target;

    public override void ResetCache()
    {
        lastUnit = -1;
    }

    public int lastUnit = -1;

    public void Set(uint handle)
    {
        AssertActive();

        var unit = TextureUnitHelper.GetAvailableTextureUnit();

        Gl.ActiveTexture(TextureUnit.Texture0 + unit);
        Gl.BindTexture(target, handle);

        if (unit == lastUnit)
            return;

        Gl.Uniform1(location, unit);
        lastUnit = unit;
    }
}
120 2
Vercidium @vercidium.com · 02/12/2024
So I changed ShaderUniform to be an abstract class, with multiple ShaderUniform<Type> classes that inherit from it. To define uniforms for a shader, I can now call AddUInt(...), AddFloat(...), etc:
A C# class with the following code:

public unsafe class ShaderUniformFloat(string name) : ShaderUniform(name)
{
    public override void ResetCache()
    {
        last = 0;
    }

    public override string Type => "float";

    public float last;
    public void Set(double v) => Set((float)v);
    public void Set(float v)
    {
        AssertActive();

        if (v == last)
            return;

        Gl.Uniform1(location, v);
        last = v;
    }
}A C# class with the following code:

public class AnimatedUniforms : ShaderUniformHelper
{
    public AnimatedUniforms() : base("")
    {
        data = AddUInt("data");
        renderDistance = AddFloat("renderDistance");
        mvp = AddMat4("mvp");
        objectMat = AddMat4("objectMat");
    }

    public ShaderUniformUInt data;
    public ShaderUniformFloat renderDistance;
    public ShaderUniformMat4 mvp;
    public ShaderUniformMat4 objectMat;
}
100 1
Vercidium @vercidium.com · 02/12/2024
I previously had a ShaderUniform class which was used to set a value on a uniform in a shader. It had functions like SetInt, SetVec3, SetMat4, etc. However this meant I could call SetMat4 on an integer uniform, and it won't throw an error.
100 1
Vercidium @vercidium.com · 02/12/2024
Hundreds of errors in Visual Studio, we meet again! After refactoring shaders to support hot reloading (which is awesome) I realised the way textures were bound to shaders wasn't great. So now, I'm refactoring shaders... again...
A list of 800 errors in Visual Studio
180 8
Vercidium @vercidium.com · 01/12/2024
Shader Hot Reloading is working! If the current shader string is different to the last, the shader gets recreated and its uniforms are reconnected. Also if the shader string is invalid (e.g. syntax error), it will revert to the last working shader. #gamedev
0192 19
Vercidium @vercidium.com · 30/11/2024
I'm also looking back at some old code and thinking "what was I thinking!?" There's so much room for optimisation here. I'm keen to run some benchmarks post- and pre-refactor
040 4
Vercidium @vercidium.com · 30/11/2024
The shader refactor is complete and the project is building again. Now it's time to fix all the runtime bugs 😅 The codebase is much leaner though: 157 files changed 4860 insertions 8485 deletions Net: 3625 lines deleted #gamedev
1150 15
Vercidium @vercidium.com · 29/11/2024
Thank you for sharing, that is very concise! I like it, I’ll try it out
000 0
Vercidium @vercidium.com · 29/11/2024
Oooh I see. I’ll check out HLSL, thank you!
000 0
Vercidium @vercidium.com · 29/11/2024
My goal is to reduce the amount of manual ‘management’ work - e.g. ensuring uniforms/varyings have the same names across shaders and code - so that shaders don’t break so easily when working on them
100 1
Vercidium @vercidium.com · 29/11/2024
I started learning Vulkan the other day and having to compile my shaders down to SPIRV is a hassle 😅 I’ll need to add a pre-build step that does it automatically for me
200 2
Vercidium @vercidium.com · 29/11/2024
So far this refactor has removed 2000 lines of code, and means shaders are more enjoyable to work on!
010 1
Vercidium @vercidium.com · 29/11/2024
Varying are also defined in one place now and are appended to both fragment and vertex shader strings (‘in’ is replaced with ‘out’ for the vertex shader).
110 1
Vercidium @vercidium.com · 29/11/2024
So I’ve created a ShaderUniformHelper class that has AddFragment(…) and AddVertex(…) functions, which appends the uniforms to the top of the shader string. Now all the uniforms for one shader are defined in one place.
100 1
Vercidium @vercidium.com · 29/11/2024
Previously I was defining uniform names in 3 places (C# variable name, C# string parameter, and in the fragment/vertex shader) With hundreds of shaders and over 1000 uniforms, this duplication adds up!
100 1
Vercidium @vercidium.com · 29/11/2024
Working on a huge shader refactor today, with the goal of being able to hot reload shaders. Each shader used to be two large strings (one for the fragment shader and one for the vertex shader), but now they are constructed from these 5 strings. This keeps uniform and varying names consistent too!
A screenshot of a GLSL shader helper class, written in C#
390 9