Minecraft Like with Neko Engine

I’m currently a student at the SAE Institute of Geneva, in the Game Programming section. For the computer graphic module, our class began to work on creating a basic clone of Minecraft, using the custom game engine made in C++ : Neko engine.

Our main goal was to implement basic functions, such as:

  • Chunk System
  • Procedural Generation
  • Light & Shadows
  • Basic player movements

In this project, my goal was to implement the Light & Shadows.

Minecraft Like context

In the Minecraft Like game, the player roam across the proceduraly generated terrain. This terrain is composed of chunks and blocs. For each bloc, a shadow need to be displayed.

Light Structure

To start, we need a light source, I created a simple struct which contains all the needed information about the light source.

struct DirectionalLight
{
	Vec3f position = Vec3f::one * 10.0f;
	Vec3f direction = Vec3f(-1.0f, -1.0f, 0.0f);
	Color3 color = Vec3f(1.0f, 1.0f, 1.0f);
	
	float intensity = 2.0f;
	float ambientStrength = 1.0f;
	float diffuseStrength = 1.0f;
	float specularStrength = 1.0f;
	int specularPow = 32;
}; 
Then in the chunk rendering part of the code, I implemented this directional light
DirectionalLight directionalLight_; 

I also created a vertex shader and a fragment shader to render the cubes with the Blinn-Phong lighting model. After some coding for the implementation of basic material structure, I got my first cube casted with a light !

Shadows

Then, I needed to display some shadows, and believe me it was not an easy task.
First of all, my current rendering process was the following:

  1. Initialize light parameters
  2. Set camera parameters
  3. Bind the model shader
  4. Render scene on the Framebuffer with the model shader

To create a shadow I first need to create a depth buffer, with a depth shader, which should give me something like this :

Then, I have to change my rendering process to something like this:

 

  1. Initialize light parameters
  2. Initialize Depth buffer
  3. Set camera parameters
  4. Bind the depth shader
  5. Render scene on the Framebuffer with the depth shader
  6. Bind the model shader
  7. Calculate the shadow in the model shader
  8. Render scene on the Framebuffer with the model shader

The directional light is modeled to be infinitely far away, but we need to render the scene from the light perspective, all rays are parallel.

In the shadow calculation I integrated multiple technics to render the shadow correctly, and to remove undesired artefacts.

  • A bias to get rid of shadow acne.
  • Used backface culling to get rid of peter panning
  • Used PCF to have smoother shadow edges.
float ShadowCalculation(vec4 fragPosLightSpace)
{
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    projCoords = projCoords * 0.5 + 0.5;
    if(projCoords.x < 0.0 || projCoords.x > 1.0 ||projCoords.y < 0.0 || projCoords.y > 1.0)
        return 0.0;
    
    float closestDepth = texture(shadowMap, projCoords.xy).r; 
    float currentDepth = projCoords.z;
    if(currentDepth > 1.0)
        return 0.0;
    
    vec3 normal = normalize(Normal);
    vec3 lightDir = -light.direction;
    
    float shadow = 0.0;
    vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
    for(int x = -1; x <= 1; ++x)
    {
        for(int y = -1; y <= 1; ++y)
        {
            float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; 
            shadow += currentDepth - bias > pcfDepth  ? 1.0 : 0.0;        
        }    
    }
    shadow /= 9.0;
    
    if(projCoords.z > 1.0)
        shadow = 0.0;
        
    return shadow;
} 

Before it gave me correct results, I had some strange complications, let’s check some of them :

Then, after a lot of tinkering and bug corrections, I finaly had my first shadow !


Conclusion

As my first big experience in OpenGl with lights and shadows, which where not my speciality, when I figured out what needed to be done, and by learning technics online, I succeeded to create a working shadow and correct lighting conditions for the Minecraft like. I also learned a lot and gained a lot of experience by working along with my teammates.