Projects Jams Discord News
Resources
Unwind Fishbowls Forums
About
Manifesto Our values About
Log In

Engine Work: DDGI Light Probe Depth Data Compression

Chen August 2, 2020

Continuing from last post, DDGI requires a high amount of memory to store its depth maps. I present a compression scheme that compresses the data to 5~10% of its original size. Note this is completely orthogonal to BC texture compression or any bit-saving tricks, so this compression ratio can be improved further with those existing techniques.

Memory Constraint

For DDGI to work effectively, we need a 16x16 depth map attached to each probe, with each texel storing both depth and depth^2. If we use R16G16 to store each texel, then that would give us 1KB per probe, not counting the gutter padding.

Let’s say we have a generous budget of 1GB for light probes, and we have a 200x200x50 meter^3 world. Placing probes one meter apart, we would need 2 million probes, which will take up 1.9G. So a dumb uniform distribution of probes won’t cut it.

A smarter wa

Read more

Engine Work: Global Illumination with Irradiance Probes

Chen April 21, 2020

Global illumination is one key effect I want to achieve with Monter. For a low-poly style game, GI is an important effect that gives the fidelity, which the low-poly game asset itself lacks. I’ve attempted to achieve this effect with irradiance probes, drawing ideas from both DDGI for probe interpolation and Remedy’s GI talk for optimal probe placement.

Global Illumination with Irradiance Probes

Before light probes, Monter used a constant term for indirect illumination, so that surfaces in shadow are not completely dark. It doesn’t account for indirect illumination or skylight illumination, which are key elements to producing realistic lighting. So I am aiming to finally bring global illumination into this game with the help of irradiance probes.

[I]flat ambient term, looks

Read more

Enable Ray Tracing: Ray Traversal

Chen April 8, 2020

Last time I covered the design of acceleration structure (AS) for my game engine’s ray tracing system. This time, I will go into depth on how ray traversal is done with such an AS. As I go on to describe how ray traversal is done, it should become much clearer on why the AS is designed this way.

In a traditional ray tracer, all you have to do is to build an AS over some static geometry during startup, and for the rest of the program, you just keep tracing some rays through the AS. That part is well-covered in literatures such as Physically Based Rendering, but it becomes messier when we bring ray tracing to real-time games.

Rigid Body Transformation

The first obstacle is to track rigid body transformations. Building BVH over a mesh is an expensive operation, so we only do it on startup time. Transforming the mesh then would invalidate the BVH we’ve buil

Read more

Enable Ray Tracing: Two-Level Acceleration Structure

Chen March 16, 2020

I started doing some work to add a GPU ray tracing system to my engine. I want to experiment and see what sort of effects can be enabled on current gen GPUS, even without special hardware support. And of course, before we can shoot some rays, we need an acceleration structure (AS) for all the geometries in the scene. There are some popular ones, such as BVH (which also happens to by my choice of AS in this case). However, it remains an issue as to how to efficiently maintain AS for a highly dynamic scene like Monter’s, with animatable meshes and dynamic geometries.

Problem Statement

I want high quality BVH for fastest ray tracing possible, so I rolled with a SAH-based top-down BVH builder. Despite producing high quality BVHs, it has two problems: it is slow, and it can’t run on the GPU.

Instead of trying to come up with some fancy GPU builder that w

Read more

Engine Optimization: Fast High-Quality Cloudscape through Noise and Reprojection

Chen February 18, 2020

Hey guys, it’s been a long time. This time I want to share an optimization I did with my volumetric cloud. Here is the procedural volumetric cloudscape article that contains my initial implementation. In this post, we are going to expand upon that, and introduce techniques that would make things go fast without loss of quality.

Where we left off

As you can recall, our volumetric cloud solution was quite expensive. To run at a decent quality at 1080p, it was taking about 10~30ms on a GTX 1060 card, definitely over the frame budget.

There were two dimensions to our cost. One is the number of rays we are shooting, corresponds to the size of our shader output. The other dimension is sample count, which determines the fidelity of our cloud. Both of these need to be pretty high to achieve nice quality.

