mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-04 10:44:52 +00:00
feat(gameengine): add minimal BSP shaders so quake3 package can render
Quake 3 package was missing GPU shaders entirely. With these in place, the engine boots quake3 successfully: pak0 loads, BSP parses, lightmap atlas and geometry build, and shaders compile/bind correctly on the Vulkan path. bsp.vert: matches BspRenderVertex layout (position/uv/lmuv/normal) and re-uses the existing VertexUniformData uniform block from the seed pipeline so no C++ changes are needed. bsp.frag: classic Q3 model — albedo × lightmap × overbright + ambient. Skips PBR / shadow mapping entirely; Q3's baked lightmaps already encode direct + bounce lighting and shadowing. Q3 shader-script effects (animated sky, scrolling water, env-mapped chrome) render flat — adding them is a follow-up. SPIR-V only for now (Windows/Vulkan/D3D12 via SDL3 cross-compile). MSL and DXIL still missing for Mac/native-D3D12 paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#version 450
|
||||
|
||||
// Quake 3 BSP fragment shader (minimal).
|
||||
// Q3 bakes radiosity into a lightmap atlas at compile time, so runtime lighting
|
||||
// is just: albedo × lightmap × overbright. The classic Q3 "overbright bits = 1"
|
||||
// doubles lightmap intensity — modern screens are brighter, so we expose it as
|
||||
// part of the existing FragmentUniformData.material slot (z) with a 2.0 default.
|
||||
//
|
||||
// Fragment sampler bindings come from workflow_draw_map_step.cpp BSP path:
|
||||
// set=2 binding=0 albedo (per-surface diffuse from extracted pk3 textures)
|
||||
// set=2 binding=1 shadowMap (shadow map — ignored for BSP, lightmap is canonical)
|
||||
// set=2 binding=2 lightmap (shared atlas built by bsp.lightmap_atlas)
|
||||
|
||||
layout(set = 2, binding = 0) uniform sampler2D albedoTex;
|
||||
layout(set = 2, binding = 1) uniform sampler2D shadowMap;
|
||||
layout(set = 2, binding = 2) uniform sampler2D lightmapTex;
|
||||
|
||||
layout(set = 3, binding = 0) uniform PBRUniforms {
|
||||
vec4 u_lightDir;
|
||||
vec4 u_lightColor; // a = exposure
|
||||
vec4 u_ambient;
|
||||
vec4 u_material; // z = lightmap overbright multiplier (defaults via C++)
|
||||
vec4 u_flashPos;
|
||||
vec4 u_flashDir;
|
||||
vec4 u_flashColor;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec2 v_uv;
|
||||
layout(location = 1) in vec2 v_lmuv;
|
||||
layout(location = 2) in vec3 v_worldNormal;
|
||||
layout(location = 3) in vec3 v_worldPos;
|
||||
layout(location = 4) in vec3 v_cameraPos;
|
||||
|
||||
layout(location = 0) out vec4 o_color;
|
||||
|
||||
void main() {
|
||||
vec3 albedo = texture(albedoTex, v_uv).rgb;
|
||||
vec3 lightmap = texture(lightmapTex, v_lmuv).rgb;
|
||||
|
||||
// Q3 overbright. material.z falls back to 2.0 (engine pushes 0 today, so
|
||||
// fall through to a sane default rather than rendering a black map).
|
||||
float overbright = (u_material.z > 0.0) ? u_material.z : 2.0;
|
||||
|
||||
vec3 ambient = u_ambient.rgb * albedo;
|
||||
vec3 lit = albedo * lightmap * overbright + ambient;
|
||||
|
||||
float exposure = (u_lightColor.a > 0.0) ? u_lightColor.a : 1.0;
|
||||
o_color = vec4(lit * exposure, 1.0);
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
#version 450
|
||||
|
||||
// Quake 3 BSP vertex shader (minimal).
|
||||
// Vertex format `position_uv_lmuv_normal` (BspRenderVertex):
|
||||
// loc 0: vec3 position
|
||||
// loc 1: vec2 diffuse uv
|
||||
// loc 2: vec2 lightmap uv (already atlas-remapped by bsp.lightmap_atlas step)
|
||||
// loc 3: vec3 world-space normal
|
||||
// Uniform layout matches sdl3cpp::services::rendering::VertexUniformData
|
||||
// so the same C++ uniform push call used by the seed pipeline works here.
|
||||
|
||||
layout(location = 0) in vec3 a_position;
|
||||
layout(location = 1) in vec2 a_uv;
|
||||
layout(location = 2) in vec2 a_lmuv;
|
||||
layout(location = 3) in vec3 a_normal;
|
||||
|
||||
layout(set = 1, binding = 0) uniform VertexUniforms {
|
||||
mat4 u_modelViewProj;
|
||||
mat4 u_model;
|
||||
vec4 u_surfaceNormal; // unused for BSP — per-vertex normal wins
|
||||
vec4 u_uvScale;
|
||||
vec4 u_cameraPos;
|
||||
mat4 u_shadowVP; // unused for BSP — lightmap already encodes shadowing
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 v_uv;
|
||||
layout(location = 1) out vec2 v_lmuv;
|
||||
layout(location = 2) out vec3 v_worldNormal;
|
||||
layout(location = 3) out vec3 v_worldPos;
|
||||
layout(location = 4) out vec3 v_cameraPos;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_modelViewProj * vec4(a_position, 1.0);
|
||||
v_uv = a_uv * u_uvScale.xy;
|
||||
v_lmuv = a_lmuv;
|
||||
vec4 wp = u_model * vec4(a_position, 1.0);
|
||||
v_worldPos = wp.xyz;
|
||||
v_worldNormal = mat3(u_model) * a_normal;
|
||||
v_cameraPos = u_cameraPos.xyz;
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user