Cuboid Engine is a graphical rendering framework developed by me over time as a hobby, I simply have one rule:
Keep, Everything, Realtime!
Which essentially means I don’t bake any lighting information, which is a heavy hit on performance and increases the challange! 🙂
The images below do not represent all features but some in the current state of the engine, the first 4 images represent some features of the current state of the engine:
The rendering system follows a deferred path, looking past the regular features of /graphics engines, this engine shines in the following:
- Cascaded Custom Light Propagation Volumes GI System ( With a Low and High Frequency buffer per cascade )
- BRDF Shading
- Luminance Adaptation
- High Quality Tone mapping (+Bloom Effect)
- Per LightSource Volumetric Lighting ( RayMarched )
- Currently Discontinued Screen Space Reflections seen on the law few images.
- Including a few minour effects that overall contribute to the image
With all features enabled the engine runs at a steady ~100 fps ( ~10 ms ) on my GTX 970 at a resolution of 1920×1080.
The rendering system is based on DirectX 11 and written in C++. It also has a great layer of flexibility, allowing the user to create his own materials without breaking the pipeline (Such as voxelization on any material given), such as:
Shader { // 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 CG_RPSHADER #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 CG_VSPROCESS(o, IN); // Return "encoded" version CG_VSRETURN(o); } // 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 clip(diff.a - 0.1001); // Fill out the surface information surf.diffuse = diff; surf.normal = CG_NORMALMAP( // Do some simple normal mapping T_Normal, v.CG_TEXCOORD, v.CG_NORMAL * ((IsFrontFace) ? 1 : -1), // Flip the normal if backside for leaves v.CG_TANGENT, v.CG_BINORMAL ); surf.subsurface = 1; // I've got a simple version of some ssss, but it's not very good yet. surf.thickness = 0.1; // For the sssss ( Want more s's? ) surf.specular = 0.35; surf.anisotropic = 0.2; surf.clearcoat = 0; surf.metallic = 0; surf.roughness = 0.65f; surf.emission = 0; // Return "encoded" version // Aka compress the data into the gbuffer! CG_PSRETURN(v, surf); } };