#version 450 core
// Vertex attribute inputs
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;
// Outputs to fragment shader
layout(location = 0) out vec3 vWorldPos;
layout(location = 1) out vec3 vNormal;
layout(location = 2) out vec2 vTexCoord;
layout(location = 3) out vec4 vShadowCoord;
// Uniform buffer for transform matrices
layout(std140, binding = 0) uniform Matrices {
mat4 model;
mat4 view;
mat4 projection;
mat4 lightSpaceMatrix;
};
// Material properties
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
// Point light
struct PointLight {
vec3 position;
vec3 color;
float intensity;
float radius;
};
#define MAX_LIGHTS 8
#define PI 3.14159265359
/// Transform normal from object to world space
vec3 transformNormal(vec3 normal, mat4 modelMatrix) {
mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
return normalize(normalMatrix * normal);
}
/// Compute fresnel factor using Schlick approximation
float fresnelSchlick(float cosTheta, float F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
/// Compute distance attenuation for point lights
float attenuate(float distance, float radius) {
float d = max(distance, 0.001);
float attenuation = 1.0 / (d * d);
float falloff = clamp(1.0 - pow(d / radius, 4.0), 0.0, 1.0);
return attenuation * falloff;
}
/// Apply fog effect based on distance
vec4 applyFog(vec4 color, float distance, vec3 fogColor, float fogDensity) {
float fogFactor = exp(-fogDensity * distance);
fogFactor = clamp(fogFactor, 0.0, 1.0);
return mix(vec4(fogColor, 1.0), color, fogFactor);
}
void main() {
vec4 worldPos = model * vec4(aPosition, 1.0);
vWorldPos = worldPos.xyz;
vNormal = transformNormal(aNormal, model);
vTexCoord = aTexCoord;
vShadowCoord = lightSpaceMatrix * worldPos;
gl_Position = projection * view * worldPos;
}