diff --git a/shaders/slang/multithreading/phong.slang b/shaders/slang/multithreading/phong.slang new file mode 100644 index 00000000..ad82f3af --- /dev/null +++ b/shaders/slang/multithreading/phong.slang @@ -0,0 +1,54 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; + float3 Color; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float3 Color; + float3 ViewVec; + float3 LightVec; +}; + +[shader("vertex")] +VSOutput vertexMain(VSInput input, uniform float4x4 mvp, uniform float3 color) +{ + VSOutput output; + if ((input.Color.r == 1.0) && (input.Color.g == 0.0) && (input.Color.b == 0.0)) + { + output.Color = color; + } + else + { + output.Color = input.Color; + } + output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); + float4 pos = mul(mvp, float4(input.Pos, 1.0)); + output.Normal = mul((float3x3)mvp, input.Normal); + float3 lPos = float3(0.0, 0.0, 0.0); + output.LightVec = lPos - pos.xyz; + output.ViewVec = -pos.xyz; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + 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), 8.0) * float3(0.75, 0.75, 0.75); + return float4(diffuse + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/multithreading/starsphere.slang b/shaders/slang/multithreading/starsphere.slang new file mode 100644 index 00000000..2d6c492f --- /dev/null +++ b/shaders/slang/multithreading/starsphere.slang @@ -0,0 +1,58 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +#define HASHSCALE3 float3(443.897, 441.423, 437.195) +#define STARFREQUENCY 0.01 + +// Hash function by Dave Hoskins (https://www.shadertoy.com/view/4djSRW) +float hash33(float3 p3) +{ + p3 = frac(p3 * HASHSCALE3); + p3 += dot(p3, p3.yxz+float3(19.19, 19.19, 19.19)); + return frac((p3.x + p3.y)*p3.z + (p3.x+p3.z)*p3.y + (p3.y+p3.z)*p3.x); +} + +float3 starField(float3 pos) +{ + float3 color = float3(0.0, 0.0, 0.0); + float threshhold = (1.0 - STARFREQUENCY); + float rnd = hash33(pos); + if (rnd >= threshhold) + { + float starCol = pow((rnd - threshhold) / (1.0 - threshhold), 16.0); + color += starCol.xxx; + } + return color; +} + +struct VSInput +{ + float3 Pos; +} + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 UVW; +}; + +[shader("vertex")] +VSOutput vertexMain(VSInput input, uniform float4x4 mvp) +{ + VSOutput output; + output.UVW = input.Pos; + output.Pos = mul(mvp, float4(input.Pos.xyz, 1.0)); + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + // Fake atmosphere at the bottom + float3 atmosphere = clamp(float3(0.1, 0.15, 0.4) * (input.UVW.y + 0.25), 0.0, 1.0); + float3 color = starField(input.UVW) + atmosphere; + return float4(color, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/offscreen/mirror.slang b/shaders/slang/offscreen/mirror.slang new file mode 100644 index 00000000..49cf8791 --- /dev/null +++ b/shaders/slang/offscreen/mirror.slang @@ -0,0 +1,68 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float4 ProjCoord; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + float4x4 model; +}; +ConstantBuffer ubo; + +Sampler2D samplerColor; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.ProjCoord = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos.xyz, 1.0)))); + output.Pos = output.ProjCoord; + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input, bool FrontFacing : SV_IsFrontFace) +{ + float4 tmp = (1.0 / input.ProjCoord.w).xxxx; + float4 projCoord = input.ProjCoord * tmp; + + // Scale and bias + projCoord += float4(1.0, 1.0, 1.0, 1.0); + projCoord *= float4(0.5, 0.5, 0.5, 0.5); + + // Slow single pass blur + // For demonstration purposes only + const float blurSize = 1.0 / 512.0; + + float4 color = float4(float3(0.0, 0.0, 0.0), 1.); + + if (FrontFacing) + { + // Only render mirrored scene on front facing (upper) side of mirror surface + float4 reflection = float4(0.0, 0.0, 0.0, 0.0); + for (int x = -3; x <= 3; x++) + { + for (int y = -3; y <= 3; y++) + { + reflection += samplerColor.Sample(float2(projCoord.x + x * blurSize, projCoord.y + y * blurSize)) / 49.0; + } + } + color += reflection; + } + + return color; +} \ No newline at end of file diff --git a/shaders/slang/offscreen/phong.slang b/shaders/slang/offscreen/phong.slang new file mode 100644 index 00000000..e8743485 --- /dev/null +++ b/shaders/slang/offscreen/phong.slang @@ -0,0 +1,63 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Color; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float ClipDistance : SV_ClipDistance0; + float3 Normal; + float3 Color; + float3 EyePos; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 view; + float4x4 model; + float4 lightPos; +}; +ConstantBuffer ubo; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Normal = input.Normal; + output.Color = input.Color; + output.Pos = mul(ubo.projection, mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0)))); + output.EyePos = mul(ubo.view, mul(ubo.model, float4(input.Pos, 1.0))).xyz; + output.LightVec = normalize(ubo.lightPos.xyz - output.EyePos); + // Clip against reflection plane + float4 clipPlane = float4(0.0, 0.0, 0.0, 0.0); + output.ClipDistance = dot(float4(input.Pos, 1.0), clipPlane); + return output; +} + + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + float3 Eye = normalize(-input.EyePos); + float3 Reflected = normalize(reflect(-input.LightVec, input.Normal)); + float4 IAmbient = float4(0.1, 0.1, 0.1, 1.0); + float4 IDiffuse = max(dot(input.Normal, input.LightVec), 0.0).xxxx; + float specular = 0.75; + float4 ISpecular = float4(0.0, 0.0, 0.0, 0.0); + if (dot(input.EyePos, input.Normal) < 0.0) + { + ISpecular = float4(0.5, 0.5, 0.5, 1.0) * pow(max(dot(Reflected, Eye), 0.0), 16.0) * specular; + } + return float4((IAmbient + IDiffuse) * float4(input.Color, 1.0) + ISpecular); +} \ No newline at end of file diff --git a/shaders/slang/offscreen/quad.slang b/shaders/slang/offscreen/quad.slang new file mode 100644 index 00000000..49b0ebf7 --- /dev/null +++ b/shaders/slang/offscreen/quad.slang @@ -0,0 +1,28 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float2 UV; +}; + +[[vk::binding(1, 0)]] Sampler2D samplerColor; + +[shader("vertex")] +VSOutput vertexMain(uint VertexIndex: SV_VertexID) +{ + VSOutput output; + output.UV = float2((VertexIndex << 1) & 2, VertexIndex & 2); + output.Pos = float4(output.UV * 2.0f - 1.0f, 0.0f, 1.0f); + return output; +} + +[shader("fragment")] +float4 fragmentMain(VSOutput input) +{ + return samplerColor.Sample(input.UV); +} \ No newline at end of file