204 lines
5.5 KiB
C++
204 lines
5.5 KiB
C++
#ifndef RENDERER_H
|
|
#define RENDERER_H
|
|
|
|
#include <glm/mat4x4.hpp>
|
|
#include <glm/vec3.hpp>
|
|
|
|
#include <destrum/Graphics/Camera.h>
|
|
#include <destrum/Graphics/IndirectDrawList.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/Renderer2DPass.h>
|
|
#include <destrum/Graphics/Pipelines/ShadowMapPipeline.h>
|
|
#include <destrum/Graphics/ids.h>
|
|
#include <destrum/Graphics/MeshDrawCommand.h>
|
|
#include <destrum/Graphics/Resources/NBuffer.h>
|
|
#include <destrum/Graphics/RenderResources.h>
|
|
|
|
|
|
#include <array>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <vector>
|
|
|
|
#include <destrum/Graphics/Pipelines/SkinningPipeline.h>
|
|
|
|
#include "Pipelines/SkyboxPipeline.h"
|
|
|
|
class GameRenderer
|
|
{
|
|
public:
|
|
struct DrawStats
|
|
{
|
|
std::uint32_t meshDraws{0};
|
|
std::uint32_t indirectCommands{0};
|
|
std::uint32_t instances{0};
|
|
std::uint32_t mainViewCommands{0};
|
|
std::uint32_t mainViewInstances{0};
|
|
};
|
|
|
|
struct SceneData
|
|
{
|
|
const Camera& camera;
|
|
glm::vec3 ambientColor;
|
|
float ambientIntensity;
|
|
glm::vec3 fogColor;
|
|
float fogDensity;
|
|
float skyboxRotation{0.0f}; // radians around the world up axis
|
|
};
|
|
|
|
explicit GameRenderer();
|
|
|
|
void init(GfxDevice& gfxDevice, RenderResources& _resources, glm::ivec2 drawImageSize);
|
|
void beginDrawing(GfxDevice& gfxDevice);
|
|
void endDrawing();
|
|
|
|
void draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera, const SceneData& sceneData);
|
|
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 submitLight(const Light& light);
|
|
const GPUImage& getDrawImage() const;
|
|
|
|
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize)
|
|
{
|
|
createDrawImage(gfxDevice, newSize, false);
|
|
lightCullingPipeline->resize(gfxDevice, newSize);
|
|
}
|
|
|
|
Material& getMaterialMutable(MaterialID id);
|
|
void updateMaterialGPU(MaterialID id);
|
|
|
|
void setSkyboxTexture(ImageID skyboxImageId);
|
|
|
|
|
|
[[nodiscard]] SkinningPipeline& getSkinningPipeline() const
|
|
{
|
|
return *skinningPipeline;
|
|
}
|
|
|
|
void setRenderWireframe(bool wireframe)
|
|
{
|
|
meshPipeline->setRenderWireframe(wireframe);
|
|
}
|
|
|
|
bool getRenderWireframe()
|
|
{
|
|
return meshPipeline->getRenderWireframe();
|
|
}
|
|
|
|
void setRenderLightHeatmap(bool heatmap)
|
|
{
|
|
renderLightHeatmap = heatmap;
|
|
}
|
|
|
|
bool getRenderLightHeatmap() const
|
|
{
|
|
return renderLightHeatmap;
|
|
}
|
|
|
|
void setShadowDistance(float distance)
|
|
{
|
|
shadowMapPipeline->setShadowDistance(distance);
|
|
}
|
|
|
|
float getShadowDistance() const
|
|
{
|
|
return shadowMapPipeline->getShadowDistance();
|
|
}
|
|
|
|
RenderResources* getResources()
|
|
{
|
|
return resources;
|
|
}
|
|
|
|
[[nodiscard]] const DrawStats& getDrawStats() const { return lastDrawStats; }
|
|
|
|
void draw2D(
|
|
VkCommandBuffer cmd,
|
|
GfxDevice& gfxDevice,
|
|
const glm::mat4& projection);
|
|
|
|
private:
|
|
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
|
void uploadLights(const Camera& camera);
|
|
[[nodiscard]] std::uint32_t assignShadowIndex(const Light& light, const Frustum& cameraFrustum);
|
|
|
|
RenderResources* resources = nullptr;
|
|
|
|
void recordMaterialUpdates(VkCommandBuffer cmd);
|
|
|
|
std::vector<MaterialID> pendingMaterialUploads;
|
|
|
|
|
|
std::vector<MeshDrawCommand> meshDrawCommands;
|
|
std::vector<std::size_t> sortedMeshDrawCommands;
|
|
IndirectDrawList drawList;
|
|
DrawStats lastDrawStats;
|
|
|
|
VkFormat drawImageFormat{VK_FORMAT_R16G16B16A16_SFLOAT};
|
|
VkFormat depthImageFormat{VK_FORMAT_D32_SFLOAT};
|
|
|
|
ImageID drawImageId{NULL_IMAGE_ID};
|
|
ImageID depthImageId{NULL_IMAGE_ID};
|
|
|
|
VkSampleCountFlagBits samples{VK_SAMPLE_COUNT_1_BIT};
|
|
|
|
|
|
struct GPUSceneData
|
|
{
|
|
glm::mat4 view;
|
|
glm::mat4 proj;
|
|
glm::mat4 invProj;
|
|
glm::mat4 viewProj;
|
|
glm::vec4 cameraPos;
|
|
|
|
glm::vec3 ambientColor;
|
|
float ambientIntensity;
|
|
|
|
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 shadowMapId;
|
|
float shadowNormalOffset;
|
|
std::uint32_t padding;
|
|
glm::mat4 lightViewProj;
|
|
|
|
std::uint32_t spotShadowAtlasId;
|
|
std::uint32_t spotShadowTilesPerRow;
|
|
std::array<GPUSpotShadow, ShadowMapPipeline::MAX_SPOT_SHADOWS> spotShadows;
|
|
};
|
|
|
|
NBuffer sceneDataBuffer;
|
|
|
|
std::unique_ptr<MeshPipeline> meshPipeline;
|
|
std::unique_ptr<SkyboxPipeline> skyboxPipeline;
|
|
std::unique_ptr<LineRenderingPass> lineRenderingPass;
|
|
std::unique_ptr<Renderer2DPass> renderer2DPass;
|
|
|
|
std::unique_ptr<SkinningPipeline> skinningPipeline;
|
|
std::unique_ptr<LightCullingPipeline> lightCullingPipeline;
|
|
std::unique_ptr<ShadowMapPipeline> shadowMapPipeline;
|
|
|
|
std::optional<glm::vec3> shadowLightDirection;
|
|
std::vector<Light> submittedLights;
|
|
std::vector<GPUSpotShadow> spotShadows;
|
|
|
|
bool renderLightHeatmap{false};
|
|
bool initialized{false};
|
|
};
|
|
|
|
#endif //RENDERER_H
|