diff --git a/shaders/slang/texture/texture.slang b/shaders/slang/texture/texture.slang new file mode 100644 index 00000000..8c104e10 --- /dev/null +++ b/shaders/slang/texture/texture.slang @@ -0,0 +1,68 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float2 UV; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float2 UV; + float LodBias; + float3 Normal; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; + float4 viewPos; + float lodBias; +}; +ConstantBuffer ubo; + +Sampler2D samplerColor; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.UV = input.UV; + output.LodBias = ubo.lodBias; + + float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; + + output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); + + float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); + output.Normal = mul((float3x3)ubo.model, input.Normal); + float3 lightPos = float3(0.0, 0.0, 0.0); + float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); + output.LightVec = lPos - pos.xyz; + output.ViewVec = ubo.viewPos.xyz - pos.xyz; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float4 color = samplerColor.SampleLevel(input.UV, input.LodBias); + + 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) * float3(1.0, 1.0, 1.0); + float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; + + return float4(diffuse * color.rgb + specular, 1.0); +} diff --git a/shaders/slang/texture3d/texture3d.slang b/shaders/slang/texture3d/texture3d.slang new file mode 100644 index 00000000..c11208b9 --- /dev/null +++ b/shaders/slang/texture3d/texture3d.slang @@ -0,0 +1,66 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float2 UV; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 UV; + float3 Normal; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; + float4 viewPos; + float depth; +}; +ConstantBuffer ubo; + +Sampler3D samplerColor; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.UV = float3(input.UV, ubo.depth); + + float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; + + output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); + + float4 pos = mul(ubo.model, float4(input.Pos, 1.0)); + output.Normal = mul((float3x3)ubo.model, input.Normal); + float3 lightPos = float3(0.0, 0.0, 0.0); + float3 lPos = mul((float3x3)ubo.model, lightPos.xyz); + output.LightVec = lPos - pos.xyz; + output.ViewVec = ubo.viewPos.xyz - pos.xyz; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float4 color = samplerColor.Sample(input.UV); + + 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) * float3(1.0, 1.0, 1.0); + float specular = pow(max(dot(R, V), 0.0), 16.0) * color.r; + + return float4(diffuse * color.r + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/texturearray/instancing.slang b/shaders/slang/texturearray/instancing.slang new file mode 100644 index 00000000..6db77ac9 --- /dev/null +++ b/shaders/slang/texturearray/instancing.slang @@ -0,0 +1,49 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float2 UV; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 UV; +}; + +struct Instance +{ + float4x4 model; + float arrayIndex; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + Instance instance[8]; +}; +ConstantBuffer ubo; + +Sampler2DArray samplerArray; + +[shader("vertex")] +VSOutput vertexMain(VSInput input, uint InstanceIndex: SV_InstanceID) +{ + VSOutput output; + output.UV = float3(input.UV, ubo.instance[InstanceIndex].arrayIndex); + float4x4 modelView = mul(ubo.view, ubo.instance[InstanceIndex].model); + output.Pos = mul(ubo.projection, mul(modelView, float4(input.Pos, 1.0))); + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + return samplerArray.Sample(input.UV); +} \ No newline at end of file diff --git a/shaders/slang/texturecubemap/reflect.slang b/shaders/slang/texturecubemap/reflect.slang new file mode 100644 index 00000000..ffeda065 --- /dev/null +++ b/shaders/slang/texturecubemap/reflect.slang @@ -0,0 +1,70 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 WorldPos; + float3 Normal; + float LodBias; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; + float4x4 invModel; + float lodBias; +}; +ConstantBuffer ubo; + +SamplerCube samplerColor; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); + + output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; + output.Normal = mul((float3x3)ubo.model, input.Normal); + output.LodBias = ubo.lodBias; + + float3 lightPos = float3(0.0f, -5.0f, 5.0f); + output.LightVec = lightPos.xyz - output.WorldPos.xyz; + output.ViewVec = -output.WorldPos; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) : SV_TARGET +{ + float3 cI = normalize (input.ViewVec); + float3 cR = reflect (cI, normalize(input.Normal)); + + cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; + // Convert cubemap coordinates into Vulkan coordinate space + cR.z *= -1.0; + + float4 color = samplerColor.SampleLevel(cR, input.LodBias); + + float3 N = normalize(input.Normal); + float3 L = normalize(input.LightVec); + float3 V = normalize(input.ViewVec); + float3 R = reflect(-L, N); + float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; + float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); + float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); + return float4(ambient + diffuse * color.rgb + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/texturecubemap/skybox.slang b/shaders/slang/texturecubemap/skybox.slang new file mode 100644 index 00000000..618fb2f3 --- /dev/null +++ b/shaders/slang/texturecubemap/skybox.slang @@ -0,0 +1,47 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 UVW; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; +}; +ConstantBuffer ubo; + +SamplerCube samplerCubeMap; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.UVW = input.Pos; + // Convert cubemap coordinates into Vulkan coordinate space + output.UVW.xy *= -1.0; + // Remove translation from view matrix + float4x4 viewMat = ubo.model; + viewMat[0][3] = 0.0; + viewMat[1][3] = 0.0; + viewMat[2][3] = 0.0; + output.Pos = mul(ubo.projection, mul(viewMat, float4(input.Pos.xyz, 1.0))); + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + return samplerCubeMap.Sample(input.UVW); +} \ No newline at end of file diff --git a/shaders/slang/texturecubemaparray/reflect.slang b/shaders/slang/texturecubemaparray/reflect.slang new file mode 100644 index 00000000..1edb34b3 --- /dev/null +++ b/shaders/slang/texturecubemaparray/reflect.slang @@ -0,0 +1,68 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 WorldPos; + float3 Normal; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; + float4x4 invModel; + float lodBias; + int cubeMapIndex; +}; +ConstantBuffer ubo; + +SamplerCubeArray samplerCubeMapArray; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Pos = mul(ubo.projection, mul(ubo.model, float4(input.Pos.xyz, 1.0))); + + output.WorldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; + output.Normal = mul((float3x3)ubo.model, input.Normal); + + float3 lightPos = float3(0.0f, -5.0f, 5.0f); + output.LightVec = lightPos.xyz - output.WorldPos.xyz; + output.ViewVec = -output.WorldPos; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float3 cI = normalize(input.WorldPos.xyz); + float3 cR = reflect(cI, normalize(input.Normal)); + + cR = mul(ubo.invModel, float4(cR, 0.0)).xyz; + cR.yz *= -1.0; + + float4 color = samplerCubeMapArray.SampleLevel(float4(cR, ubo.cubeMapIndex), ubo.lodBias); + + float3 N = normalize(input.Normal); + float3 L = normalize(input.LightVec); + float3 V = normalize(input.ViewVec); + float3 R = reflect(-L, N); + float3 ambient = float3(0.5, 0.5, 0.5) * color.rgb; + float3 diffuse = max(dot(N, L), 0.0) * float3(1.0, 1.0, 1.0); + float3 specular = pow(max(dot(R, V), 0.0), 16.0) * float3(0.5, 0.5, 0.5); + return float4(ambient + diffuse * color.rgb + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/texturecubemaparray/skybox.slang b/shaders/slang/texturecubemaparray/skybox.slang new file mode 100644 index 00000000..f7686993 --- /dev/null +++ b/shaders/slang/texturecubemaparray/skybox.slang @@ -0,0 +1,49 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 UVW; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; + float4x4 invModel; + float lodBias; + int cubeMapIndex; +}; +ConstantBuffer ubo; + +SamplerCubeArray samplerCubeMapArray; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.UVW = input.Pos; + output.UVW.xy *= -1.0; + // Remove translation from view matrix + float4x4 viewMat = ubo.model; + viewMat[0][3] = 0.0; + viewMat[1][3] = 0.0; + viewMat[2][3] = 0.0; + output.Pos = mul(ubo.projection, mul(viewMat, float4(input.Pos.xyz, 1.0))); + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + return samplerCubeMapArray.SampleLevel(float4(input.UVW, ubo.cubeMapIndex), ubo.lodBias); +} \ No newline at end of file diff --git a/shaders/slang/texturemipmapgen/texture.slang b/shaders/slang/texturemipmapgen/texture.slang new file mode 100644 index 00000000..41aaca50 --- /dev/null +++ b/shaders/slang/texturemipmapgen/texture.slang @@ -0,0 +1,68 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float2 UV; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float2 UV; + float LodBias; + float3 Normal; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + float4x4 model; + float4 viewPos; + float lodBias; + int samplerIndex; +}; +ConstantBuffer ubo; + +Texture2D textureColor; +SamplerState samplers[3]; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.UV = input.UV * float2(2.0, 1.0); + output.LodBias = ubo.lodBias; + + float3 worldPos = mul(ubo.model, float4(input.Pos, 1.0)).xyz; + + output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); + + output.Normal = mul((float3x3)ubo.model, input.Normal); + float3 lightPos = float3(-30.0, 0.0, 0.0); + output.LightVec = worldPos - lightPos; + output.ViewVec = ubo.viewPos.xyz - worldPos; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float4 color = textureColor.Sample(samplers[ubo.samplerIndex], input.UV, int2(0, 0), input.LodBias); + + 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.65) * float3(1.0, 1.0, 1.0); + float specular = pow(max(dot(R, V), 0.0), 16.0) * color.a; + return float4(diffuse * color.r + specular, 1.0); +} \ No newline at end of file