/* ## COMPILED C++ ##
// Author: Jackson Luff
// Name: SegmentedGrid.cpp
// Type: CPP File
// Description:
// * This is where the map is
// * created pre-process. This
// * is more efficent then textures.
*/
void SegmentedGrid::GenPerlin(unsigned int a_dims, float a_dimScale)
{
// Populate verts with row + cols input
m_vertices = new VertexData[a_dims * a_dims];
// Set up scale and octave count
float scale = (1.0f / a_dims) * 6.0f;
int octaves = 9;
// Iterate through verticies and apply perlin noise
// (Could be optimized)
for (unsigned int r = 0; r < a_dims; ++r)
{
for (unsigned int c = 0; c < a_dims; ++c)
{
float amplitude = 1.f;
float persistence = 0.2f;
m_vertices[r * a_dims + c].position = glm::vec4((float)(c * a_dimScale), 0, (float)(r * a_dimScale), 1.0f);
m_vertices[r * a_dims + c].uv = glm::vec2((float)c / a_dims, (float)r / a_dims);
// Iterate through octaves per vert
// octaves are used to 'tone' the noise
for (int o = 0; o < octaves; ++o)
{
// generate simplex and perlin with scale and frequency
float freq = powf(4, (float)o);
float simplex_sample = glm::simplex(glm::vec2((float)r, (float)c) * scale * freq/10.0f) * 0.5f + 0.5f;
float perlin_sample = glm::perlin(glm::vec2((float)r, (float)c) * scale * freq) * 0.5f + 0.5f;
// Apply simplex and perlin together, to create a blend between the two
m_vertices[r * a_dims + c].position.y += (perlin_sample+simplex_sample) * amplitude;
amplitude *= persistence;
}
// Generate Perlin noise with a height scale based on a ratio (to keep things clean)
float mapGeneralScale = 5.0f;
float mapHeightScale = ((a_dims * 150.0f) / 512.0f) * (a_dimScale/3.0f);
m_vertices[r * a_dims + c].position.y *= mapHeightScale*mapGeneralScale;
m_vertices[r * a_dims + c].position.x *= mapGeneralScale;
m_vertices[r * a_dims + c].position.z *= mapGeneralScale;
}
}
/* ## FRAGMENT SHADER ##
// Author: Jackson Luff
// Name: Terrain.frag
// Type: Fragment Shader
// Description:
// * Here I work with splotching
// * the terrain textures everywhere.
// * If i didn't the texture work
// * would actually look quite bland.
*/
#version 430
in vec3 vPosition;
in vec3 vNormal;
in vec3 vTangent;
in vec3 vBiNormal;
in vec2 vCoords;
uniform mat4 World = mat4(0);
uniform float elapsedTime = -1.0;
float DiffuseLightPower = 5.0;
vec3 DiffuseLightColour = vec3(1);
float SpecularLightPower = 5.0;
vec3 SpecularLightColour = vec3(1, 0.75, 0.65);
float VCoordScale = 50.0;
uniform sampler2D grassDiffuse;
uniform sampler2D grassNormal;
uniform sampler2D stoneDiffuse;
uniform sampler2D stoneNormal;
uniform sampler2D bumpyPerlinTexture;
uniform sampler2D smoothPerlinTexture;
out vec4 pixelColour;
vec3 DiffuseSplotch(in sampler2D t, in vec2 coords, in float baseCoordMulti,
in float lCoordMulti, in float lAlter)
{
// Setup textures with varied tile samples
vec3 data = texture(t, coords*baseCoordMulti).rgb;
vec3 firstOverlay = texture(t, coords*lCoordMulti).rgb;
vec3 secondOverlay = texture(t, coords*20.0).rgb;
// Check for light splotching of green
if(firstOverlay.g > 0.2)
data += firstOverlay + lAlter;
// Check for heavy splotching of blue
if(secondOverlay.g > 0.6)
data += secondOverlay * vec3(0.7);
data = mix(data, data*vec3(0.8), 1);
return data;
}
vec3 NormalSplotch(in sampler2D t, in vec2 coords, in float baseCoordMulti,
in float lSplotch, in float lCoordMulti,
in float hSplotch, in float hCoordMulti)
{
// Setup textures with varied tile samples
vec3 data = texture(t, coords*baseCoordMulti).rgb * 2 - 1;
vec3 firstOverlay = texture(t, coords*lCoordMulti).rgb * 2 - 1;
vec3 secondOverlay = texture(t, coords*hCoordMulti).rgb * 2 - 1;
// Check for light splotching of green
if(firstOverlay.g > lSplotch)
data = normalize(data + firstOverlay);
// Check for heavy splotching of green
if(secondOverlay.b > hSplotch)
data = normalize(data + secondOverlay);
return data;
}
void main()
{
// Set up light vector
vec3 lightPosition = vec3(3000 + sin(elapsedTime), 5000, 3000);
vec3 lightVector = normalize(lightPosition - vPosition);
// Smooth step to allowed gradual use in mix()
float dotNorm = dot(normalize(vNormal), vec3(0.0,1.0,0.0));
dotNorm = smoothstep(0.8, 1.0, dotNorm * 0.5 + 0.5);
// Create a Tangent Bi-Normal for accurate normal reads
mat3 TBN = mat3(
normalize( vTangent ),
normalize( vBiNormal ),
normalize( vNormal ));
// Here we set up the normal information
// (The grass normal was too intense, so I mashed it up)
vec3 grassNormalSamp = NormalSplotch(grassNormal, vCoords, VCoordScale, 0.2, 3, 0.6, 10);
vec3 stoneNormalSamp = texture(stoneNormal, vCoords*VCoordScale).rgb * 2 -1;
vec3 normalSampData = mix(stoneNormalSamp, grassNormalSamp, dotNorm);
// Set up the diffuse of the texture mapping
vec3 grassDiffuseSamp = DiffuseSplotch(grassDiffuse, vCoords, VCoordScale, 3, -0.2);
vec3 stoneDiffuseSamp = DiffuseSplotch(stoneDiffuse, vCoords, VCoordScale, 2, +0.0) * 0.85;
vec3 diffuseSampData = mix(stoneDiffuseSamp, grassDiffuseSamp, dotNorm);
// Produce lighting based on normal information
float dNLight = max( 0, dot( TBN * normalSampData, lightVector ));
vec4 diffLight = vec4(vec3(pow(max( 0, dot( vNormal, lightVector )), 2.0)), 1.0);
// i'm using both lighting sets to get a smooth and effective amount of light
pixelColour = vec4(diffuseSampData * dNLight, 1.0) * clamp(diffLight, 0.2, 1.0);
}