diff --git a/shaders/slang/_rename.py b/shaders/slang/_rename.py index 5b6e61d1..f24457fb 100644 --- a/shaders/slang/_rename.py +++ b/shaders/slang/_rename.py @@ -7,6 +7,11 @@ from shutil import move def checkRenameFiles(samplename): mappings = {} match samplename: + case "geometryshader": + mappings = { + "normaldebug.vert.spv": "base.vert.spv", + "normaldebug.frag.spv": "base.frag.spv", + } case "raytracingbasic": mappings = { "raytracingbasic.rchit.spv": "closesthit.rchit.spv", @@ -18,6 +23,10 @@ def checkRenameFiles(samplename): "raytracingreflections.rchit.spv": "closesthit.rchit.spv", "raytracingreflections.rmiss.spv": "miss.rmiss.spv", "raytracingreflections.rgen.spv": "raygen.rgen.spv", - } + } + case "viewportarray": + mappings = { + "scene.geom.spv": "multiview.geom.spv", + } for x, y in mappings.items(): move(samplename + "\\" + x, samplename + "\\" + y) diff --git a/shaders/slang/compileshaders.py b/shaders/slang/compileshaders.py index 9582c1a9..5a6faf94 100644 --- a/shaders/slang/compileshaders.py +++ b/shaders/slang/compileshaders.py @@ -46,13 +46,15 @@ def getShaderStages(filename): if '[shader("closesthit")]' in filecontent: stages.append("closesthit") if '[shader("callable")]' in filecontent: - stages.append("callable") + stages.append("callable") if '[shader("compute")]' in filecontent: - stages.append("compute") + stages.append("compute") if '[shader("amplification")]' in filecontent: - stages.append("amplification") + stages.append("amplification") if '[shader("mesh")]' in filecontent: - stages.append("mesh") + stages.append("mesh") + if '[shader("geometry")]' in filecontent: + stages.append("geometry") f.close() return stages @@ -64,7 +66,7 @@ compile_single_sample = "" if args.sample != None: compile_single_sample = args.sample if (not os.path.isdir(compile_single_sample)): - print("ERROR: No directory found with name %s" % compile_single_sample) + print("ERROR: No directory found with name %s" % compile_single_sample) exit(-1) dir_path = os.path.dirname(os.path.realpath(__file__)) @@ -105,6 +107,8 @@ for root, dirs, files in os.walk(dir_path): output_ext = ".mesh" case "amplification": output_ext = ".task" + case "geometry": + output_ext = ".geom" output_file = output_base_file_name + output_ext + ".spv" output_file = output_file.replace(".slang", "") res = subprocess.call("%s %s -profile spirv_1_4 -matrix-layout-column-major -target spirv -o %s -entry %s -stage %s -warnings-disable 39001" % (compiler_path, input_file, output_file, entry_point, stage), shell=True) diff --git a/shaders/slang/geometryshader/mesh.slang b/shaders/slang/geometryshader/mesh.slang new file mode 100644 index 00000000..fbe1e977 --- /dev/null +++ b/shaders/slang/geometryshader/mesh.slang @@ -0,0 +1,58 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float4 Pos; + float3 Normal; + float3 Color; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float3 Normal; + float3 Color; + float3 ViewVec; + float3 LightVec; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; +}; +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.model, input.Pos)); + + float4 pos = mul(ubo.model, float4(input.Pos.xyz, 1.0)); + output.Normal = mul((float4x3)ubo.model, input.Normal).xyz; + + float3 lightPos = float3(1.0f, -1.0f, 1.0f); + output.LightVec = lightPos.xyz - 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 ambient = float3(0.1, 0.1, 0.1); + 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.75, 0.75, 0.75); + return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/geometryshader/normaldebug.slang b/shaders/slang/geometryshader/normaldebug.slang new file mode 100644 index 00000000..9b244d8d --- /dev/null +++ b/shaders/slang/geometryshader/normaldebug.slang @@ -0,0 +1,68 @@ +/* Copyright (c) 2025, Sascha Willems + * + * SPDX-License-Identifier: MIT + * + */ + +struct VSInput +{ + float3 Pos; + float3 Normal; +}; + +struct VSOutput +{ + float4 Pos : POSITION0; + float3 Normal; +}; + +struct GSOutput +{ + float4 Pos : SV_POSITION; + float3 Color; +}; + +struct UBO +{ + float4x4 projection; + float4x4 model; +}; +ConstantBuffer ubo; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Normal = input.Normal; + output.Pos = float4(input.Pos.xyz, 1.0); + return output; +} + +[shader("geometry")] +[maxvertexcount(6)] +void geometryMain(triangle VSOutput input[3], inout LineStream outStream) +{ + float normalLength = 0.02; + for(int i=0; i<3; i++) + { + float3 pos = input[i].Pos.xyz; + float3 normal = input[i].Normal.xyz; + + GSOutput output = (GSOutput)0; + output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos, 1.0))); + output.Color = float3(1.0, 0.0, 0.0); + outStream.Append( output ); + + output.Pos = mul(ubo.projection, mul(ubo.model, float4(pos + normal * normalLength, 1.0))); + output.Color = float3(0.0, 0.0, 1.0); + outStream.Append( output ); + + outStream.RestartStrip(); + } +} + +[shader("fragment")] +float4 fragmentMain(GSOutput input) +{ + return float4(input.Color, 1.0); +} \ No newline at end of file diff --git a/shaders/slang/viewportarray/scene.slang b/shaders/slang/viewportarray/scene.slang new file mode 100644 index 00000000..e6b6eb7e --- /dev/null +++ b/shaders/slang/viewportarray/scene.slang @@ -0,0 +1,90 @@ +/* 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; +}; + +struct GSOutput +{ + float4 Pos : SV_POSITION; + uint ViewportIndex : SV_ViewportArrayIndex; + uint PrimitiveID : SV_PrimitiveID; + float3 Normal; + float3 Color; + float3 ViewVec; + float3 LightVec; +} + +struct UBO +{ + float4x4 projection[2]; + float4x4 modelview[2]; + float4 lightPos; +}; +ConstantBuffer ubo; + +[shader("vertex")] +VSOutput vertexMain(VSInput input) +{ + VSOutput output; + output.Color = input.Color; + output.Normal = input.Normal; + output.Pos = float4(input.Pos.xyz, 1.0); + return output; +} + +[shader("geometry")] +[maxvertexcount(3)] +[instance(2)] +void geometryMain(triangle VSOutput input[3], inout TriangleStream outStream, uint InvocationID: SV_GSInstanceID, uint PrimitiveID: SV_PrimitiveID) +{ + for (int i = 0; i < 3; i++) + { + GSOutput output; + output.Normal = mul((float3x3)ubo.modelview[InvocationID], input[i].Normal); + output.Color = input[i].Color; + + float4 pos = input[i].Pos; + float4 worldPos = mul(ubo.modelview[InvocationID], pos); + + float3 lPos = mul(ubo.modelview[InvocationID], ubo.lightPos).xyz; + output.LightVec = lPos - worldPos.xyz; + output.ViewVec = -worldPos.xyz; + + output.Pos = mul(ubo.projection[InvocationID], worldPos); + + // Set the viewport index that the vertex will be emitted to + output.ViewportIndex = InvocationID; + output.PrimitiveID = PrimitiveID; + outStream.Append(output); + } + + outStream.RestartStrip(); +} + +[shader("fragment")] +float4 fragmentMain(GSOutput input) +{ + float3 N = normalize(input.Normal); + float3 L = normalize(input.LightVec); + float3 V = normalize(input.ViewVec); + float3 R = reflect(-L, N); + float3 ambient = float3(0.1, 0.1, 0.1); + 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.75, 0.75, 0.75); + return float4((ambient + diffuse) * input.Color.rgb + specular, 1.0); +} \ No newline at end of file