mercoledì 10 gennaio 2018

Day 219: Small improvements

Today I fixed a problem with frustum culling. The perspective divide was not accounting for negative w, and that was causing some incorrect culling in certain situations.

I also offloaded some calculations (batches constructions) to another thread, in order to improve CPU performance.

martedì 9 gennaio 2018

Day 218: Frustum Culling

Today I implemented something that I was supposed to do a long time ago, frustum culling.
When I first started developing the engine I had a limited knowledge in 3D geometry, so I never implemented it because I didn't want to blindly copy an implementation.
Now that I improved on that side, I decided to tackle the problem, and it was pretty easy to get it to work.

First thing, I added to each mesh an AABB that gets created once at load time.

Then I proceeded to add a frustum test that, if failed, disables the geometry rendering (not the shadows though, because their contribute needs to be there even if the caster object isn't).

The implementation of the AABB - frustum intersection test uses NDC space. I realized that its much cleaner to convert the AABB to NDC and test the vertices against simple boundaries (-1 and 1 along the three axes), rather than doing more complex plane intersections in world space. I didn't look for it online, but I bet this is the way it is done.

In the picture you can see a part of the Sponza scene rendered with 67 draw calls, instead of the usual ~390.


venerdì 22 dicembre 2017

Day 217: Dithering transparency

Today I decided to implement a nice little effect I often notice in games, which is that sort of dithering pattern that is gradually replacing transparency in new games. For example, Mario Odissey exclusively use it throughout the game.

The reasons for its use are mainly to be found in performance, as the dithering pattern drastically reduces the overdraw, and also for its support of deferred rendering. Personally, I even find it more pleasing to the eye than transparency in some situations (i.e. an object disappearing with camera occlusion).

I implemented it by sampling a dither texture, and tiling sections of it across the screen, depending on the alpha value. For the alpha, I added an alpha attribute to the shaders, as well as finally adding support for opacity textures, which I somehow had never done before.

In the picture you can see:

- proper opacity support for the leaves, with some dithering effect around the edges
- the dithering pattern, which I increased with depth just for the sake of this picture, while normally it uses alpha


mercoledì 6 dicembre 2017

Day 216: Small improvements

Today I cleaned and improved some of the batches classes, especially the Font one, which was slower than necessary.
I'm also starting to plan a substantial refactor of the engine, in order to remove the need for batching and sorting in case of materials that do not benefit from instancing. I'm still trying to find a clean way to do it before starting to work on it.

martedì 5 dicembre 2017

Day 215: Improved Shell and Log

Today I decided to clean the engine a bit, and improve some of the debugging tools, which is always a good long-term investment.

First, I decided to add a small Stat window that constantly shows some of the most important performance data. FPS and draw calls are the most important ones for sure, and the reason I made the system in the first place, but other useful data can be occasionally shown.

I also modified the command parser for the shell, as it still consisted in an ugly chain of ifs, and I never had time to improve it. I created a map of lambda functions, and the command is used to access the map and call the corresponding function. The lambdas also return a string containing an hint about what the command does, and the new "help" command uses this fact to produce helpful messages.

I also fixed some bugs in the scene system and in the material class, and I plan to refactor them a bit more in the future.


lunedì 4 dicembre 2017

Day 214: Optimized and integrated SSAO

Today I decided to improve SSAO, and to integrate it into the pipeline of the engine. This required a few steps:

1) Move the SSAO shader to the engine code, and make it independent from the post processor, so that it can be used withing the deferred rendering pipeline

2) Instead of using the results directly, store a low-precision single-channel texture in the G-Buffer (actually 2, because of step 3).

3) Create 2 shaders to apply vertical and horizontal blur. They alternatively use the two occlusion textures.

4) Apply the results only to ambient light in the directional light shaders.

As you can see from the picture, the bilateral filtering makes the noise go away quite well, and finally the "shadows" look like shadows. On top of that, applying the results only to ambient light makes the effect much nicer when other lights interact with it.


giovedì 30 novembre 2017

Day 213: SSAO

Today I finished implementing SSAO. The result is messier than expected, with a lot of visible noise. I knew I had to expect noise between pixels, but I at least hoped that pixels close to each other would behave similarly, making noise softer on the eye.

Also, I realized that SSAO should be applied only to ambient light, or at least have different weights, and only influence diffuse light in a small amount.

That being said, the steps required to have a proper, functional implementation of SSAO seem to be:

1) Blur the result to soften the noise
2) Feed the texture to the lighting calculations, so that the right amount of AO can be applied properly.

I'm not sure I'll go ahead with the implementation, as it requires some big changes to the pipeline, and I really just wanted to test the post processor. But I might change my mind in the future, as the graphics pipeline evolves.

In the picture, you can see the AO factor buffer on the top, and the result applied to the image on the bottom (particularly visible near corners and edges).