#version 460 // Flat shading: the per-face normal is reconstructed from screen-space // derivatives of the model-space position, so the vertex stream needs no // normals. color.a selects shaded (1) vs constant colour (0, for wireframe). layout(location = 0) in vec3 vModelPos; layout(location = 0) out vec4 outColor; layout(push_constant) uniform PC { mat4 mvp; vec4 color; } pc; void main() { vec3 dx = dFdx(vModelPos); vec3 dy = dFdy(vModelPos); vec3 c = cross(dx, dy); float len = length(c); vec3 n = (len > 1e-8) ? c / len : vec3(0.0, 0.0, 1.0); const vec3 L = normalize(vec3(0.4, 0.85, 0.55)); float diff = abs(dot(n, L)); // two-sided float shade = clamp(0.25 + 0.8 * diff, 0.0, 1.0); vec3 base = pc.color.rgb; vec3 rgb = mix(base, base * shade, pc.color.a); outColor = vec4(rgb, 1.0); }