In the end of the last post, I ended up doing this cloud

Read more

Engine Work: Collision Wrap-up

Chen December 28, 2018

Hey guys, sorry for the inactivity. I have been making steady progress on Monter over the past couple of months, but couldn’t find any time to do a writeup about it. I try to make these writeups as high quality as possible, so I was reluctant to publish any article that just glosses over the details. And now I finally have the time to do another writeup on Monter. There’s a lot of stuff to cover, such as the new grass system, terrain system, and water shader. But for this post, let’s first wrap up the collision system that I promised months ago.

I’ve covered the theory of GJK in the last post, but there are a couple of implementation details that’s worth noting.

Optimizing GJK: support function

Recall that, in each iteration of GJK, we must need something called a support function. The support function’s job is to find the vertex that’s the furthest along the search direction. We could implement it with a simple linear search, but that means O(N) at each i

Read more

Engine Work: Procedural Volumetric Cloud Rendering

Chen August 10, 2018

Hi all. I know I owe you a followup blog post to the collision system, but I decided it’s best to write about the recent procedural cloud render I did while it is still fresh in my head. Here are a couple of screenshots:

(you might have noticed I added grass. A blog post on that will be out soon)

Before we get started, I just want to clearly state that this is not based on any physical equations whatsoever. This result is solely obtained by experimenting with various mathematical equations with a weak physical basis; the “look” of the cloud is the only emphasis here, not correctness.

Goals

The goals I aim for when started writing the volumetric cloud rendering are the following:

. Simplicity: I want the entire cloud render to just be a single shader pass. . Procedural: Generated geometry, for that it is easy to animate and has unlimited resolution. . Volumetric

Read more

Engine Work: GJK-based Collision Detection & Response

Chen July 9, 2018

For some reason, information on collision detection & response is quite sparse compared to all the other subjects. Worse yet, there are some bad information out there that are praised to be good resources. Pieces of information are also often discoherent, such as resources on collision detection says nothing about collision response and vice versa. It took me a while to find good information on this subject, and I have finally implemented a working collision system that works reasonably well for games.

A new collision object representation This time, I chose convex polyhedrons to be the collision representation for the small objects in my game, such as trees, rocks, and so on. Concave objects, such as houses, are broken down into convex polyhedrons. I am aware of some of the convex decomposition techniques, but I didn’t want to do them, as I think that would take too much time. Instead, I manually decompose concave mesh into convex polyhedrons in Blender.

As for terrai

Read more

I'm back!

Chen July 2, 2018

Hi all! Sorry for the inactivity. School got in the way and I wasn't able to work on Monter much in the past three months and therefore hasn't posted any new progress. But now with school out of the way, I can finally come back and work on Monter again. So, expect new updates on the reworked collision system very soon!

Read more

Numerical Robustness and New Approach

Chen April 1, 2018

Thanks to the debugging system from last post, I was able to pinpoint the bugs fairly quickly. However, as I tweak the algorithm to improve its numerical robustness, it becomes obvious that the problem is not as simple as just making the algorithm robust. In order to elaborate my concern and problem, here’s a review of the main algorithm.

Recap of Faurby’s As I have stated in my previous posts, the current collision system is based on Faurby’s paper, which is really just a simple swept sphere vs triangle mesh collision detection & response routine. Here’s a pseudo-code version:

[code]

