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