Skip to content

shaders

FreeBodyEngine.graphics.pbr.shaders #

FBUSL source for PBRPipeline's internal shaders - the lighting composite pass (deferred, reads the G-buffer back) and the light-list/PBR math it shares with default_forward.fbfrag (forward-shaded transparent objects - see graphics/material.py's BlendMode and PBRMaterial's shader defaults).

MAX_LIGHTS is a hard cap: every slot is a flat set of named uniforms (LightN_...) rather than a true GLSL uniform array, unrolled MAX_LIGHTS times in source. This is a deliberate, lower-risk choice over FBUSL's @buffer blocks - see graphics/pbr/pipeline.py's module docstring for why. Raising this constant costs one recompile of both shaders (see graphics/pbr/pipeline.py, which reads it from here) and linearly more uniform-set calls per frame; it is not a per-object cost.

Shadows: only slot 0 is ever sampled against a shadow map (see PBRPipeline._collect_lights - the shadow-casting DirectionalLight3D, if any, is always placed there). Every other slot is unshadowed. See graphics/pbr/lighting.py's module docstring for why 2D lights and non-slot-0 3D lights don't cast shadows yet.

LIGHTING_COMPOSITE_FRAG = f'@output{_LIT_ONLY_OUTPUT_PADDING}result: vec4@uniformgAlbedo: texturegEmmisive: texturegRoughness: texturegMetallic: texturegWorldPos: texturegWorldNormal: texture{_LIGHT_UNIFORM_BLOCK}@inputuv: vec2{_LIGHTING_FUNCTIONS}def main() -> void:world_pos4: vec4 = sample(gWorldPos, uv)if world_pos4.w < 0.5:result = vec4(0.0, 0.0, 0.0, 0.0)else:world_pos: vec3 = vec3(world_pos4.x, world_pos4.y, world_pos4.z)normal: vec3 = normalize(vec3(sample(gWorldNormal, uv).x, sample(gWorldNormal, uv).y, sample(gWorldNormal, uv).z))albedo4: vec4 = sample(gAlbedo, uv)albedo: vec3 = vec3(albedo4.x, albedo4.y, albedo4.z)emissive: vec3 = vec3(sample(gEmmisive, uv).x, sample(gEmmisive, uv).y, sample(gEmmisive, uv).z)roughness: float = clamp(sample(gRoughness, uv).x, 0.04, 1.0)metallic: float = sample(gMetallic, uv).xlit: vec3 = accumulate_lighting(world_pos, normal, ViewPos, albedo, roughness, metallic, emissive, Ambient)result = vec4(lit.x, lit.y, lit.z, albedo4.w)' module-attribute #

LIGHTING_COMPOSITE_VERT = '\n@uniform\nmodel: mat4\n\n@input\nvertex: vec3\nuvs: vec2\nnormal: vec3\n\n@output\nuv: vec2\n\ndef main():\n uv = uvs\n VERTEX_POSITION = model * vec4(vertex.x, vertex.y, vertex.z, 1.0)\n' module-attribute #

MAX_LIGHTS = 8 module-attribute #