suicmez/game/terrain.fs

86 lines
2.5 KiB
Forth
Raw Normal View History

2025-12-18 21:32:05 +05:30
#version 330
// Input from vertex shader
in vec3 fragPosition;
in vec3 fragNormal;
in vec2 fragTexCoord;
// Uniforms
uniform sampler2D texture0;
uniform vec3 viewPos;
uniform vec3 lightDir;
uniform vec3 lightColor;
uniform float lightIntensity;
uniform float ambientIntensity;
uniform vec3 terrainColor;
// Output
out vec4 finalColor;
// Simplex noise for AO calculation
float hash(float n) {
return fract(sin(n) * 43758.5453123);
}
float noise(vec3 p) {
vec3 i = floor(p);
vec3 f = fract(p);
f = f * f * (3.0 - 2.0 * f);
float n = i.x + i.y * 157.0 + i.z * 113.0;
return mix(
mix(mix(hash(n), hash(n + 1.0), f.x),
mix(hash(n + 157.0), hash(n + 158.0), f.x), f.y),
mix(mix(hash(n + 113.0), hash(n + 114.0), f.x),
mix(hash(n + 270.0), hash(n + 271.0), f.x), f.y),
f.z
);
}
// Calculate ambient occlusion with more contrast
float calculateAO(vec3 position, vec3 normal) {
// Sample 8 directions around the surface
float ao = 0.0;
float radius = 2.5;
int samples = 8;
for (int i = 0; i < samples; i++) {
float angle = 6.28318530718 * float(i) / float(samples);
vec3 offset = vec3(cos(angle) * radius, noise(position * 0.5 + float(i)), sin(angle) * radius);
// Sample height variation (approximated via noise)
float heightVariation = noise((position + offset) * 0.3);
// Calculate occlusion based on height and normal
float dotProduct = max(0.0, dot(normal, normalize(offset)));
ao += mix(0.0, dotProduct * heightVariation, 0.7);
}
// Increased contrast: 0.8 multiplier instead of 0.6
ao = 1.0 - (ao / float(samples)) * 0.8;
// Min 0.1 (darker shadows) instead of 0.2
return max(0.1, ao);
}
void main()
{
// Normalize interpolated normal
vec3 norm = normalize(fragNormal);
// Use normal Y component to create geometry-revealing green shading
// Higher Y normal (upward-facing) = brighter green (peaks/flat areas)
// Lower Y normal (sloped) = darker green (slopes/valleys)
float brightness = (norm.y + 1.0) * 0.5; // Map -1..1 to 0..1
// Increase contrast: darker minimum, brighter maximum
// Old range: 0.4 to 1.0 (0.6 total range)
// New range: 0.2 to 1.2 (1.0 total range) - much more contrast
float contrastMultiplier = 0.2 + brightness * 1.0;
// Create base terrain color modulated by geometry
vec3 baseColor = terrainColor;
vec3 finalColorRGB = baseColor * contrastMultiplier;
finalColor = vec4(finalColorRGB, 1.0);
}