Root cause: GLSL std140 layout adds padding after mat4 for vec4 fields,
causing light data to be read at wrong offsets → NaN/artifacts.
Fix:
- UBO back to 64 bytes (mat4 vp only)
- Light data (pos + color, 32 bytes) sent via push constants at offset 64
- Two push constant ranges: Vertex (0-64, model) + Fragment (64-96, light)
- Both vertex and fragment shaders read from same push_constant block
- PBR shader fully restored with Cook-Torrance BRDF
- Dynamic point light follows physics ball
Light at (0,10,0) hardcoded in GLSL. Tests if lighting math works.
If light works: problem is UBO layout for light data (std140 padding).
If artifacts: problem is in fragWorldPos or fragNormal.
- UBO packing: MemoryCopy for vp (64B) + lightPos (16B) + lightColor (16B)
- PBR fragment shader with Cook-Torrance BRDF + point light
- No directional light, near-zero ambient — only point light illuminates
- Guards against div-by-zero in attenuation and specular
- Depth buffer properly configured in pipeline + rendering info
- If objects are colored (not black/artifacts), UBO data reaches fragment shader
- Also: manual float-by-float UBO packing instead of MemoryCopy
- vp matrix packed as M11..M44 (row-major, no row_major in GLSL = transpose)
- Removed directional light from fragment shader
- Ambient reduced to near-zero (0.01) — scene is dark
- Only light source is the physics LightBall falling from y=15
- Objects near the ball are illuminated, far objects are in darkness
- Dramatic contrast shows dynamic lighting clearly
- UBO expanded from 64 to 128 bytes: vp(64) + lightPos(16) + lightColor(16)
- Vertex shader: passes point light UBO data through
- Fragment shader: refactored calcLight() function, shared by directional + point
- Point light: Unity-style attenuation pow(1 - dist/range, 2)
- Directional light reduced intensity (0.4) to balance with point light
- Point light: position (0,8,0), warm color (1,0.9,0.7), intensity 15, range 25
- Renderer: reads Light component from ECS, packs into UBO with Marshal.StructureToPtr
- Scene: MainLight entity with Light.Point at (0,8,0)
- 0 C# struct changes — pure UBO layout + shader upgrade
- Vertex shader: passes world position, world normal, albedo to fragment
- Fragment shader: full PBR implementation
- D term: Trowbridge-Reitz GGX distribution
- G term: Smith geometry with Schlick-GGX
- F term: Schlick Fresnel approximation
- kD/kS split based on metallic
- Directional light (0.5, 0.8, 0.3) with warm color
- Ambient term (0.15, 0.18, 0.22) for fill light
- ACES filmic tonemapping
- Gamma 2.2 correction
- Fixed roughness=0.5, metallic=0.1 (per-object materials = future)
- No C# code changes — pure shader upgrade
- Vertex shader: pass normal through mat3(model) to fragment
- Fragment shader: directional light (0.5, 0.8, 0.3) with 0.25 ambient
+ 0.75 diffuse = faces now have depth and 3D form
- Torus knot has smooth normals (vn in OBJ), cubes have face normals
- 0 validation errors, ~2300 FPS
- vkCmdBindIndexBuffer indexType changed from 0 (UINT16) to 1 (UINT32)
to match uint[] index data — this was causing black screen
- Removed depth stencil state, depth attachment format, and depth
rendering attachment from pipeline/renderer (depth buffer still
created in swapchain but unused)
- Fragment shader: directional light dot(normal, lightDir) with 0.2 ambient
- Vertex shader: pass normal through mat3(model) to fragment
- Same-color faces now have different shading based on orientation