95 lines
2.6 KiB
GLSL
95 lines
2.6 KiB
GLSL
|
#version 330
|
||
|
// Color input from Vertex shader
|
||
|
in vec3 vNormal;
|
||
|
in vec3 vPosition;
|
||
|
|
||
|
// Final fragment fColor
|
||
|
out vec4 fColor;
|
||
|
|
||
|
// Light object and camera position vectors
|
||
|
uniform vec3 uCameraPosition;
|
||
|
struct Light {
|
||
|
vec3 position;
|
||
|
|
||
|
// Light colors RGB value
|
||
|
vec3 ambient;
|
||
|
vec3 diffuse;
|
||
|
vec3 specular;
|
||
|
};
|
||
|
uniform Light uLight;
|
||
|
|
||
|
struct Material {
|
||
|
// Strength ranges 0.0f - 1.0f
|
||
|
float ambientStrength;
|
||
|
float diffuseStrength;
|
||
|
float specularStrength;
|
||
|
// 32, 64, 128, 256
|
||
|
float shine;
|
||
|
|
||
|
// Material color values
|
||
|
vec3 ambient;
|
||
|
vec3 diffuse;
|
||
|
vec3 specular;
|
||
|
};
|
||
|
uniform Material uMaterial;
|
||
|
|
||
|
struct Result {
|
||
|
vec3 ambient;
|
||
|
vec3 diffuse;
|
||
|
vec3 specular;
|
||
|
vec3 sum;
|
||
|
};
|
||
|
|
||
|
void SumResult(inout Result result)
|
||
|
{
|
||
|
result.sum = result.ambient + result.diffuse + result.specular;
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
// A struct to store lighting results as we finish calculating them
|
||
|
// Valuse stored here will be applied to the final output of our shader
|
||
|
Result result;
|
||
|
|
||
|
// Ambient lighting
|
||
|
result.ambient = (uLight.ambient * uMaterial.ambient) * uMaterial.ambientStrength;
|
||
|
|
||
|
//
|
||
|
// Diffuse lighting
|
||
|
|
||
|
// Normalize the provided normal vector
|
||
|
// + Creates a vector with length of 1 in the same direction as vNormal
|
||
|
vec3 norm = normalize(vNormal);
|
||
|
// Get a vector from this frag to the lightSoruce
|
||
|
vec3 lightDir = normalize(uLight.position - vPosition);
|
||
|
// As the normal vector approaches an angle looking at lightDir vector
|
||
|
// + If this is negative, the frag is on a surface opposite of the lightSource
|
||
|
float diff = max(dot(norm, lightDir), 0.0f);
|
||
|
result.diffuse = (uLight.diffuse * diff * uMaterial.diffuse) * uMaterial.diffuseStrength;
|
||
|
|
||
|
//
|
||
|
// Specular lighting
|
||
|
|
||
|
// Get a vector from the camera to the fragment as our viewDir
|
||
|
vec3 viewDir = normalize(uCameraPosition - vPosition);
|
||
|
// Since lightDir is already a vector from this frag to the light source
|
||
|
// reflectionDir is the opposite; A vector from the light to the frag
|
||
|
vec3 reflectDir = reflect(-lightDir, norm);
|
||
|
|
||
|
// Use dot product to check if viewDir and reflectDir angles are intersecting
|
||
|
// -1.0f if they are opposite; 1.0 if they are looking at each other directly
|
||
|
// + If this is negative, the lightSource is behind the player; Ignore it
|
||
|
float angleAlpha = max(dot(viewDir, reflectDir), 0.0f);
|
||
|
// As the angleAlpha approaches 1, raise to the power of uMaterial.shine
|
||
|
float spec = pow(angleAlpha, uMaterial.shine);
|
||
|
// Apply specular result to the
|
||
|
result.specular = (uLight.specular * uMaterial.specular * spec) * uMaterial.specularStrength;
|
||
|
|
||
|
//
|
||
|
// Final calculation
|
||
|
SumResult(result);
|
||
|
|
||
|
// Final output
|
||
|
fColor = vec4(result.sum, 1.0f); // Reapply alpha for opacity
|
||
|
}
|