For a student project, I created a small village scene in OpenGL and C++, where the player could somehow interact with the environment.
The goal of this project was to create a scene with a village, where the player can move using WASD, cut trees by clicking on them, collect wood and light a fire by clicking on one of the rocks. The player can turn on a flashlight, a fog, change camera and open a menu. The time changes, which is visualized by darkening and dawning of the sky.
An example of some of the shaders: The part of the project can be found here: Github.
This is part of the vertex shader which computes color using texture and light in the current vertex
struct Material { // structure that describes currently used material
vec3 ambient; // ambient component
vec3 diffuse; // diffuse component
vec3 specular; // specular component
float shininess; // sharpness of specular reflection
bool useTexture; // defines whether the texture is used or not
};
// warning: sampler inside the Material struct can cause problems -> so its outside
uniform sampler2D texSampler; // sampler for the texture access
struct Light { // structure describing light parameters
vec3 ambient; // intensity & color of the ambient component
vec3 diffuse; // intensity & color of the diffuse component
vec3 specular; // intensity & color of the specular component
vec3 position; // light position
vec3 spotDirection; // spotlight direction
float spotCosCutOff; // cosine of the spotlight's half angle
float spotExponent; // distribution of the light energy within the reflector's cone (center->cone's edge)
};
in vec3 position; // vertex position in world space
in vec3 normal; // vertex normal
in vec2 texCoord; // incoming texture coordinates
uniform bool fog;
uniform bool cat;
uniform bool cube;
uniform float time; // time used for simulation of moving lights (such as sun)
uniform Material material; // current material
uniform mat4 PVMmatrix; // Projection * View * Model --> model to clip coordinates
uniform mat4 Pmatrix; // Projection * View * Model --> model to clip coordinates
uniform mat4 Vmatrix; // View --> world to eye coordinates
uniform mat4 Mmatrix; // Model --> model to world coordinates
uniform mat4 normalMatrix; // inverse transposed Mmatrix
uniform vec3 reflectorPosition; // reflector position (world coordinates)
uniform vec3 reflectorDirection; // reflector direction (world coordinates)
smooth out vec2 texCoord_v; // outgoing texture coordinates
smooth out vec4 color_v; // outgoing fragment color
smooth out vec3 thePosition;
smooth out vec4 theColor;
smooth out vec3 theNormal;
smooth out vec3 pointLightPos;
smooth out vec3 pointLightPosRef;
smooth out vec3 refDirection;
out float visibility;
float density = 0.5;
float gradient = 1.5;
void main() {
visibility = 0.01;
vec3 vertexPosition = (Vmatrix * Mmatrix * vec4(position, 1.0)).xyz; // vertex in eye coordinates
vec3 vertexNormal = normalize( (Vmatrix * normalMatrix * vec4(normal, 0.0) ).xyz); // normal in eye coordinates by NormalMatrix
vec4 outputColor = vec4(0.0, 0.0, 0.0, 1.0f);
if(cat){
float pct = abs(sin(time/3));
gl_Position = PVMmatrix * vec4(position*mix(1, 1.05, pct), 1);
}
else
gl_Position = PVMmatrix * vec4(position, 1); // out:v vertex in clip coordinates
thePosition = vertexPosition;
theColor = outputColor;
theNormal = vertexNormal;
vec4 distanceCam = Vmatrix* Mmatrix * vec4(position, 1.0);
float distance = length(distanceCam);
visibility = exp(-pow((distance*density), gradient));
visibility = clamp(visibility,0.0, 1.0);
color_v = outputColor;
texCoord_v = texCoord;
}
This is part of the fragment shader which computes color in the current fragment
#version 140
struct Material { // structure that describes currently used material
vec3 ambient; // ambient component
vec3 diffuse; // diffuse component
vec3 specular; // specular component
float shininess; // sharpness of specular reflection
bool useTexture; // defines whether the texture is used or not
};
uniform sampler2D texSampler; // sampler for the texture access
uniform Material material; // current material
struct PointLight{
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 position;
float cutOff;
float exponent;
float effect;
vec3 attenuation;
vec3 direction;
};
struct DirectionalLight{
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 direction;
bool shines;
};
struct SpotLight{
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec3 position;
bool turnedOn;
vec3 attenuation;
};
uniform PointLight pointLight;
uniform DirectionalLight directionalLight;
uniform SpotLight spotLight;
uniform mat4 PVMmatrix; // Projection * View * Model --> model to clip coordinates
uniform mat4 Pmatrix; // Projection * View * Model --> model to clip coordinates
uniform mat4 Vmatrix; // View --> world to eye coordinates
uniform mat4 Mmatrix; // Model --> model to world coordinates
uniform mat4 normalMatrix;
smooth in vec3 thePosition;
smooth in vec3 theNormal;
smooth in vec4 theColor;
smooth in vec3 pointLightPos;
smooth in vec3 pointLightPosRef;
smooth in vec3 refDirection;
smooth in vec4 color_v; // incoming fragment color (includes lighting)
smooth in vec2 texCoord_v; // fragment texture coordinates
out vec4 color_f; // outgoing fragment color
uniform bool fog;
uniform bool cube;
in float visibility;
uniform float time;
uniform bool fastenTime;
float sunSpeed = 0.05f;
vec4 getColor(vec3 pos, vec3 rayDir, vec3 ambient, vec3 diffuse, vec3 specular, Material material, vec3 fragPosition, vec3 fragNormal){
vec3 R = reflect(-rayDir, fragNormal);
vec3 V = normalize(-fragPosition);
float NdotL = max(0.0, dot(fragNormal, rayDir));
float RdotV = max(0.0, dot(R, V));
return vec4(material.ambient * ambient + material.diffuse * diffuse * NdotL + material.specular * specular * pow(RdotV, material.shininess),1.0f);
}
vec4 getDirLight(DirectionalLight light, Material material, vec3 fragPosition, vec3 fragNormal) {
vec3 pos = (Vmatrix * vec4(cos(time * sunSpeed), 0.0, sin(time * sunSpeed), 0.0)).xyz;
vec3 rayDir = normalize(pos);
vec4 color = getColor(pos,rayDir,light.ambient, light.diffuse,light.specular,material,fragPosition, fragNormal);
return color;
}
vec4 getPointLight(PointLight light, Material material, vec3 fragPosition, vec3 fragNormal) {
vec3 pos = (Vmatrix * vec4(light.position, 1.0)).xyz;
vec3 direction = normalize((Vmatrix * vec4(light.direction, 0.0)).xyz);
vec3 rayDir = pos - fragPosition;
float distance = length(pos - fragPosition);
rayDir = normalize(rayDir);
vec4 color = getColor(pos,rayDir,light.ambient, light.diffuse,light.specular,material,fragPosition, fragNormal);
float angle = dot(-rayDir, direction);
float attenuationFactor = 1.0f/(light.attenuation.x + light.attenuation.y*distance + light.attenuation.z*distance*distance);
if(max(angle, 0) < light.cutOff)
color = vec4(vec3(0.0),1);
return color*attenuationFactor*pow(max(angle,0), light.exponent);
}
vec4 getSpotLight(SpotLight light, Material material, vec3 fragPosition, vec3 fragNormal) {
vec3 pos = (Vmatrix * vec4(light.position, 1.0)).xyz;
vec3 rayDir = pos - fragPosition;
float distance = length(pos - fragPosition);
rayDir = normalize(rayDir);
vec4 color = getColor(pos,rayDir,light.ambient, light.diffuse,light.specular,material,fragPosition, fragNormal);
float attenuationFactor = 1.5f;
if(distance>1)
attenuationFactor = 1.0f/(light.attenuation.x + light.attenuation.y*distance + light.attenuation.z*distance*distance);
return color*attenuationFactor;
}
void main() {
vec3 L = normalize(pointLightPos-thePosition);
if(directionalLight.shines)
color_f = color_v;
if(!fastenTime)
color_f = color_f + getDirLight(directionalLight, material, thePosition,theNormal);
color_f = color_f + getPointLight(pointLight, material, thePosition, theNormal);
if(spotLight.turnedOn)
color_f = color_f + getSpotLight(spotLight, material, thePosition, theNormal);
if(cube)
color_f = vec4(0.7, 0.7, 0.7, 1);
if(material.useTexture)
color_f = color_f * texture(texSampler, texCoord_v);
if(fog)
color_f = mix(vec4(vec3(0.5, 0.5, 0.5), 1.0), color_f, visibility);
}
Comments