The purpose of this post is to talk through a collection of the projects completed to gain a better understanding of a specific area of game development. Each project section contains a description of the project and the area of research / enrichment it was meant to tackle.


The Shaders of Firewatch

When playing many games; I wonder how certain visual effects have been achieved. In the case of Firewatch, I watched a GDC video explaining the various techniques titled The Art of Firewatch. This inspired me to spend some time writing some shaders to replicate the effects seen in Campo Santo's Firewatch. The first shader I wrote was a depth based gradient fog image effect, the term 'stylistic fog' was coined as it's simpler name.

The concept for the shader is fairly simple; build an image effect that uses a depth-texture, colouring each pixel based on how far it is from the camera, I used a gradient texture to define the colours used.


The second shader I wrote inspired by Firewatch was a procedural skybox using vastly abstracted atmospheric scattering. The aim was contain the following elements in the skybox:

  • A colour below the horizon line,
  • A colour above the horizon line,
  • A colour for the horizone line,
  • A Sun location and colour.

The shader turned out alot cheaper and simpler than I would have first thought; the most expensive parts of it are the two 'pow' functions. Here is the fragment shader:


half4 frag(v2f i) : COLOR
{
float3 v = normalize(i.texcoord);

float p = v.y;
float p1 = 1 - pow(min(1, 1 - p), _SkyExponent1);
float p3 = 1 - pow(min(1, 1 + p), _SkyExponent2);
float p2 = 1 - p1 - p3;

half3 c_sky = _SkyColor1 * p1 + _SkyColor2 * p2 + _SkyColor3 * p3;
half3 c_sun = _SunColor * min(pow(max(0, dot(v, _SunVector)), _SunAlpha) * _SunBeta, 1);

return half4(c_sky * _SkyIntensity + c_sun * _SunIntensity, 0);
}


Bullet trajectory simulation

We have all played a large number of shooters, there are two main methods used to simulate bullet trajectories; instantaneous raycasts or physics simulated bullets. Simulating using raycasts is easy enough to replicate but I was interested in how this was done using simulation - I've also been thinking about how this would work over a network and how this causes issues when there are issues with player connectivity or latency. The networking elements are outside the scope of this mini-project but I'll go through the methodology I used to simulate each bullet's trajectory.



I did some research into the 5.56mm bullet and the M16 rifle and created a basic model for the creation of a bullet prefab to setup the initial velocity. I'd then be able to check my simulation against real-life statistics to see if I have been successful. I used the fixed update to simulate the trajectory of the bullets, starting with integration, then a raycast to check for collisions followed by some debug drawing:


protected void FixedUpdate()
{
travelTime += Time.fixedDeltaTime;

// 1. Integrate (Heun's method)
float h = Time.fixedDeltaTime;

Vector3 accelerationFactorEuler = Physics.gravity;
Vector3 accelerationFactorHeun = Physics.gravity;

Vector3 velocityFactor = velocity;

Vector3 posEuler = position + h * velocityFactor;
Vector3 velEuler = velocity + h * accelerationFactorEuler;

Vector3 posHeun = position + h * 0.5f * (velocityFactor + velEuler);
Vector3 velHeun = velocity + h * 0.5f * (accelerationFactorEuler + accelerationFactorHeun);

// 2. Raycast (hit detection)
float length = (posHeun - position).magnitude;
ray = new Ray(position, (posHeun - position) / length);
hitInfo = new RaycastHit();
Physics.Raycast(ray, out hitInfo, length, collisionMask);

// 3. Debug
if(hitInfo.collider != null){
Debug.DrawLine(position, hitInfo.point, Color.red, 60.0f);
distance = Vector3.Distance(initial, hitInfo.point);
PrintDebug(hitInfo.point);
Destroy(gameObject);
}else{
Debug.DrawLine(position, posHeun, Color.green, 60.0f);
}

position = posHeun;
velocity = velHeun;
}

I used Huen's method as the integration method since it's more accurate than just using Euler. The final step was to gather results and compare them against real world values.



In the image above, there are three line colours, the blue line is a basic raycast to get the data used to calculate the bullet drop. The green line is the trajectory visualisation and the red line shows the bullet collision.


These are just a couple of the enrichment projects I've done over the past three years, I generally do one of these projects once every few months (dependant on inspiration).