feat: add forward+ rendering
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#ifndef LIGHTCOMPONENT_H
|
||||
#define LIGHTCOMPONENT_H
|
||||
|
||||
#include <destrum/ObjectModel/Component.h>
|
||||
#include <destrum/Graphics/Light.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class LightComponent final : public Component {
|
||||
public:
|
||||
explicit LightComponent(GameObject& parent, LightType type = LightType::Point);
|
||||
|
||||
LightComponent(const LightComponent& other) = delete;
|
||||
LightComponent(LightComponent&& other) noexcept = delete;
|
||||
LightComponent& operator=(const LightComponent& other) = delete;
|
||||
LightComponent& operator=(LightComponent&& other) noexcept = delete;
|
||||
|
||||
void Render(const RenderContext& ctx) override;
|
||||
|
||||
std::string GetTypeName() const override { return "LightComponent"; }
|
||||
|
||||
nlohmann::json Serialize() const override;
|
||||
void Deserialize(const nlohmann::json& data) override;
|
||||
void ImGuiInspector() override;
|
||||
|
||||
void SetType(LightType type) { m_Type = type; }
|
||||
[[nodiscard]] LightType GetType() const { return m_Type; }
|
||||
|
||||
void SetColor(const glm::vec3& color) { m_Color = color; }
|
||||
[[nodiscard]] const glm::vec3& GetColor() const { return m_Color; }
|
||||
|
||||
void SetIntensity(float intensity);
|
||||
[[nodiscard]] float GetIntensity() const { return m_Intensity; }
|
||||
|
||||
void SetRange(float range);
|
||||
[[nodiscard]] float GetRange() const { return m_Range; }
|
||||
|
||||
void SetConeAngles(float innerConeAngle, float outerConeAngle);
|
||||
[[nodiscard]] float GetInnerConeAngle() const { return m_InnerConeAngle; }
|
||||
[[nodiscard]] float GetOuterConeAngle() const { return m_OuterConeAngle; }
|
||||
|
||||
private:
|
||||
LightType m_Type{LightType::Point};
|
||||
glm::vec3 m_Color{1.0f};
|
||||
float m_Intensity{1.0f};
|
||||
float m_Range{10.0f};
|
||||
float m_InnerConeAngle{0.35f};
|
||||
float m_OuterConeAngle{0.5f};
|
||||
};
|
||||
|
||||
#endif // LIGHTCOMPONENT_H
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef LIGHT_H
|
||||
#define LIGHT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
enum class LightType : std::uint32_t {
|
||||
Directional = 0,
|
||||
Point = 1,
|
||||
Spot = 2,
|
||||
};
|
||||
|
||||
struct Light {
|
||||
LightType type{LightType::Point};
|
||||
|
||||
glm::vec3 position{0.0f};
|
||||
glm::vec3 direction{0.0f, -1.0f, 0.0f};
|
||||
|
||||
glm::vec3 color{1.0f};
|
||||
float intensity{1.0f};
|
||||
|
||||
float range{10.0f};
|
||||
|
||||
float innerConeAngle{0.35f};
|
||||
float outerConeAngle{0.5f};
|
||||
};
|
||||
|
||||
struct GPULight {
|
||||
glm::vec3 position;
|
||||
float range;
|
||||
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
|
||||
glm::vec3 direction;
|
||||
std::uint32_t type;
|
||||
|
||||
float spotInnerCos;
|
||||
float spotOuterCos;
|
||||
glm::vec2 padding;
|
||||
};
|
||||
|
||||
static_assert(sizeof(GPULight) == 64, "GPULight must match the struct in lights.glsl");
|
||||
|
||||
#endif //LIGHT_H
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef LIGHTCULLINGPIPELINE_H
|
||||
#define LIGHTCULLINGPIPELINE_H
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <destrum/Graphics/ComputePipeline.h>
|
||||
#include <destrum/Graphics/Light.h>
|
||||
#include <destrum/Graphics/ids.h>
|
||||
#include <destrum/Graphics/Resources/AppendableBuffer.h>
|
||||
#include <destrum/Graphics/Resources/Buffer.h>
|
||||
|
||||
class GfxDevice;
|
||||
class RenderResources;
|
||||
|
||||
class LightCullingPipeline final {
|
||||
public:
|
||||
|
||||
static constexpr std::uint32_t TILE_SIZE = 16;
|
||||
static constexpr std::uint32_t MAX_LIGHTS_PER_TILE = 255;
|
||||
static constexpr std::uint32_t TILE_STRIDE = MAX_LIGHTS_PER_TILE + 1;
|
||||
|
||||
static constexpr std::size_t MAX_LIGHTS = 1024;
|
||||
|
||||
void init(GfxDevice& gfxDevice, RenderResources& resources, glm::ivec2 drawImageSize);
|
||||
void cleanup(GfxDevice& gfxDevice);
|
||||
|
||||
void resize(GfxDevice& gfxDevice, glm::ivec2 drawImageSize);
|
||||
|
||||
void beginDrawing(std::size_t frameIndex);
|
||||
void appendLight(const Light& light);
|
||||
|
||||
void flushCurrentFrame(VkCommandBuffer cmd, GfxDevice& gfxDevice);
|
||||
|
||||
void cullLights(
|
||||
VkCommandBuffer cmd,
|
||||
const RenderResources& resources,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
ImageID depthImageId,
|
||||
VkExtent2D renderExtent);
|
||||
|
||||
[[nodiscard]] VkDeviceAddress getLightsBufferAddress() const;
|
||||
[[nodiscard]] VkDeviceAddress getTileLightIndicesBufferAddress() const { return tileLightIndicesBuffer.address; }
|
||||
|
||||
[[nodiscard]] std::uint32_t getNumLights() const;
|
||||
[[nodiscard]] glm::uvec2 getTileCount() const { return tileCount; }
|
||||
|
||||
private:
|
||||
void createTileBuffer(GfxDevice& gfxDevice, glm::ivec2 drawImageSize);
|
||||
|
||||
VkPipelineLayout m_pipelineLayout{VK_NULL_HANDLE};
|
||||
std::unique_ptr<ComputePipeline> lightCullingPipeline;
|
||||
|
||||
struct PushConstants {
|
||||
VkDeviceAddress sceneDataBuffer;
|
||||
glm::uvec2 screenSize;
|
||||
std::uint32_t depthTexId;
|
||||
std::uint32_t padding;
|
||||
};
|
||||
|
||||
struct PerFrameData {
|
||||
AppendableBuffer<GPULight> lightsBuffer;
|
||||
};
|
||||
|
||||
std::array<PerFrameData, FRAMES_IN_FLIGHT> framesData;
|
||||
std::size_t currentFrameIndex{0};
|
||||
bool warnedAboutLightLimit{false};
|
||||
|
||||
GPUBuffer tileLightIndicesBuffer;
|
||||
glm::uvec2 tileCount{0u, 0u};
|
||||
|
||||
PerFrameData& getCurrentFrameData();
|
||||
const PerFrameData& getCurrentFrameData() const;
|
||||
};
|
||||
|
||||
#endif //LIGHTCULLINGPIPELINE_H
|
||||
@@ -27,6 +27,15 @@ public:
|
||||
VkFormat drawImageFormat,
|
||||
VkFormat depthImageFormat);
|
||||
|
||||
void drawDepthPrepass(
|
||||
VkCommandBuffer cmd,
|
||||
VkExtent2D renderExtent,
|
||||
const RenderResources& resources,
|
||||
const Camera& camera,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
const std::vector<MeshDrawCommand>& drawCommands,
|
||||
const std::vector<std::size_t>& sortedDrawCommands);
|
||||
|
||||
void draw(
|
||||
VkCommandBuffer cmd,
|
||||
VkExtent2D renderExtent,
|
||||
@@ -55,9 +64,20 @@ private:
|
||||
std::uint32_t padding;
|
||||
};
|
||||
|
||||
void drawMeshes(
|
||||
VkCommandBuffer cmd,
|
||||
const Pipeline& pipeline,
|
||||
VkExtent2D renderExtent,
|
||||
const RenderResources& resources,
|
||||
const Camera& camera,
|
||||
const GPUBuffer& sceneDataBuffer,
|
||||
const std::vector<MeshDrawCommand>& drawCommands,
|
||||
const std::vector<std::size_t>& sortedDrawCommands);
|
||||
|
||||
private:
|
||||
VkPipelineLayout m_pipelineLayout{VK_NULL_HANDLE};
|
||||
std::unique_ptr<Pipeline> m_pipeline;
|
||||
std::unique_ptr<Pipeline> m_depthPrepassPipeline;
|
||||
|
||||
bool m_renderWireframe{false};
|
||||
};
|
||||
|
||||
@@ -35,7 +35,6 @@ private:
|
||||
struct SkyboxPushConstants {
|
||||
glm::mat4 invViewProj;
|
||||
glm::vec4 skyboxRot[3];
|
||||
glm::vec3 cameraPos;
|
||||
std::uint32_t skyboxTextureId;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,7 +57,10 @@ public:
|
||||
BindlessSetManager& getBindlessSetManager();
|
||||
VkDescriptorSetLayout getBindlessDescSetLayout() const;
|
||||
const VkDescriptorSet& getBindlessDescSet() const;
|
||||
void bindBindlessDescSet(VkCommandBuffer cmd, VkPipelineLayout layout) const;
|
||||
void bindBindlessDescSet(
|
||||
VkCommandBuffer cmd,
|
||||
VkPipelineLayout layout,
|
||||
VkPipelineBindPoint bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS) const;
|
||||
|
||||
MeshCache& meshes() { return *meshCache; }
|
||||
const MeshCache& meshes() const { return *meshCache; }
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
#include <destrum/Graphics/Camera.h>
|
||||
#include <destrum/Graphics/Light.h>
|
||||
#include <destrum/Graphics/Pipelines/LightCullingPipeline.h>
|
||||
#include <destrum/Graphics/Pipelines/LineRenderingPass.h>
|
||||
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
||||
#include <destrum/Graphics/Pipelines/QuadRendererPass.h>
|
||||
@@ -20,9 +22,11 @@
|
||||
|
||||
#include "Pipelines/SkyboxPipeline.h"
|
||||
|
||||
class GameRenderer {
|
||||
class GameRenderer
|
||||
{
|
||||
public:
|
||||
struct SceneData {
|
||||
struct SceneData
|
||||
{
|
||||
const Camera& camera;
|
||||
glm::vec3 ambientColor;
|
||||
float ambientIntensity;
|
||||
@@ -40,11 +44,15 @@ public:
|
||||
void cleanup(GfxDevice& gfxDevice);
|
||||
|
||||
void drawMesh(MeshID id, const glm::mat4& transform, MaterialID materialId);
|
||||
void drawSkinnedMesh(MeshID id, const glm::mat4& transform, MaterialID materialId, SkinnedMesh* skinnedMesh, std::size_t jointMatricesStartIndex);
|
||||
void drawSkinnedMesh(MeshID id, const glm::mat4& transform, MaterialID materialId, SkinnedMesh* skinnedMesh,
|
||||
std::size_t jointMatricesStartIndex);
|
||||
void submitLight(const Light& light);
|
||||
const GPUImage& getDrawImage() const;
|
||||
|
||||
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize) {
|
||||
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize)
|
||||
{
|
||||
createDrawImage(gfxDevice, newSize, false);
|
||||
lightCullingPipeline->resize(gfxDevice, newSize);
|
||||
}
|
||||
|
||||
Material& getMaterialMutable(MaterialID id);
|
||||
@@ -54,18 +62,31 @@ public:
|
||||
|
||||
void flushMaterialUpdates(GfxDevice& gfxDevice);
|
||||
|
||||
[[nodiscard]] SkinningPipeline& getSkinningPipeline() const {
|
||||
[[nodiscard]] SkinningPipeline& getSkinningPipeline() const
|
||||
{
|
||||
return *skinningPipeline;
|
||||
}
|
||||
|
||||
void setRenderWireframe(bool wireframe) {
|
||||
void setRenderWireframe(bool wireframe)
|
||||
{
|
||||
meshPipeline->setRenderWireframe(wireframe);
|
||||
}
|
||||
|
||||
bool getRenderWireframe() {
|
||||
bool getRenderWireframe()
|
||||
{
|
||||
return meshPipeline->getRenderWireframe();
|
||||
}
|
||||
|
||||
void setRenderLightHeatmap(bool heatmap)
|
||||
{
|
||||
renderLightHeatmap = heatmap;
|
||||
}
|
||||
|
||||
bool getRenderLightHeatmap() const
|
||||
{
|
||||
return renderLightHeatmap;
|
||||
}
|
||||
|
||||
RenderResources* getResources()
|
||||
{
|
||||
return resources;
|
||||
@@ -96,33 +117,41 @@ private:
|
||||
VkSampleCountFlagBits samples{VK_SAMPLE_COUNT_1_BIT};
|
||||
|
||||
|
||||
struct GPUSceneData {
|
||||
// camera
|
||||
struct GPUSceneData
|
||||
{
|
||||
glm::mat4 view;
|
||||
glm::mat4 proj;
|
||||
glm::mat4 invProj;
|
||||
glm::mat4 viewProj;
|
||||
glm::vec4 cameraPos;
|
||||
|
||||
// ambient
|
||||
glm::vec3 ambientColor;
|
||||
float ambientIntensity;
|
||||
|
||||
// fog
|
||||
glm::vec3 fogColor;
|
||||
float fogDensity;
|
||||
|
||||
VkDeviceAddress materialsBuffer;
|
||||
|
||||
VkDeviceAddress lightsBuffer;
|
||||
VkDeviceAddress tileLightIndicesBuffer;
|
||||
std::uint32_t numLights;
|
||||
std::uint32_t tileCountX;
|
||||
std::uint32_t debugLightHeatmap;
|
||||
std::uint32_t padding;
|
||||
};
|
||||
|
||||
NBuffer sceneDataBuffer;
|
||||
|
||||
|
||||
std::unique_ptr<MeshPipeline> meshPipeline;
|
||||
std::unique_ptr<SkyboxPipeline> skyboxPipeline;
|
||||
std::unique_ptr<LineRenderingPass> lineRenderingPass;
|
||||
std::unique_ptr<QuadRendererPass> quadRendererPass;
|
||||
|
||||
std::unique_ptr<SkinningPipeline> skinningPipeline;
|
||||
std::unique_ptr<LightCullingPipeline> lightCullingPipeline;
|
||||
|
||||
bool renderLightHeatmap{false};
|
||||
bool initialized{false};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#ifndef DESTRUM_ENGINECOMPONENTLIST_H
|
||||
#define DESTRUM_ENGINECOMPONENTLIST_H
|
||||
|
||||
// Keep the component manifest in one place. Consumers define X before
|
||||
// expanding one of these lists to generate registration or other metadata.
|
||||
#include <destrum/Components/Animator.h>
|
||||
#include <destrum/Components/LightComponent.h>
|
||||
#include <destrum/Components/MeshRendererComponent.h>
|
||||
#include <destrum/Components/OrbitAndSpin.h>
|
||||
#include <destrum/Components/Rotator.h>
|
||||
@@ -15,6 +14,7 @@
|
||||
|
||||
#define DESTRUM_ENGINE_COMPONENTS(X) \
|
||||
X(MeshRendererComponent) \
|
||||
X(LightComponent) \
|
||||
X(Rotator) \
|
||||
X(Spinner) \
|
||||
X(OrbitAndSpin) \
|
||||
|
||||
@@ -22,11 +22,8 @@ public:
|
||||
static bool Load(Scene& scene, const std::filesystem::path& path,
|
||||
std::function<void(float)> progressCallback = nullptr);
|
||||
|
||||
// Thread-safe: parse and validate a scene file on any thread.
|
||||
// No engine state is touched during parsing.
|
||||
static LoadResult LoadSceneFile(const std::filesystem::path& path);
|
||||
|
||||
// Main-thread-only: construct a scene from pre-validated JSON.
|
||||
static bool ConstructScene(Scene& scene, LoadResult& result,
|
||||
std::function<void(float)> progressCallback = nullptr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user