Skip to content

Commit ca43995

Browse files
committed
Add: Startup of ShadowMap Example
1 parent 5a1f735 commit ca43995

9 files changed

Lines changed: 578 additions & 4 deletions

File tree

examples/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(EOS_EXAMPLES_DEPENDENCIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies)
22
add_subdirectory(ModelPBR)
33
add_subdirectory(Triangle)
4-
add_subdirectory(MultiDrawIndirect)
4+
add_subdirectory(MultiDrawIndirect)
5+
add_subdirectory(ShadowMapping)

examples/MultiDrawIndirect/src/main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ int main()
3737
{
3838
.Config = { .EnableValidationLayers = true },
3939
.PreferredHardwareType = EOS::HardwareDeviceType::Discrete,
40-
.ApplicationName = "EOS - Model PBR",
40+
.ApplicationName = "EOS - MultiDrawIndirect",
4141
};
4242

4343
CameraDescription cameraDescription
@@ -216,7 +216,7 @@ int main()
216216
cmdUpdateBuffer(cmdBuffer, perFrameBuffer, perFrameData);
217217
cmdBeginRendering(cmdBuffer, renderPass, framebuffer);
218218
{
219-
cmdPushMarker(cmdBuffer, "Damaged Helmet", 0xff0000ff);
219+
cmdPushMarker(cmdBuffer, "Sponza", 0xff0000ff);
220220
cmdBindVertexBuffer(cmdBuffer, 0, vertexBuffer);
221221
cmdBindIndexBuffer(cmdBuffer, indexBuffer, EOS::IndexFormat::UI32);
222222
cmdBindRenderPipeline(cmdBuffer, renderPipelineHandle);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE_EXAMPLE(ShadowMapping)
2+
FETCH_ASSIMP(${EOS_EXAMPLES_DEPENDENCIES_DIR} ShadowMapping)
3+
FETCH_GLM(${EOS_EXAMPLES_DEPENDENCIES_DIR} ShadowMapping)
Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
#include "../../common.h"
2+
#include "EOS.h"
3+
#include "logger.h"
4+
#include "shaders/shaderUtils.h"
5+
#include "utils.h"
6+
7+
struct PerFrameData final
8+
{
9+
glm::mat4 model;
10+
glm::mat4 mvp;
11+
glm::mat4 depthMVP;
12+
glm::vec4 lightPos;
13+
glm::vec3 cameraPos;
14+
uint32_t shadowMapID;
15+
uint64_t drawDataPtr;
16+
};
17+
18+
struct DrawData final
19+
{
20+
uint32_t albedoID;
21+
uint32_t normalID;
22+
uint32_t metallicRoughnessID;
23+
uint32_t pad;
24+
};
25+
26+
struct Vertex final
27+
{
28+
glm::vec3 position;
29+
glm::vec3 normal;
30+
glm::vec2 uv;
31+
glm::vec4 tangent;
32+
};
33+
34+
int main()
35+
{
36+
EOS::ContextCreationDescription contextDescr
37+
{
38+
.Config = { .EnableValidationLayers = true },
39+
.PreferredHardwareType = EOS::HardwareDeviceType::Discrete,
40+
.ApplicationName = "EOS - ShadowMapping",
41+
};
42+
43+
CameraDescription cameraDescription
44+
{
45+
.origin = {0.0f, 10.0f, -3.5f},
46+
.rotation = {0, 0.0f},
47+
.acceleration = 200.0f
48+
};
49+
50+
ExampleAppDescription appDescription
51+
{
52+
.contextDescription = contextDescr,
53+
.cameraDescription = cameraDescription
54+
};
55+
56+
ExampleApp App{appDescription};
57+
58+
EOS::Holder<EOS::ShaderModuleHandle> shaderHandleVert = EOS::LoadShader(App.Context, App.ShaderCompiler, "modelAlbedo", EOS::ShaderStage::Vertex);
59+
EOS::Holder<EOS::ShaderModuleHandle> shaderHandleFrag = EOS::LoadShader(App.Context, App.ShaderCompiler, "modelAlbedo", EOS::ShaderStage::Fragment);
60+
61+
EOS::Holder<EOS::ShaderModuleHandle> shaderHandleShadowVert = EOS::LoadShader(App.Context, App.ShaderCompiler, "shadowDepth", EOS::ShaderStage::Vertex);
62+
EOS::Holder<EOS::ShaderModuleHandle> shaderHandleShadowFrag = EOS::LoadShader(App.Context, App.ShaderCompiler, "shadowDepth", EOS::ShaderStage::Fragment);
63+
64+
//TODO: This could be constevaled with reflection
65+
constexpr EOS::VertexInputData vdesc
66+
{
67+
.Attributes =
68+
{
69+
{ .Location = 0, .Format = EOS::VertexFormat::Float3, .Offset = offsetof(Vertex, position) },
70+
{ .Location = 1, .Format = EOS::VertexFormat::Float3, .Offset = offsetof(Vertex, normal) },
71+
{ .Location = 2, .Format = EOS::VertexFormat::Float2, .Offset = offsetof(Vertex, uv) },
72+
{ .Location = 3, .Format = EOS::VertexFormat::Float4, .Offset = offsetof(Vertex, tangent) }
73+
},
74+
75+
.InputBindings =
76+
{
77+
{ .Stride = sizeof(Vertex) }
78+
}
79+
};
80+
81+
EOS::Holder<EOS::TextureHandle> depthTexture = App.CreateDepthTexture();
82+
83+
EOS::Holder<EOS::TextureHandle> shadowDepthTexture = App.Context->CreateTexture(
84+
{
85+
.Type = EOS::ImageType::Image_2D,
86+
.TextureFormat = EOS::Format::Z_F32,
87+
.TextureDimensions = {2048, 2048},
88+
.Usage = EOS::TextureUsageFlags::Attachment | EOS::TextureUsageFlags::Sampled,
89+
.DebugName = "Depth Buffer",
90+
});
91+
92+
93+
Scene scene = LoadModel("../data/sponza/Sponza.gltf", App.Context.get());
94+
std::vector<Vertex> vertices;
95+
vertices.reserve(scene.vertices.size());
96+
for (const VertexInformation& vertexInfo : scene.vertices) vertices.emplace_back(vertexInfo.position, vertexInfo.normal, vertexInfo.uv, vertexInfo.tangent);
97+
98+
99+
EOS::Holder<EOS::BufferHandle> vertexBuffer = App.Context->CreateBuffer(
100+
{
101+
.Usage = EOS::BufferUsageFlags::Vertex,
102+
.Storage = EOS::StorageType::Device,
103+
.Size = sizeof(Vertex) * vertices.size(),
104+
.Data = vertices.data(),
105+
.DebugName = "Buffer: vertex"
106+
});
107+
108+
EOS::Holder<EOS::BufferHandle> indexBuffer = App.Context->CreateBuffer(
109+
{
110+
.Usage = EOS::BufferUsageFlags::Index,
111+
.Storage = EOS::StorageType::Device,
112+
.Size = sizeof(uint32_t) * scene.indices.size(),
113+
.Data = scene.indices.data(),
114+
.DebugName = "Buffer: index"
115+
});
116+
117+
std::vector<DrawData> drawData;
118+
drawData.reserve(scene.meshes.size());
119+
for (auto& mesh : scene.meshes)
120+
{
121+
drawData.push_back({
122+
.albedoID = mesh.textures.albedo.Index(),
123+
.normalID = mesh.textures.normal.Index(),
124+
.metallicRoughnessID = mesh.textures.metallicRoughness.Index(),
125+
});
126+
}
127+
128+
EOS::Holder<EOS::BufferHandle> drawDataBuffer = App.Context->CreateBuffer({
129+
.Usage = EOS::BufferUsageFlags::StorageFlag,
130+
.Storage = EOS::StorageType::HostVisible,
131+
.Size = sizeof(DrawData) * drawData.size(),
132+
.Data = drawData.data(),
133+
.DebugName = "drawDataBuffer",
134+
});
135+
136+
EOS::Holder<EOS::BufferHandle> perFrameBuffer = App.Context->CreateBuffer(
137+
{
138+
.Usage = EOS::BufferUsageFlags::StorageFlag,
139+
.Storage = EOS::StorageType::HostVisible,
140+
.Size = sizeof(PerFrameData),
141+
.DebugName = "perFrameBuffer",
142+
});
143+
144+
std::vector<EOS::DrawIndexedIndirectCommand> indirectCmds;
145+
indirectCmds.reserve(scene.meshes.size());
146+
for (auto& mesh : scene.meshes)
147+
{
148+
indirectCmds.emplace_back(
149+
EOS::DrawIndexedIndirectCommand
150+
{
151+
.indexCount = mesh.indexCount,
152+
.instanceCount = 1,
153+
.firstIndex = mesh.indexOffset,
154+
.vertexOffset = static_cast<int32_t>(mesh.vertexOffset),
155+
.firstInstance = 0,
156+
});
157+
}
158+
159+
EOS::Holder<EOS::BufferHandle> indirectBuffer = App.Context->CreateBuffer({
160+
.Usage = EOS::BufferUsageFlags::Indirect,
161+
.Storage = EOS::StorageType::Device,
162+
.Size = sizeof(EOS::DrawIndexedIndirectCommand) * indirectCmds.size(),
163+
.Data = indirectCmds.data(),
164+
.DebugName = "indirectBuffer",
165+
});
166+
167+
168+
//It would be nice if these pipeline descriptions would be stored as JSON/XML into the material system
169+
EOS::RenderPipelineDescription renderPipelineShade
170+
{
171+
.VertexInput = vdesc,
172+
.VertexShader = shaderHandleVert,
173+
.FragmentShader = shaderHandleFrag,
174+
.ColorAttachments = {{ .ColorFormat = App.Context->GetSwapchainFormat()}},
175+
.DepthFormat = EOS::Format::Z_F32, //TODO depthTexture->Format
176+
.PipelineCullMode = EOS::CullMode::Back,
177+
.DebugName = "Basic Render Pipeline",
178+
};
179+
EOS::Holder<EOS::RenderPipelineHandle> renderPipelineHandle = App.Context->CreateRenderPipeline(renderPipelineShade);
180+
181+
EOS::RenderPipelineDescription renderPipelineShadow
182+
{
183+
.VertexInput = vdesc,
184+
.VertexShader = shaderHandleShadowVert,
185+
.FragmentShader = shaderHandleShadowFrag,
186+
.ColorAttachments = {},
187+
.DepthFormat = EOS::Format::Z_F32, //TODO depthTexture->Format
188+
.PipelineCullMode = EOS::CullMode::Back,
189+
.DebugName = "ShadowMap Render Pipeline",
190+
};
191+
EOS::Holder<EOS::RenderPipelineHandle> renderPipelineShadowHandle = App.Context->CreateRenderPipeline(renderPipelineShadow);
192+
193+
194+
const glm::mat4 m = glm::scale(glm::mat4(1.0f), glm::vec3(0.04f));
195+
constexpr glm::vec3 lightPos = glm::vec3(10.0f, 10.0f, 0.0f);
196+
197+
198+
// Matrix from light's point of view
199+
constexpr float lightFOV = 90.0f;
200+
constexpr float zNear = 0.01f;
201+
constexpr float zFar = 100.0f;
202+
const glm::mat4 depthProjectionMatrix = glm::perspective(glm::radians(lightFOV), 1.0f, zNear, zFar);
203+
const glm::mat4 depthViewMatrix = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0, 1, 0));
204+
const glm::mat4 depthModelMatrix = m;//glm::mat4(1.0f);
205+
const glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix;
206+
207+
208+
209+
App.Run([&]()
210+
{
211+
const float aspectRatio = static_cast<float>(App.Window.Width) / static_cast<float>(App.Window.Height);
212+
213+
214+
const glm::mat4 mvp = App.MainCamera.GetViewProjectionMatrix(aspectRatio) * m;
215+
216+
const PerFrameData perFrameData
217+
{
218+
.model = m,
219+
.mvp = mvp,
220+
.depthMVP = depthMVP,
221+
.lightPos = glm::vec4(lightPos, 1.0f),
222+
.cameraPos = App.MainCamera.GetPosition(),
223+
.shadowMapID = shadowDepthTexture.Index(),
224+
.drawDataPtr = App.Context->GetGPUAddress(drawDataBuffer)
225+
};
226+
227+
EOS::ICommandBuffer& cmdBuffer = App.Context->AcquireCommandBuffer();
228+
229+
230+
EOS::Framebuffer framebufferShadow
231+
{
232+
.DepthStencil = { .Texture = shadowDepthTexture },
233+
.DebugName = "ShadowMap framebuffer"
234+
};
235+
236+
237+
EOS::Framebuffer framebufferShade
238+
{
239+
.Color = {{.Texture = App.Context->GetSwapChainTexture()}},
240+
.DepthStencil = { .Texture = depthTexture },
241+
.DebugName = "Basic Color Depth Framebuffer",
242+
};
243+
244+
constexpr EOS::RenderPass renderPass
245+
{
246+
.Color { { .LoadOpState = EOS::LoadOp::Clear, .ClearColor = { 0.36f, 0.4f, 1.0f, 0.28f } } },
247+
.Depth{ .LoadOpState = EOS::LoadOp::Clear, .ClearDepth = 1.0f }
248+
};
249+
250+
constexpr EOS::RenderPass shadowRenderPass
251+
{
252+
.Depth{ .LoadOpState = EOS::LoadOp::Clear, .ClearDepth = 1.0f }
253+
};
254+
255+
constexpr EOS::DepthState depthState
256+
{
257+
.CompareOpState = EOS::CompareOp::Less,
258+
.IsDepthWriteEnabled = true,
259+
};
260+
261+
cmdPipelineBarrier(cmdBuffer, {},
262+
{
263+
{ App.Context->GetSwapChainTexture(), EOS::ResourceState::Undefined, EOS::ResourceState::RenderTarget },
264+
{ depthTexture, EOS::ResourceState::Undefined, EOS::ResourceState::DepthWrite },
265+
{ shadowDepthTexture, EOS::ResourceState::Undefined, EOS::ResourceState::DepthWrite },
266+
});
267+
268+
cmdUpdateBuffer(cmdBuffer, perFrameBuffer, perFrameData);
269+
270+
struct FramePointers
271+
{
272+
uint64_t draw;
273+
}pc
274+
{
275+
.draw = App.Context->GetGPUAddress(perFrameBuffer)
276+
};
277+
278+
cmdPushMarker(cmdBuffer, "Shadow Pass", 0xff0000ff);
279+
cmdBeginRendering(cmdBuffer, shadowRenderPass, framebufferShadow);
280+
{
281+
cmdBindVertexBuffer(cmdBuffer, 0, vertexBuffer);
282+
cmdBindIndexBuffer(cmdBuffer, indexBuffer, EOS::IndexFormat::UI32);
283+
cmdBindRenderPipeline(cmdBuffer, renderPipelineShadowHandle);
284+
cmdPushConstants(cmdBuffer, pc);
285+
cmdSetDepthState(cmdBuffer, depthState);
286+
cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, 0, scene.meshes.size());
287+
}
288+
cmdEndRendering(cmdBuffer);
289+
cmdPopMarker(cmdBuffer);
290+
291+
//Transition Shadow Depth to Shader Resource
292+
cmdPipelineBarrier(cmdBuffer, {},{{ shadowDepthTexture, EOS::ResourceState::DepthWrite, EOS::ResourceState::ShaderResource },});
293+
294+
cmdPushMarker(cmdBuffer, "Shade Pass", 0xff0000ff);
295+
cmdBeginRendering(cmdBuffer, renderPass, framebufferShade);
296+
{
297+
cmdBindVertexBuffer(cmdBuffer, 0, vertexBuffer);
298+
cmdBindIndexBuffer(cmdBuffer, indexBuffer, EOS::IndexFormat::UI32);
299+
cmdBindRenderPipeline(cmdBuffer, renderPipelineHandle);
300+
cmdPushConstants(cmdBuffer, pc);
301+
cmdSetDepthState(cmdBuffer, depthState);
302+
cmdDrawIndexedIndirect(cmdBuffer, indirectBuffer, 0, scene.meshes.size());
303+
}
304+
cmdEndRendering(cmdBuffer);
305+
cmdPopMarker(cmdBuffer);
306+
307+
cmdPipelineBarrier(cmdBuffer, {}, {{App.Context->GetSwapChainTexture(), EOS::ResourceState::RenderTarget, EOS::ResourceState::Present}});
308+
App.Context->Submit(cmdBuffer, App.Context->GetSwapChainTexture());
309+
});
310+
311+
return 0;
312+
}

0 commit comments

Comments
 (0)