Add Metal shaders for Quake 3 BSP

This commit is contained in:
2026-05-02 20:52:51 +01:00
parent 0baaf52d51
commit 9ec17a5302
4 changed files with 99 additions and 0 deletions
@@ -0,0 +1,46 @@
#include <metal_stdlib>
using namespace metal;
struct PBRUniforms {
float4 u_lightDir;
float4 u_lightColor;
float4 u_ambient;
float4 u_material;
float4 u_flashPos;
float4 u_flashDir;
float4 u_flashColor;
};
struct FragmentInput {
float4 position [[position]];
float2 uv;
float2 lightmapUv;
float3 worldNormal;
float3 worldPos;
float3 cameraPos;
};
fragment float4 main0(
FragmentInput in [[stage_in]],
texture2d<float> albedoTex [[texture(0)]],
sampler albedoSampler [[sampler(0)]],
texture2d<float> shadowMap [[texture(1)]],
sampler shadowSampler [[sampler(1)]],
texture2d<float> lightmapTex [[texture(2)]],
sampler lightmapSampler [[sampler(2)]],
constant PBRUniforms& pbr [[buffer(0)]])
{
(void)shadowMap;
(void)shadowSampler;
(void)in.worldNormal;
(void)in.worldPos;
(void)in.cameraPos;
float3 albedo = albedoTex.sample(albedoSampler, in.uv).rgb;
float3 lightmap = lightmapTex.sample(lightmapSampler, in.lightmapUv).rgb;
float overbright = (pbr.u_material.z > 0.0) ? pbr.u_material.z : 2.0;
float3 ambient = pbr.u_ambient.rgb * albedo;
float exposure = (pbr.u_lightColor.a > 0.0) ? pbr.u_lightColor.a : 1.0;
return float4((albedo * lightmap * overbright + ambient) * exposure, 1.0);
}
@@ -0,0 +1,43 @@
#include <metal_stdlib>
using namespace metal;
struct VertexUniforms {
float4x4 u_modelViewProj;
float4x4 u_model;
float4 u_surfaceNormal;
float4 u_uvScale;
float4 u_cameraPos;
float4x4 u_shadowVP;
};
struct VertexInput {
float3 position [[attribute(0)]];
float2 uv [[attribute(1)]];
float2 lightmapUv [[attribute(2)]];
float3 normal [[attribute(3)]];
};
struct VertexOutput {
float4 position [[position]];
float2 uv;
float2 lightmapUv;
float3 worldNormal;
float3 worldPos;
float3 cameraPos;
};
vertex VertexOutput main0(
VertexInput in [[stage_in]],
constant VertexUniforms& uniforms [[buffer(0)]])
{
VertexOutput out;
out.position = uniforms.u_modelViewProj * float4(in.position, 1.0);
out.uv = in.uv * uniforms.u_uvScale.xy;
out.lightmapUv = in.lightmapUv;
float4 worldPos = uniforms.u_model * float4(in.position, 1.0);
out.worldPos = worldPos.xyz;
out.worldNormal = (uniforms.u_model * float4(in.normal, 0.0)).xyz;
out.cameraPos = uniforms.u_cameraPos.xyz;
return out;
}
@@ -32,8 +32,17 @@ std::string WorkflowOverlayFpsStep::GetPluginId() const {
}
void WorkflowOverlayFpsStep::TryInit(SDL_GPUDevice* device, SDL_Window* window) {
if (disabled_) return;
device_ = device;
const char* driver = SDL_GetGPUDeviceDriver(device);
const std::string driverName = driver ? driver : "";
if (driverName != "vulkan") {
if (logger_) logger_->Warn("overlay.fps: SPIR-V overlay only supported on Vulkan, disabled for " + driverName);
disabled_ = true;
return;
}
auto loadSpv = [](const char* path) -> std::vector<uint8_t> {
std::ifstream f(path, std::ios::binary | std::ios::ate);
if (!f.is_open()) return {};
@@ -28,6 +28,7 @@ private:
std::shared_ptr<ILogger> logger_;
bool ready_ = false;
bool disabled_ = false;
bool vbuf_uploaded_ = false;
SDL_GPUGraphicsPipeline* pipeline_ = nullptr;
SDL_GPUTexture* tex_ = nullptr;