Skip to content

Commit 8d50885

Browse files
committed
Added slang shaders for compute cull and lod sample
Adjusted vertex bindings
1 parent d8c8630 commit 8d50885

7 files changed

Lines changed: 175 additions & 4 deletions

File tree

24 Bytes
Binary file not shown.

shaders/glsl/computecullandlod/indirectdraw.vert

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ layout (location = 1) in vec3 inNormal;
66
layout (location = 2) in vec3 inColor;
77

88
// Instanced attributes
9-
layout (location = 4) in vec3 instancePos;
10-
layout (location = 5) in float instanceScale;
9+
layout (location = 3) in vec3 instancePos;
10+
layout (location = 4) in float instanceScale;
1111

1212
layout (binding = 0) uniform UBO
1313
{
0 Bytes
Binary file not shown.

shaders/hlsl/computecullandlod/indirectdraw.vert

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ struct VSInput
66
[[vk::location(1)]] float3 Normal : NORMAL0;
77
[[vk::location(2)]] float3 Color : COLOR0;
88
// Instanced attributes
9-
[[vk::location(4)]] float3 instancePos : TEXCOORD0;
10-
[[vk::location(5)]] float instanceScale : TEXCOORD1;
9+
[[vk::location(3)]] float3 instancePos : TEXCOORD0;
10+
[[vk::location(4)]] float instanceScale : TEXCOORD1;
1111
};
1212

1313
struct UBO
-1.51 KB
Binary file not shown.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
#define MAX_LOD_LEVEL_COUNT 6
8+
[[SpecializationConstant]] const int MAX_LOD_LEVEL = 5;
9+
10+
struct InstanceData
11+
{
12+
float3 pos;
13+
float scale;
14+
};
15+
StructuredBuffer<InstanceData> instances;
16+
17+
// Same layout as VkDrawIndexedIndirectCommand
18+
struct IndexedIndirectCommand
19+
{
20+
uint indexCount;
21+
uint instanceCount;
22+
uint firstIndex;
23+
uint vertexOffset;
24+
uint firstInstance;
25+
};
26+
RWStructuredBuffer<IndexedIndirectCommand> indirectDraws;
27+
28+
// Binding 2: Uniform block object with matrices
29+
struct UBO
30+
{
31+
float4x4 projection;
32+
float4x4 modelview;
33+
float4 cameraPos;
34+
float4 frustumPlanes[6];
35+
};
36+
ConstantBuffer<UBO> ubo;
37+
38+
// Binding 3: Indirect draw stats
39+
struct UBOOut
40+
{
41+
uint drawCount;
42+
uint lodCount[MAX_LOD_LEVEL_COUNT];
43+
};
44+
RWStructuredBuffer<UBOOut> uboOut;
45+
46+
// Binding 4: level-of-detail information
47+
struct LOD
48+
{
49+
uint firstIndex;
50+
uint indexCount;
51+
float distance;
52+
float _pad0;
53+
};
54+
StructuredBuffer<LOD> lods;
55+
56+
bool frustumCheck(float4 pos, float radius)
57+
{
58+
// Check sphere against frustum planes
59+
for (int i = 0; i < 6; i++)
60+
{
61+
if (dot(pos, ubo.frustumPlanes[i]) + radius < 0.0)
62+
{
63+
return false;
64+
}
65+
}
66+
return true;
67+
}
68+
69+
[shader("compute")]
70+
[numthreads(16, 1, 1)]
71+
void computeMain(uint3 GlobalInvocationID : SV_DispatchThreadID)
72+
{
73+
uint idx = GlobalInvocationID.x;
74+
uint temp;
75+
76+
// Clear stats on first invocation
77+
if (idx == 0)
78+
{
79+
InterlockedExchange(uboOut[0].drawCount, 0, temp);
80+
for (uint i = 0; i < MAX_LOD_LEVEL + 1; i++)
81+
{
82+
InterlockedExchange(uboOut[0].lodCount[i], 0, temp);
83+
}
84+
}
85+
86+
float4 pos = float4(instances[idx].pos.xyz, 1.0);
87+
88+
// Check if object is within current viewing frustum
89+
if (frustumCheck(pos, 1.0))
90+
{
91+
indirectDraws[idx].instanceCount = 1;
92+
93+
// Increase number of indirect draw counts
94+
InterlockedAdd(uboOut[0].drawCount, 1, temp);
95+
96+
// Select appropriate LOD level based on distance to camera
97+
uint lodLevel = MAX_LOD_LEVEL;
98+
for (uint i = 0; i < MAX_LOD_LEVEL; i++)
99+
{
100+
if (distance(instances[idx].pos.xyz, ubo.cameraPos.xyz) < lods[i].distance)
101+
{
102+
lodLevel = i;
103+
break;
104+
}
105+
}
106+
indirectDraws[idx].firstIndex = lods[lodLevel].firstIndex;
107+
indirectDraws[idx].indexCount = lods[lodLevel].indexCount;
108+
// Update stats
109+
InterlockedAdd(uboOut[0].lodCount[lodLevel], 1, temp);
110+
}
111+
else
112+
{
113+
indirectDraws[idx].instanceCount = 0;
114+
}
115+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright (c) 2025, Sascha Willems
2+
*
3+
* SPDX-License-Identifier: MIT
4+
*
5+
*/
6+
7+
struct VSInput
8+
{
9+
float4 Pos : POSITION0;
10+
float3 Normal;
11+
float3 Color;
12+
// Instanced attributes
13+
float3 instancePos;
14+
float instanceScale;
15+
};
16+
17+
struct VSOutput
18+
{
19+
float4 Pos : SV_POSITION;
20+
float3 Normal;
21+
float3 Color;
22+
float3 ViewVec;
23+
float3 LightVec;
24+
};
25+
26+
struct UBO
27+
{
28+
float4x4 projection;
29+
float4x4 modelview;
30+
};
31+
ConstantBuffer<UBO> ubo;
32+
33+
[shader("vertex")]
34+
VSOutput vertexMain(VSInput input)
35+
{
36+
VSOutput output;
37+
output.Color = input.Color;
38+
output.Normal = input.Normal;
39+
float4 pos = float4((input.Pos.xyz * input.instanceScale) + input.instancePos, 1.0);
40+
output.Pos = mul(ubo.projection, mul(ubo.modelview, pos));
41+
float4 wPos = mul(ubo.modelview, float4(pos.xyz, 1.0));
42+
float4 lPos = float4(0.0, 10.0, 50.0, 1.0);
43+
output.LightVec = lPos.xyz - pos.xyz;
44+
output.ViewVec = -pos.xyz;
45+
return output;
46+
}
47+
48+
[shader("fragment")]
49+
float4 fragmentMain(VSOutput input)
50+
{
51+
float3 N = normalize(input.Normal);
52+
float3 L = normalize(input.LightVec);
53+
float3 ambient = float3(0.25, 0.25, 0.25);
54+
float3 diffuse = max(dot(N, L), 0.0).xxx;
55+
return float4((ambient + diffuse) * input.Color, 1.0);
56+
}

0 commit comments

Comments
 (0)