vec3 move_sphere(vec3 sphere_p, float sphere_r, vec3 vel) {

Triangle_Array mesh = get_scene_static_mesh();

// NOTE(chen):contact_p is initial contact point of swept sphere against mesh // t is the normalized time of impact used to modulate vel vec3 contact_p, float t = try_move_sphere(sphere_p, sphere_r, vel, mesh);

vec3 legal_vel = vel * t;

Read more

Engine Work: Collision Debug System

Chen March 25, 2018

The collision system is one of the areas worth investing time into to get rid of all the bugs and ensure it’s 100% robust. However, it is not trivial to do that. I can test it by walking the character all over the map, but that’s a lot of manual work and it is extremely likely many cases will not be caught. Furthermore, this method of testing only confirms whether or not my collision is bugged, but doesn’t help me answer why the bug occurs or how to fix it. Once the character is stuck, I lose the information of the input that triggered it. In addition, the same exhausting test will have to be applied every time I make an adjustment to the collision system. This makes a debug infrastructure that automatically tests and records the collision system very desirable.

Rapidly Exploring Random Trees

Thanks to Casey’s blog, I have discovered Rapidly Exploring Random Trees, an algorithm that’s very useful in this case. It is an algorithm that randomly expands a tree out

Read more

Collision System Part 2: Sparse Hash-Based Grid Partitioning, Multithreading, and Future

Chen March 10, 2018

What happened last time … performance issues

So we got collision working, but its performance is unacceptable. If I load the entire world geometry up as collision mesh, the collision routine would take up to about 100ms to process per frame, that’s insane!

One well-known technique that helps with performance is spatial partitioning. As its name implies, a spatial partitioning algorithm takes a bunch of geometries and groups them in terms of vicinity. When geometry needs to be queried for collision detection, we can only pick out the geometries that are close enough to our moving character and ignore the rest.

There are a lot of choices: octree, kd-tree, etc. I chose to go with a uniform grid, since it seems to be the easiest to implement.

Grid storage problem & wasted space

In order to partition the entire world geometry, the grid must be big enough to contain all of it. And each grid cell holds all the polygons that overlaps with that cell. To generat

Read more

Collision System Part 1: Collision Detection and Response Against Static Mesh

Chen February 17, 2018

In this post I will be discussing the collision algorithm I used to handle interaction between the player and his surroundings. It is based on Fauerby’s paper.

I really struggled to find good resources on collision detection and collision response so hopefully my post can serve as somewhat of a starting point if you want to implement your own collision system.

Collision object representation

When you render a game scene, almost all the objects are represented by a triangle meshes. They help provide fine-grained details that you see on the screen. However, they aren’t always the best candidates to represent objects in a collision algorithm due to performance implications. Even when they are used, there are strict requirements on what type of mesh they have to be; maybe they have to be convex or have a low polygon count for the algorithm to work well. It is much more common to use a simple primitive sh

Read more

Engine Work: Sky shading pass

Chen January 14, 2018

Hi everyone. For the past couple of weeks I have been mostly working on Monter’s movement system, but it’s still heavily WIP so I can’t write about it just yet. What I did finish though is a simple sky shading pass. It turned out quite nice because it gels well with Monter’s simple low-poly art style. So I’m going to write about that instead.

Considering how to draw a sky

Skybox has been a popular choice for many years. It’s a technique that packs the pre-rendered skydome into a cubemap, which is a texture with six faces. A cube geometry is then passed to the renderer with the cubemap texture on.

However, most skybox images on the internet go for the realistic look, which is still pretty crappy. Viewers can easily tell they are fake because they are static images. Since Monter is going for a minimalistic look, I decided to render sky procedurally; a simple hemispherical gradient will do.

Setting it up

So instead of having some sort of preset g

Read more

Engine work: Light transmittance and memory management

Chen December 24, 2017

Hi folks, it’s been a while since my last update. Unfortunately school got in the way so my progress on Monter stagnated a bit, but I was still able to put work into it. A terrain walking system has always been my next big goal, but there were still missing pieces here and there. So I spent the past week patching them up. And after this blog post, I will finally start to work on the terrain walking system.

Light transmittance in air

The only reason we can see anything at all is thanks to light. Light sources first emit light and some of the light hit some surfaces. The surface partially absorbs the light, and reflects the rest of the light in some direction. Eventually, some of the reflected light reaches our eyes, giving us the information we need to piece together an image in our brain.

It’s easy to think that light travel without energy loss. That is mostly true if the light travels in vacuum, but if I am simulating an earth-like world, I have to consider the a

Read more

Debugging Cascaded Shadow Map

Chen December 2, 2017

I want to try something different for this post. Rather than just a boring rundown of the technology I implemented, I am going to write about how I approached at solving a bug in my shadow system. I think this post is a lot more down to earth than the other ones and I hope you will enjoy it.

Cascaded Shadow Map(CSM) bug

Alright, just when I want to take a shot from a different angle to show off my new assets, my shadow map broke. You can clearly see the huge gap in shadow on the right of this screenshot here: From the look of it, it seems to be a problem with how my cascade volumes are getting computed. The first thing to do is stepping through the code that calculates the cascade map volumes. Well, the values look right until they get multiplied with a bunch of other matrices and turned into some numbers that are hard to reasoned with.

Debugging the CSM

In situations like these, a graphical debugger is priceless.

Read more

Progress Report: Shadow and Editor Improvements

Chen December 2, 2017

Hi folks. I will talk about the progress I’ve made since last time and how the blog post style will be changed.

Less Emphasis on the Well-covered Subjects on the Internet

When I read my own posts from the past, I noticed they have a lot of duplicate info with popular tutorials out there. So in the future posts, I will minimize the effort I spend on talking about popular subjects and talk more about the unspoken quarks and side-effect of them.

Shadow Improvement

If the player’s PC can’t handle high resolution shadow map texture, then alias will occur on the edges of the shadow, which is not good. One way to deal with the jagged shadow edges is PCF. It blurs shadow’s edges by sampling neighbor texels’ depth test results and blend them together. The way I am blending is to precompute some poisson disk samples, then for each pixel that I’m testing against, rotate the disk by a random amount, then use that disk to sample the neighbor texels.

Resul

Read more

Game Engine Review: Shader Managment

Chen November 28, 2017

Hi everyone. This is post is just me picking up where I left off from last blog post, so it's gonna be a short one.

It is often the case that temporary shaders are written for debugging purposes and need to be added and removed frequently. Same for merging shaders to speed up rendering and splitting shaders for more reusability. If we just build shaders separately and store them in their own files, managing those files and editing the code that build and store the shaders become an unpleasant hassle very quickly. Unable to bear this chore, I set out to resolve this issue.

Runtime Uber Shader

My first approach to this rising problem is using a runtime uber shader. Runtime uber shader is a shader that contains all the shader subroutines. Instead of binding different shaders by calling glUseProgram() for different operations, I permanently bind the uber shader and some kind of flag is uploaded to this shader to change which routine of it is executed.

An example uber sh

Read more

Game Engine Review: Rendering Pipeline

Chen November 17, 2017

As promised, I will be a doing a full review of the game engine in its current state. This blog is dedicated to the renderer in my game engine. I will provide you with a high-level overview, how the renderer came about, and some interesting implementation details.

Overview

Like every other game, Monter’s rendering pipeline is not just a simple draw call. It involves precomputing textures such as shadow maps and ambient occlusion textures to help enrich the visual scene when the actual rendering starts. It also has a post-processing stack which helps smooth out the jagged edges and emulates color bleeding from bright surfaces. Each pass, except shadow mapping, will be discussed in detail in the following sections.

Shadow Map Pass

This pass has already been covered by my first blog, so I won’t be explaining it in detail. All it

Read more

Progress Report: Shadow Mapping

Chen November 12, 2017

Hi everyone. It’s an honor to be featured by handmade network. I will be pushing out blogs where I talk about the challenges I face during Monter’s development. I’ve been thinking long and hard about what to write about on a first blog. The best choice seems to be writing a review of what I’ve done for the game engine so far, but I’ve just finished shadow mapping, so I decided to go with it this time because it’s still fresh. A review of the entire engine will probably be the topic of my second blog, so stay tuned.

Shadow in Real Time Rendering

The cleanest way to do shadow, which is done in most ray tracers, is raycasting against light casters. When computing radiance from a surface point to the screen, a ray is cast from the surface point to the light caster, and if it’s obstructed by any shadow occluders, the surface point is shadowed. However, testing rays against meshes made of polygons is expensive. That process can be accelerated by kd trees and such,

Read more