first commit

This commit is contained in:
David Ali
2026-01-09 13:50:52 +01:00
commit 9f87935db1
24 changed files with 7925 additions and 0 deletions

35
assets/shaders/mesh.frag Normal file
View File

@@ -0,0 +1,35 @@
#version 450 core
layout(location = 0) out vec4 oColor;
layout(std140, binding = 0) uniform PerFrame {
mat4 uView;
mat4 uProj;
vec4 uLightDir;
};
layout(std140, binding = 2) uniform Material {
vec4 uAlbedo; // rgb used, a padding
};
in VS_OUT {
vec3 wPos;
vec3 wNrm;
vec2 uv;
flat int hasNrm;
flat int hasUV;
} v;
vec3 fallbackNormal(vec3 wPos) {
vec3 dx = dFdx(wPos), dy = dFdy(wPos);
vec3 c = cross(dx, dy);
float l2 = dot(c, c);
return (l2 < 1e-12) ? vec3(0, 0, 1) : normalize(c);
}
void main() {
vec3 N = (v.hasNrm != 0) ? normalize(v.wNrm) : fallbackNormal(v.wPos);
vec3 L = normalize(-uLightDir.xyz);
float ndl = max(dot(N, L), 0.0);
vec3 ambient = vec3(0.08);
vec3 colorLinear = ambient + uAlbedo.rgb * ndl;
oColor = vec4(pow(colorLinear, vec3(1.0/2.2)), 1.0);
}

45
assets/shaders/mesh.vert Normal file
View File

