Less bullshit… More code!

The word “bullshit” is probably an exaggeration, although I honestly dislike it like everyone else does ( At least to my understanding ). What I’m talking about is the glorious exams, not university exams just regular high school exams. But that part is over now, and I’m more or less satisfied with the result. Now, since that part is over, I got lots of time to code and stuff…

Just since the beginning of the exams to now, I’ve been rewriting my engine. And got pretty much everything implemented. The performance was the main goal. The previous version of my engine ran at ~100 fps at half of the screen resolution, the newely written engine runs at ~120 fps at full HD resolution (i.e. 1920 x 1080). Now this is a big thing because I’ve got a lot of post processing effects that really torture the gpu bandwith, such as volumetric scattering, so the resolution seriously affects the frame time. And together with that the architecture of the new system is seriously better together with the new material system that I wrote about in my last entry ( It has been upgraded a bit from that point )

There’s still lots of small optimizations to do, and still lots of unfinished “new” features. But one of the main things I changed is the way my voxelization system works. Every single time a new mesh/object/whateverpeoplecallit has been added the scene the mesh is voxelized without any transformation applied to a “cache” buffer, this cache buffer is added to some list of a sort. Then there’s the main cache buffer that represents the final voxel structure around the camera. So each frame ( through a compute shader ) all voxel caches are iterated through, then each cell of the caches are first transformed by the current transformation matrix of the mesh ( As each cache represents a mesh without any transformations ) and then fitted inside the main voxel cache ( With some magic stuff that speeds this up ). The awesome thing about this is that every single time the camera is moved / the mesh is moved, scaled or even rotated there no need to revoxelize the mesh at all ( Less frame time, yay ).

Although I chose to disable screen space reflections as IMHO there were too many artifacts which were too noticeable. So in the meantime I have a secret next gen way to perform pixel perfect indirect specular reflections ( I WISH Posted Image )

Currently, all effects combined minus the ssr, showing off volume shadows. Nothing fancy.
Posted Image
Oversaturated example of the diffuse gi:
Posted Image
Dynamic filling of the voxel cache, oriented around the player:
Posted Image
So while playing around, I found this “mega nature pack” in the Unreal Engine 4 marketplace. So I purchased the package and started messing around, just programmer art Posted Image. Now all this shows is that I have some serious work to do with my shading model, and I need to invest some time into some cheap subsurface scattering… Btw in the image below the normals are messed up, so the lighting appears weird in some points. And the volumetric scattering is disabled, since it also desaturates the image a bit ( For valid reasons ).
Posted Image
So I tried messing around with the normals and used the SV_IsFrontFace to determine the direction of the normal on the leaf, and got something like this: ( Volumetric scattering disabled ) ( Btw, quality is lost due to gifs! I love dem gifs ) ( Ignore the red monkey )
Posted Image

The following is the shader used for the tree, which is written by the user: ( Heavily commented )

	// Include the CG Data Layouts
	#include "cg_layout.hlsl"
    // Define the return types of the shader
	// This stage is really important to allow the parser
	// to create the geometry shader for voxelization
	// and also if the user has created his own geometry shader, so that it can figure
	// out a way to voxelize the mesh properly, in this way the user
	// can use ALL stages of the pipeline (VS, HS, DS, GS, PS) without
	// voxelization not being possible.
	// The only problem is well, he has to write the stuff below: ( Even more if he used more stages )
	#set CG_RVSHADER Vertex //       Set the return type of vertex shader
	#set vert CG_VSHADER    // [Opt] Set the name of the vertex shader instead of writing CG_VSHADER
	#set pix CG_PSHADER     // [Opt] Set the name of the pixel shader instead of writing CG_PSHADER
	// This is his stuff
	// He can do whatever he wants!
	Texture2D T_Diffuse : register(t0);
	Texture2D T_Normal : register(t1);
	// Basic VS -> PS Structure
	// This structure inherits the "base" vertex, stuff that the engine can crunch on
	struct Vertex : CG_VERTEXBASE
		// Empty
	// Now include some routines that's needed on the end of all stages
	#include "cg_material.hlsl"
	// Vertex shader
	Vertex vert(CG_ILAYOUT IN)
		// Zero set vertex
		Vertex o = (Vertex)0;
		// Just let the engine process it
		// Although we could do it outselves, but there's no need
		// Return "encoded" version
	// Pixel Shader
	// In this case the return type is FORCED! As it's a deferred setup
	CG_GBUFFER pix(Vertex v, bool IsFrontFace : SV_IsFrontFace)
		// Basic structure containing info about the surface
		Surface surf;
		// Sample color
		float4 diff = CG_TEX(T_Diffuse, v.CG_TEXCOORD);
		// Simple alpha test for vegetation
		// We want it to clip at .a = 0.5 so add a small offset
		clip(diff.a - 0.5001);
		// Fill out the surface information
		surf.diffuse = diff;
		surf.normal = CG_NORMALMAP( // Do some simple normal mapping
			v.CG_NORMAL * ((IsFrontFace) ? 1 : -1), // Flip the normal if backside for leaves
		surf.subsurface = 1; // I've got a simple version of some sss, but it's not very good yet.
		surf.thickness = 0.1; // For the sss
		surf.specular = 0.35;
		surf.anisotropic = 0.2;
		surf.clearcoat = 0;
		surf.metallic = 0;
		surf.roughness = 0.65;
		surf.emission = 0;
		// Return "encoded" version
		// Aka compress the data into the gbuffer!
		CG_PSRETURN(v, 	surf);

So in the progress of all of this, I’m trying to fit in some SMAA and color correction. And the moment I looked into color correction using LUT, I face palmed, because how the hell did I not think of that!? ( Not in a negative way, it’s just so simple and elegant and pure awesome! ) So messing around with that and spending 5 hours on a loading problem which turned out to be too simple, it returns some kewl results: ( Just messing around )
Posted Image
So that’s more or less it. I’ll keep improving my engine, working on stuff and more stuff. I think I’ll leave the diffuse gi system where it is for a while, since it works pretty well and produces pretty results, now I need to work on some specular gi stuff since I really don’t have a robust system for that yet that doesn’t produce ugly artifacts.

See you next time people of the awesome GDNet grounds! ( GDNet -> GameDev.net )