From b8b4c89e04a89b5f501449e8d1a515f368666c01 Mon Sep 17 00:00:00 2001 From: Sascha Willems Date: Sat, 26 Apr 2025 14:50:10 +0200 Subject: [PATCH] Add slang shader for gltf sample --- shaders/slang/gltfloading/mesh.slang | 64 ++++++++++++++ shaders/slang/gltfscenerendering/scene.slang | 90 ++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 shaders/slang/gltfloading/mesh.slang create mode 100644 shaders/slang/gltfscenerendering/scene.slang diff --git a/shaders/slang/gltfloading/mesh.slang b/shaders/slang/gltfloading/mesh.slang new file mode 100644 index 00000000..7205d38f --- /dev/null +++ b/shaders/slang/gltfloading/mesh.slang @@ -0,0 +1,64 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; + float2 UV; + float3 Color; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float3 Color; + float2 UV; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + float4 lightPos; + float4 viewPos; +}; +ConstantBuffer ubo; + +[shader("vertex")] +VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) +{ + VSOutput output; + output.Normal = input.Normal; + output.Color = input.Color; + output.UV = input.UV; + output.Pos = mul(ubo.projection, mul(ubo.view, mul(modelMat, float4(input.Pos.xyz, 1.0)))); + + float4 pos = mul(ubo.view, mul(modelMat, float4(input.Pos.xyz, 1.0))); + output.Normal = mul((float3x3)ubo.view, input.Normal); + output.LightVec = ubo.lightPos.xyz - pos.xyz; + output.ViewVec = ubo.viewPos.xyz - pos.xyz; + return output; +} + +[[vk::binding(0, 1)]] Sampler2D samplerColorMap; + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); + + float3 N = normalize(input.Normal); + float3 L = normalize(input.LightVec); + float3 V = normalize(input.ViewVec); + float3 R = reflect(L, N); + float3 diffuse = max(dot(N, L), 0.0) * input.Color; + float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.75, 0.75, 0.75); + return float4(diffuse * color.rgb + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/gltfscenerendering/scene.slang b/shaders/slang/gltfscenerendering/scene.slang new file mode 100644 index 00000000..776d37ef --- /dev/null +++ b/shaders/slang/gltfscenerendering/scene.slang @@ -0,0 +1,90 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; + float2 UV; + float3 Color; + float4 Tangent; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float3 Color; + float2 UV; + float3 ViewVec; + float3 LightVec; + float4 Tangent; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + float4 lightPos; + float4 viewPos; +}; +ConstantBuffer ubo; + +struct PushConsts { + float4x4 model; +}; + +[[vk::binding(0, 1)]] Sampler2D samplerColorMap; +[[vk::binding(1, 1)]] Sampler2D samplerNormalMap; + +[SpecializationConstant] const bool ALPHA_MASK = false; +[SpecializationConstant] const float ALPHA_MASK_CUTOFF = 0.0; + +[shader("vertex")] +VSOutput vertexMain(VSInput input, uniform float4x4 modelMat) +{ + VSOutput output; + output.Normal = input.Normal; + output.Color = input.Color; + output.UV = input.UV; + output.Tangent = input.Tangent; + + float4x4 modelView = mul(ubo.view, modelMat); + + output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos.xyz, 1.0))); + + output.Normal = mul((float3x3)modelMat, input.Normal); + float4 pos = mul(modelMat, float4(input.Pos, 1.0)); + output.LightVec = ubo.lightPos.xyz - pos.xyz; + output.ViewVec = ubo.viewPos.xyz - pos.xyz; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float4 color = samplerColorMap.Sample(input.UV) * float4(input.Color, 1.0); + + if (ALPHA_MASK) { + if (color.a < ALPHA_MASK_CUTOFF) { + discard; + } + } + + float3 N = normalize(input.Normal); + float3 T = normalize(input.Tangent.xyz); + float3 B = cross(input.Normal, input.Tangent.xyz) * input.Tangent.w; + float3x3 TBN = float3x3(T, B, N); + N = mul(normalize(samplerNormalMap.Sample(input.UV).xyz * 2.0 - float3(1.0, 1.0, 1.0)), TBN); + + const float ambient = 0.1; + float3 L = normalize(input.LightVec); + float3 V = normalize(input.ViewVec); + float3 R = reflect(-L, N); + float3 diffuse = max(dot(N, L), ambient).rrr; + float3 specular = pow(max(dot(R, V), 0.0), 32.0); + return float4(diffuse * color.rgb + specular, color.a); +} \ No newline at end of file