@@ -0,0 +1,45 @@
#version 450 core
out gl_PerVertex {
vec4 gl_Position;
};
layout(std140, binding = 0) uniform PerFrame {
mat4 uView;
mat4 uProj;
vec4 uLightDir; // xyz used, w padding
};
layout(std140, binding = 1) uniform PerObject {
mat4 uModel;
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aUV;
out VS_OUT {
vec3 wPos;
vec3 wNrm;
vec2 uv;
flat int hasNrm;
flat int hasUV;
} v;
void main() {
vec4 wpos4 = uModel * vec4(aPos, 1.0);
v.wPos = wpos4.xyz;
float nLen2 = dot(aNormal, aNormal);
if(nLen2 > 1e-10) {
mat3 nrmMat = mat3(transpose(inverse(uModel)));
v.wNrm = normalize(nrmMat * aNormal);
v.hasNrm = 1;
} else {
v.wNrm = vec3(0.0);
v.hasNrm = 0;
}
v.uv = aUV;
v.hasUV = (abs(aUV.x) + abs(aUV.y)) > 1e-10 ? 1 : 0;
gl_Position = uProj * uView * wpos4;
}

View File

@@ -0,0 +1,33 @@
#version 450 core
layout(location = 0) out vec4 oColor;
layout(std140, binding = 0) uniform PerFrame {
mat4 uView;
mat4 uProj;
vec4 uLightDir; // unused
};
layout(std140, binding = 2) uniform Material {
vec4 uAlbedo; // unused
};
layout(location = 0) in vec3 vDir;
// sRGB-tuned colors; well convert to linear before mixing
vec3 srgb2lin(vec3 c){ return pow(c, vec3(2.2)); }
vec3 lin2srgb(vec3 c){ return pow(c, vec3(1.0/2.2)); }
void main() {
// nicer defaults (tweak to taste)
vec3 skyTopL = srgb2lin(vec3(0.15, 0.35, 0.75));
vec3 skyHorizonL = srgb2lin(vec3(0.75, 0.85, 0.98));
vec3 dir = normalize(vDir);
float t = clamp(dir.z * 0.5 + 0.5, 0.0, 1.0); // (B) world up = +Z
// shape the gradient a bit
t = pow(t, 1.45);
vec3 colorL = mix(skyHorizonL, skyTopL, t);
oColor = vec4(lin2srgb(colorL), 1.0); // manual gamma (your default FB isnt sRGB)
}

View File

@@ -0,0 +1,31 @@
#version 450 core
out gl_PerVertex { vec4 gl_Position; };
layout(std140, binding = 0) uniform PerFrame {
mat4 uView;
mat4 uProj;
vec4 uLightDir; // unused here
};
layout(std140, binding = 1) uniform PerObject {
mat4 uModel; // use this to scale the cube (e.g., 3.0)
};
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal; // present, unused
layout(location = 2) in vec2 aUV; // present, unused
layout(location = 0) out vec3 vDir; // explicit location for SSO
void main() {
// Use uModel to scale your standard cube (e.g., 3.0) from CPU.
vec3 pLocal = mat3(uModel) * aPos;
// Rotation-only view (drop translation)
mat3 R = mat3(uView);
vDir = pLocal;
// Glue the cube to the camera (no translation), push to far plane
vec4 p = uProj * vec4(R * pLocal, 1.0);
gl_Position = vec4(p.xy, 1.0, 1.0);
}

View File

@@ -0,0 +1,39 @@
#version 450 core
layout(location=0) out vec4 oColor;
layout(std140, binding=0) uniform PerFrame { mat4 uView; mat4 uProj; vec4 uLightDir; };
layout(std140, binding=2) uniform Material { vec4 uAlbedo; };
layout(location=0) in VS_OUT {
vec3 wPos;
vec2 uv;
} v;
// geometric normal from screen-space derivatives of the *world* position
vec3 normal_from_worldpos(vec3 w){
vec3 dx = dFdx(w), dy = dFdy(w);
vec3 n = cross(dx,dy);
float l2 = dot(n,n);
return (l2 < 1e-12) ? vec3(0,0,1) : normalize(n);
}
void main(){
vec3 N = normal_from_worldpos(v.wPos);
vec3 L = normalize(-uLightDir.xyz);
float ndl = max(dot(N,L), 0.0);
// cheap color: height-based gradient + slight darkening by slope
float h = v.wPos.z; // world height
float h01 = clamp(h * 0.1 + 0.5, 0.0, 1.0); // remap height to 0..1
vec3 low = vec3(0.35, 0.38, 0.40); // rock/soil
vec3 high = vec3(0.65, 0.75, 0.60); // grass
vec3 base = mix(low, high, h01);
float slope = 1.0 - abs(N.z); // 0 = flat up, 1 = vertical
base *= mix(1.0, 0.8, slope); // darker on steep slopes
vec3 ambient = vec3(0.08);
vec3 color = ambient + base * (uAlbedo.rgb * ndl);
oColor = vec4(color, 1.0);
}

View File

@@ -0,0 +1,45 @@
#version 450 core
out gl_PerVertex { vec4 gl_Position; };
layout(std140, binding=0) uniform PerFrame { mat4 uView; mat4 uProj; vec4 uLightDir; };
layout(std140, binding=1) uniform PerObject { mat4 uModel; };
layout(location=0) in vec3 aPos; // XY from grid, Z ignored
layout(location=2) in vec2 aUV; // 0..1 across the grid
layout(location=0) out VS_OUT {
vec3 wPos;
vec2 uv;
} v;
// ---- tiny fBm noise (tile-free, cheap) ----
float hash(vec2 p){ return fract(sin(dot(p, vec2(127.1,311.7))) * 43758.5453); }
float noise(vec2 p){
vec2 i=floor(p), f=fract(p);
float a = hash(i + vec2(0,0));
float b = hash(i + vec2(1,0));
float c = hash(i + vec2(0,1));
float d = hash(i + vec2(1,1));
vec2 u = f*f*(3.0-2.0*f);
return mix(mix(a,b,u.x), mix(c,d,u.x), u.y);
}
float fbm(vec2 p){
float a=0.5, s=0.0;
for(int i=0;i<5;i++){ s += a*noise(p); p = p*2.02 + 17.0; a*=0.5; }
return s;
}
// tunables
uniform float uHeightScale = 3.0; // world Z amplitude
uniform float uFreq = 2.0; // base frequency (cycles over 0..1 uv)
void main(){
float h = fbm(aUV * uFreq) * uHeightScale; // Z-up displacement
vec3 p = vec3(aPos.xy, h);
vec4 w = uModel * vec4(p,1.0);
v.wPos = w.xyz;
v.uv = aUV;
gl_Position = uProj * uView * w;
}