Files
Destrum/destrum/include/destrum/Graphics/Renderer.h
T

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