Sign in

iiinova is part of the Atmosphere — an open, public network where you own your identity.

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 · 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
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
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 · 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
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
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
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
Vercidium @vercidium.com · 28/11/2024
Why can you hear sounds above + below you in games, when your headphones only have speakers on the left + right?
291 9
Vercidium @vercidium.com · 27/11/2024
Final animation with the new triangulation effect. Love the way the headphones appear
151 5
Vercidium @vercidium.com · 27/11/2024
2nd and 3rd attempt. Next step is to blend them into the background colour
A low poly man with the top half split into white trianglesA low poly man with the bottom half split into white triangles
110 1
Vercidium @vercidium.com · 27/11/2024
Fixed it. Thank you @sandwich247.bsky.social for the idea!
040 4
Vercidium @vercidium.com · 27/11/2024
The culprit: t-pose man
140 4
Vercidium @vercidium.com · 27/11/2024
For every polished animation, there are countless attempts that didn't work 😅 #gamedev
1141 14
Vercidium @vercidium.com · 27/11/2024
1st attempt, glitched out a bit but looks cool
110 1
Vercidium @vercidium.com · 27/11/2024
What do you think of these "Dissolving Triangle" animations? I'd like the triangles to change to a wireframe view first, and then subtly shrink + fade out
480 8
Vercidium @vercidium.com · 26/11/2024
And lastly here's an enclosed room where no rays can escape
020 2
Vercidium @vercidium.com · 26/11/2024
Here's an indoor corridor example
120 2
Vercidium @vercidium.com · 26/11/2024
Here's another angle from the ground
110 1
Vercidium @vercidium.com · 26/11/2024
Check out these raytraced audio animations - White lines are the rays cast outwards from the player - Blue lines are the reverb rays returning to the player - Yellow lines are the rays that have discovered a sound source #gamedev
1152 15
Vercidium @vercidium.com · 25/11/2024
I revisited my low poly renderer to fix some bugs, then stayed for a while to appreciate golden hour
193 9
Vercidium @vercidium.com · 24/11/2024
I'm a game dev from Australia and I specialise in optimisation and 3D rendering. I spent 7 years creating a game engine, and now I'm teaching what I've learned over at youtube.com/vercidium I also write free blog posts at patreon.com/vercidium and I'm keen to start writing here on Bluesky too
A GIF of a 2D terrain heightmap being broken down into a grid of triangle strips, then down to its basic component: a single triangleA GIF of a graphics card appearing from thin air, with the fans spinningA GIF demonstrating how pixels are copied from the CPU to the graphics card, using the OpenGL functions glGenTexture and glTexImage2D
2141 14