refactor: move all caches to RenderResources object
This commit is contained in:
@@ -19,16 +19,17 @@ set(SRC_FILES
|
|||||||
"src/Graphics/ComputePipeline.cpp"
|
"src/Graphics/ComputePipeline.cpp"
|
||||||
"src/Graphics/Frustum.cpp"
|
"src/Graphics/Frustum.cpp"
|
||||||
"src/Graphics/GfxDevice.cpp"
|
"src/Graphics/GfxDevice.cpp"
|
||||||
"src/Graphics/ImageCache.cpp"
|
"src/Graphics/Caches/ImageCache.cpp"
|
||||||
"src/Graphics/ImageLoader.cpp"
|
"src/Graphics/ImageLoader.cpp"
|
||||||
"src/Graphics/ImmediateExecuter.cpp"
|
"src/Graphics/ImmediateExecuter.cpp"
|
||||||
"src/Graphics/Init.cpp"
|
"src/Graphics/Init.cpp"
|
||||||
"src/Graphics/MaterialCache.cpp"
|
"src/Graphics/Caches/MaterialCache.cpp"
|
||||||
"src/Graphics/MeshCache.cpp"
|
"src/Graphics/MeshCache.cpp"
|
||||||
"src/Graphics/Pipeline.cpp"
|
"src/Graphics/Pipeline.cpp"
|
||||||
"src/Graphics/Renderer.cpp"
|
"src/Graphics/Renderer.cpp"
|
||||||
"src/Graphics/Swapchain.cpp"
|
"src/Graphics/Swapchain.cpp"
|
||||||
"src/Graphics/Util.cpp"
|
"src/Graphics/Util.cpp"
|
||||||
|
"src/Graphics/RenderResources.cpp"
|
||||||
|
|
||||||
"src/Graphics/Resources/GPUImage.cpp"
|
"src/Graphics/Resources/GPUImage.cpp"
|
||||||
"src/Graphics/Resources/NBuffer.cpp"
|
"src/Graphics/Resources/NBuffer.cpp"
|
||||||
|
|||||||
@@ -43,13 +43,13 @@ protected:
|
|||||||
AppParams m_params{};
|
AppParams m_params{};
|
||||||
|
|
||||||
GfxDevice gfxDevice;
|
GfxDevice gfxDevice;
|
||||||
|
GameRenderer renderer;
|
||||||
|
RenderResources resources;
|
||||||
|
|
||||||
ImguiPass imguiPass;
|
ImguiPass imguiPass;
|
||||||
|
|
||||||
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
|
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
|
||||||
|
|
||||||
MeshCache meshCache;
|
|
||||||
MaterialCache materialCache;
|
|
||||||
|
|
||||||
bool isRunning{false};
|
bool isRunning{false};
|
||||||
bool gamePaused{false};
|
bool gamePaused{false};
|
||||||
|
|
||||||
|
|||||||
+14
-6
@@ -10,15 +10,23 @@
|
|||||||
|
|
||||||
class GfxDevice;
|
class GfxDevice;
|
||||||
|
|
||||||
|
struct MaterialDefaultTextures {
|
||||||
|
ImageID white = NULL_IMAGE_ID;
|
||||||
|
ImageID normal = NULL_IMAGE_ID;
|
||||||
|
ImageID metallicRoughness = NULL_IMAGE_ID;
|
||||||
|
ImageID emissive = NULL_IMAGE_ID;
|
||||||
|
};
|
||||||
|
|
||||||
class MaterialCache {
|
class MaterialCache {
|
||||||
friend class ResourcesInspector;
|
friend class ResourcesInspector;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(GfxDevice& gfxDevice);
|
void init(GfxDevice& gfxDevice, MaterialDefaultTextures defaults);
|
||||||
|
|
||||||
void cleanup(GfxDevice& gfxDevice);
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
|
|
||||||
MaterialID addMaterial(GfxDevice& gfxDevice, Material material);
|
MaterialID addMaterial(Material material);
|
||||||
MaterialID addSimpleTextureMaterial(GfxDevice& gfxDevice, ImageID textureID);
|
MaterialID addSimpleTextureMaterial(ImageID textureID);
|
||||||
[[nodiscard]] const Material& getMaterial(MaterialID id) const;
|
[[nodiscard]] const Material& getMaterial(MaterialID id) const;
|
||||||
|
|
||||||
[[nodiscard]] MaterialID getFreeMaterialId() const;
|
[[nodiscard]] MaterialID getFreeMaterialId() const;
|
||||||
@@ -29,7 +37,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
Material& getMaterialMutable(MaterialID id);
|
Material& getMaterialMutable(MaterialID id);
|
||||||
void updateMaterialGPU(GfxDevice& gfxDevice, MaterialID id);
|
void updateMaterialGPU(MaterialID id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Material> materials;
|
std::vector<Material> materials;
|
||||||
@@ -37,10 +45,10 @@ private:
|
|||||||
static constexpr auto MAX_MATERIALS = 1000;
|
static constexpr auto MAX_MATERIALS = 1000;
|
||||||
GPUBuffer materialDataBuffer;
|
GPUBuffer materialDataBuffer;
|
||||||
|
|
||||||
|
MaterialDefaultTextures defaultTextures;
|
||||||
|
|
||||||
// material which is used for meshes without materials
|
// material which is used for meshes without materials
|
||||||
MaterialID placeholderMaterialId{NULL_MATERIAL_ID};
|
MaterialID placeholderMaterialId{NULL_MATERIAL_ID};
|
||||||
|
|
||||||
ImageID defaultNormalMapTextureID{NULL_IMAGE_ID};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
+2
-2
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
#include <destrum/Graphics/Resources/Mesh.h>
|
#include <destrum/Graphics/Resources/Mesh.h>
|
||||||
|
|
||||||
#include "ids.h"
|
#include "../ids.h"
|
||||||
|
|
||||||
class GfxDevice;
|
class GfxDevice;
|
||||||
|
|
||||||
class MeshCache {
|
class MeshCache {
|
||||||
public:
|
public:
|
||||||
void cleanup(const GfxDevice& gfxDevice);
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
|
|
||||||
MeshID addMesh(GfxDevice& gfxDevice, const CPUMesh& cpuMesh);
|
MeshID addMesh(GfxDevice& gfxDevice, const CPUMesh& cpuMesh);
|
||||||
const GPUMesh& getMesh(MeshID id) const;
|
const GPUMesh& getMesh(MeshID id) const;
|
||||||
@@ -1,153 +1,214 @@
|
|||||||
#ifndef GFXDEVICE_H
|
#ifndef GFXDEVICE_H
|
||||||
#define GFXDEVICE_H
|
#define GFXDEVICE_H
|
||||||
|
|
||||||
#include <VkBootstrap.h>
|
#include <array>
|
||||||
#include <vk_mem_alloc.h>
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/GPUImage.h>
|
#include <VkBootstrap.h>
|
||||||
#include <destrum/Graphics/Swapchain.h>
|
#include <vk_mem_alloc.h>
|
||||||
#include <destrum/Graphics/ImageCache.h>
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
#include <volk.h>
|
#include <volk.h>
|
||||||
#include <VkBootstrap.h>
|
|
||||||
#include <vk_mem_alloc.h>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "ImmediateExecuter.h"
|
#include <glm/vec2.hpp>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/GPUImage.h>
|
||||||
#include <destrum/Graphics/Swapchain.h>
|
#include <destrum/Graphics/Swapchain.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/Resources/Buffer.h>
|
#include <destrum/Graphics/Resources/Buffer.h>
|
||||||
|
#include <destrum/Graphics/TextureIntent.h>
|
||||||
#include <destrum/Graphics/ids.h>
|
#include <destrum/Graphics/ids.h>
|
||||||
|
|
||||||
|
#include "ImmediateExecuter.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
class MeshCache;
|
|
||||||
class ImguiPass;
|
class ImguiPass;
|
||||||
|
|
||||||
#if defined(TRACY_ENABLE)
|
#if defined(TRACY_ENABLE)
|
||||||
namespace tracy { class VkCtx; }
|
namespace tracy
|
||||||
|
{
|
||||||
|
class VkCtx;
|
||||||
|
}
|
||||||
|
|
||||||
using DestrumTracyVkCtx = tracy::VkCtx*;
|
using DestrumTracyVkCtx = tracy::VkCtx*;
|
||||||
#else
|
#else
|
||||||
using DestrumTracyVkCtx = void*;
|
using DestrumTracyVkCtx = void*;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using ImmediateExecuteFunction = std::function<void(VkCommandBuffer)>;
|
||||||
|
|
||||||
namespace {
|
class GfxDevice
|
||||||
using ImmediateExecuteFunction = std::function<void(VkCommandBuffer)>;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
class GfxDevice {
|
|
||||||
public:
|
public:
|
||||||
struct FrameData {
|
struct FrameData
|
||||||
VkCommandPool commandPool;
|
{
|
||||||
VkCommandBuffer commandBuffer;
|
VkCommandPool commandPool{VK_NULL_HANDLE};
|
||||||
|
VkCommandBuffer commandBuffer{VK_NULL_HANDLE};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EndFrameProps
|
||||||
|
{
|
||||||
|
VkClearColorValue clearColor{{0.f, 0.f, 0.f, 1.f}};
|
||||||
|
glm::ivec4 drawImageBlitRect{}; // where to blit draw image to
|
||||||
|
ImguiPass* imguiPass{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
GfxDevice();
|
GfxDevice();
|
||||||
|
~GfxDevice() = default;
|
||||||
|
|
||||||
GfxDevice(const GfxDevice&) = delete;
|
GfxDevice(const GfxDevice&) = delete;
|
||||||
GfxDevice& operator=(const GfxDevice&) = delete;
|
GfxDevice& operator=(const GfxDevice&) = delete;
|
||||||
|
|
||||||
void init(SDL_Window* window, const std::string& appName, bool vSync);
|
void init(SDL_Window* window, const std::string& appName, bool vSync);
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
void recreateSwapchain(int width, int height);
|
void recreateSwapchain(int width, int height);
|
||||||
|
|
||||||
VkCommandBuffer beginFrame();
|
VkCommandBuffer beginFrame();
|
||||||
[[nodiscard]] bool needsSwapchainRecreate() const { return swapchain.isDirty(); }
|
|
||||||
VulkanImmediateExecutor& GetImmediateExecuter();
|
|
||||||
|
|
||||||
|
void endFrame(
|
||||||
struct EndFrameProps {
|
VkCommandBuffer cmd,
|
||||||
const VkClearColorValue clearColor{{0.f, 0.f, 0.f, 1.f}};
|
const GPUImage& drawImage,
|
||||||
glm::ivec4 drawImageBlitRect{}; // where to blit draw image to
|
const EndFrameProps& props);
|
||||||
ImguiPass* imguiPass = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
void endFrame(VkCommandBuffer cmd, const GPUImage& drawImage, const EndFrameProps& props);
|
|
||||||
void cleanup();
|
|
||||||
|
|
||||||
void waitIdle();
|
void waitIdle();
|
||||||
|
|
||||||
BindlessSetManager& getBindlessSetManager();
|
[[nodiscard]] bool needsSwapchainRecreate() const
|
||||||
VkDescriptorSetLayout getBindlessDescSetLayout() const;
|
{
|
||||||
const VkDescriptorSet& getBindlessDescSet() const;
|
return swapchain.isDirty();
|
||||||
void bindBindlessDescSet(VkCommandBuffer cmd, VkPipelineLayout layout) const;
|
}
|
||||||
|
|
||||||
|
VulkanImmediateExecutor& GetImmediateExecuter();
|
||||||
|
|
||||||
void immediateSubmit(ImmediateExecuteFunction&& f) const;
|
void immediateSubmit(ImmediateExecuteFunction&& f) const;
|
||||||
|
|
||||||
vkb::Device getDevice() const { return device; }
|
[[nodiscard]] std::uint32_t getCurrentFrameIndex() const
|
||||||
|
{
|
||||||
std::uint32_t getCurrentFrameIndex() const {
|
|
||||||
return frameNumber % FRAMES_IN_FLIGHT;
|
return frameNumber % FRAMES_IN_FLIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameData& getCurrentFrame() {
|
[[nodiscard]] FrameData& getCurrentFrame()
|
||||||
|
{
|
||||||
return frames[getCurrentFrameIndex()];
|
return frames[getCurrentFrameIndex()];
|
||||||
}
|
}
|
||||||
|
|
||||||
VkExtent2D getSwapchainExtent() const { return swapchain.getExtent(); }
|
[[nodiscard]] const FrameData& getCurrentFrame() const
|
||||||
|
{
|
||||||
|
return frames[getCurrentFrameIndex()];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkExtent2D getSwapchainExtent() const
|
||||||
|
{
|
||||||
|
return swapchain.getExtent();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] GPUBuffer createBuffer(
|
[[nodiscard]] GPUBuffer createBuffer(
|
||||||
std::size_t allocSize,
|
std::size_t allocSize,
|
||||||
VkBufferUsageFlags usage,
|
VkBufferUsageFlags usage,
|
||||||
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO) const;
|
VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_AUTO) const;
|
||||||
|
|
||||||
[[nodiscard]] VkDeviceAddress getBufferAddress(const GPUBuffer& buffer) const;
|
|
||||||
|
|
||||||
void destroyBuffer(const GPUBuffer& buffer) const;
|
void destroyBuffer(const GPUBuffer& buffer) const;
|
||||||
|
|
||||||
VmaAllocator getAllocator() const { return allocator; }
|
[[nodiscard]] VkDeviceAddress getBufferAddress(const GPUBuffer& buffer) const;
|
||||||
|
|
||||||
vkb::Device getVkbDevice() const { return device; }
|
[[nodiscard]] GPUImage createImageRaw(
|
||||||
|
const vkutil::CreateImageInfo& createInfo,
|
||||||
|
std::optional<VmaAllocationCreateInfo> customAllocationCreateInfo = std::nullopt) const;
|
||||||
|
|
||||||
ImageID createImage(const vkutil::CreateImageInfo& createInfo, const std::string& debugName = "", void* pixelData = nullptr, ImageID imageId = NULL_IMAGE_ID);
|
[[nodiscard]] std::optional<GPUImage> loadImageFromFileRaw(
|
||||||
ImageID createDrawImage(VkFormat format, glm::ivec2 size, const std::string& debugName = "", ImageID imageId = NULL_IMAGE_ID);
|
const std::filesystem::path& path,
|
||||||
ImageID loadImageFromFile(const std::filesystem::path& path, VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT, bool mipMap = false, TextureIntent intent = TextureIntent::ColorSrgb);
|
VkImageUsageFlags usage,
|
||||||
|
bool mipMap,
|
||||||
|
TextureIntent intent) const;
|
||||||
|
|
||||||
|
void uploadImageDataSized(
|
||||||
|
const GPUImage& image,
|
||||||
|
const void* pixelData,
|
||||||
|
std::size_t byteSize,
|
||||||
|
std::uint32_t layer) const;
|
||||||
|
|
||||||
ImageID addImageToCache(GPUImage image);
|
|
||||||
|
|
||||||
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
|
|
||||||
// void uploadImageData(const GPUImage& image, void* pixelData, std::uint32_t layer = 0) const;
|
|
||||||
void uploadImageDataSized(const GPUImage& image, const void* pixelData, std::size_t byteSize, std::uint32_t layer) const;
|
|
||||||
|
|
||||||
[[nodiscard]] GPUImage createImageRaw(const vkutil::CreateImageInfo& createInfo, std::optional<VmaAllocationCreateInfo> customAllocationCreateInfo = std::nullopt) const;
|
|
||||||
GPUImage loadImageFromFileRaw(const std::filesystem::path& path, VkImageUsageFlags usage, bool mipMap, TextureIntent intent) const;
|
|
||||||
void destroyImage(const GPUImage& image) const;
|
void destroyImage(const GPUImage& image) const;
|
||||||
|
|
||||||
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
|
[[nodiscard]] vkb::Device getDevice() const
|
||||||
|
{
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
VkInstance getVkInstance() const { return instance; }
|
[[nodiscard]] vkb::Device getVkbDevice() const
|
||||||
VkPhysicalDevice getVkPhysicalDevice() const { return physicalDevice; }
|
{
|
||||||
VkDevice getVkDevice() const { return device; }
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
std::uint32_t getGraphicsQueueFamily() const { return graphicsQueueFamily; }
|
[[nodiscard]] VkInstance getVkInstance() const
|
||||||
VkQueue getGraphicsQueue() const { return graphicsQueue; }
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
VkFormat getSwapchainFormat() const { return swapchainFormat; }
|
[[nodiscard]] VkPhysicalDevice getVkPhysicalDevice() const
|
||||||
std::uint32_t getSwapchainImageCount() const { return swapchain.getImageCount(); }
|
{
|
||||||
VkImageView getSwapchainImageView(std::uint32_t imageIndex) const {
|
return physicalDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkDevice getVkDevice() const
|
||||||
|
{
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VmaAllocator getAllocator() const
|
||||||
|
{
|
||||||
|
return allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::uint32_t getGraphicsQueueFamily() const
|
||||||
|
{
|
||||||
|
return graphicsQueueFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkQueue getGraphicsQueue() const
|
||||||
|
{
|
||||||
|
return graphicsQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkFormat getSwapchainFormat() const
|
||||||
|
{
|
||||||
|
return swapchainFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::uint32_t getSwapchainImageCount() const
|
||||||
|
{
|
||||||
|
return swapchain.getImageCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] VkImageView getSwapchainImageView(std::uint32_t imageIndex) const
|
||||||
|
{
|
||||||
return swapchain.getImageView(imageIndex);
|
return swapchain.getImageView(imageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
DestrumTracyVkCtx getTracyVkCtx() const { return tracyVkCtx; }
|
[[nodiscard]] DestrumTracyVkCtx getTracyVkCtx() const
|
||||||
|
{
|
||||||
|
return tracyVkCtx;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vkb::Instance instance;
|
vkb::Instance instance;
|
||||||
vkb::PhysicalDevice physicalDevice;
|
vkb::PhysicalDevice physicalDevice;
|
||||||
vkb::Device device;
|
vkb::Device device;
|
||||||
VmaAllocator allocator;
|
VmaAllocator allocator{VK_NULL_HANDLE};
|
||||||
|
|
||||||
DestrumTracyVkCtx tracyVkCtx = nullptr;
|
DestrumTracyVkCtx tracyVkCtx{nullptr};
|
||||||
|
|
||||||
std::uint32_t graphicsQueueFamily;
|
std::uint32_t graphicsQueueFamily{0};
|
||||||
VkQueue graphicsQueue;
|
VkQueue graphicsQueue{VK_NULL_HANDLE};
|
||||||
|
|
||||||
VkSurfaceKHR surface;
|
VkSurfaceKHR surface{VK_NULL_HANDLE};
|
||||||
VkFormat swapchainFormat;
|
VkFormat swapchainFormat{VK_FORMAT_UNDEFINED};
|
||||||
Swapchain swapchain;
|
Swapchain swapchain;
|
||||||
|
|
||||||
std::array<FrameData, FRAMES_IN_FLIGHT> frames{};
|
std::array<FrameData, FRAMES_IN_FLIGHT> frames{};
|
||||||
@@ -155,26 +216,7 @@ private:
|
|||||||
|
|
||||||
VulkanImmediateExecutor executor;
|
VulkanImmediateExecutor executor;
|
||||||
|
|
||||||
ImageID whiteImageId{NULL_IMAGE_ID};
|
bool m_vSync{false};
|
||||||
ImageID errorImageId{NULL_IMAGE_ID};
|
|
||||||
|
|
||||||
ImageCache imageCache;
|
|
||||||
|
|
||||||
bool m_vSync = false;
|
|
||||||
|
|
||||||
static uint32_t BytesPerTexel(VkFormat fmt) {
|
|
||||||
switch (fmt) {
|
|
||||||
case VK_FORMAT_R8_UNORM: return 1;
|
|
||||||
case VK_FORMAT_R8G8B8A8_UNORM: return 4;
|
|
||||||
case VK_FORMAT_B8G8R8A8_SRGB: return 4;
|
|
||||||
case VK_FORMAT_R16G16B16A16_SFLOAT: return 8;
|
|
||||||
case VK_FORMAT_R32G32B32A32_SFLOAT: return 16;
|
|
||||||
case VK_FORMAT_R8G8B8A8_SRGB: return 4;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("BytesPerTexel: unsupported format");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // GFXDEVICE_H
|
||||||
#endif //GFXDEVICE_H
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include <destrum/Graphics/Frustum.h>
|
#include <destrum/Graphics/Frustum.h>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/Resources/Mesh.h>
|
||||||
|
|
||||||
|
|
||||||
struct MeshDrawCommand {
|
struct MeshDrawCommand {
|
||||||
MeshID meshId;
|
MeshID meshId;
|
||||||
|
|||||||
@@ -1,27 +1,36 @@
|
|||||||
#ifndef MESHPIPELINE_H
|
#ifndef MESHPIPELINE_H
|
||||||
#define MESHPIPELINE_H
|
#define MESHPIPELINE_H
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <destrum/Graphics/Pipeline.h>
|
#include <vector>
|
||||||
|
|
||||||
#include <destrum/Graphics/MeshCache.h>
|
#include <glm/mat4x4.hpp>
|
||||||
#include <destrum/Graphics/MaterialCache.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/Pipeline.h>
|
||||||
#include <destrum/Graphics/Camera.h>
|
#include <destrum/Graphics/Camera.h>
|
||||||
#include <destrum/Graphics/Resources/Buffer.h>
|
#include <destrum/Graphics/Resources/Buffer.h>
|
||||||
#include <destrum/Graphics/MeshDrawCommand.h>
|
#include <destrum/Graphics/MeshDrawCommand.h>
|
||||||
|
|
||||||
|
class GfxDevice;
|
||||||
|
class RenderResources;
|
||||||
|
|
||||||
class MeshPipeline {
|
class MeshPipeline {
|
||||||
public:
|
public:
|
||||||
MeshPipeline();
|
MeshPipeline();
|
||||||
~MeshPipeline();
|
~MeshPipeline();
|
||||||
|
|
||||||
void init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat);
|
void init(
|
||||||
void draw(VkCommandBuffer cmd,
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
VkFormat drawImageFormat,
|
||||||
|
VkFormat depthImageFormat);
|
||||||
|
|
||||||
|
void draw(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
VkExtent2D renderExtent,
|
VkExtent2D renderExtent,
|
||||||
const GfxDevice& gfxDevice,
|
const RenderResources& resources,
|
||||||
const MeshCache& meshCache,
|
|
||||||
const MaterialCache& materialCache,
|
|
||||||
const Camera& camera,
|
const Camera& camera,
|
||||||
const GPUBuffer& sceneDataBuffer,
|
const GPUBuffer& sceneDataBuffer,
|
||||||
const std::vector<MeshDrawCommand>& drawCommands,
|
const std::vector<MeshDrawCommand>& drawCommands,
|
||||||
@@ -33,14 +42,11 @@ public:
|
|||||||
m_renderWireframe = wireframe;
|
m_renderWireframe = wireframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getRenderWireframe(){ return m_renderWireframe; }
|
bool getRenderWireframe() const {
|
||||||
|
return m_renderWireframe;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkPipelineLayout m_pipelineLayout;
|
|
||||||
|
|
||||||
std::unique_ptr<Pipeline> m_pipeline;
|
|
||||||
|
|
||||||
struct PushConstants {
|
struct PushConstants {
|
||||||
glm::mat4 transform;
|
glm::mat4 transform;
|
||||||
VkDeviceAddress sceneDataBuffer;
|
VkDeviceAddress sceneDataBuffer;
|
||||||
@@ -49,8 +55,11 @@ private:
|
|||||||
std::uint32_t padding;
|
std::uint32_t padding;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool m_renderWireframe{false};
|
private:
|
||||||
|
VkPipelineLayout m_pipelineLayout{VK_NULL_HANDLE};
|
||||||
|
std::unique_ptr<Pipeline> m_pipeline;
|
||||||
|
|
||||||
|
bool m_renderWireframe{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //MESHPIPELINE_H
|
#endif // MESHPIPELINE_H
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <destrum/Graphics/ids.h>
|
#include <destrum/Graphics/ids.h>
|
||||||
#include <destrum/Graphics/Pipeline.h>
|
#include <destrum/Graphics/Pipeline.h>
|
||||||
#include <destrum/Graphics/Camera.h>
|
#include <destrum/Graphics/Camera.h>
|
||||||
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
|
||||||
|
|
||||||
class SkyboxPipeline final {
|
class SkyboxPipeline final {
|
||||||
public:
|
public:
|
||||||
@@ -15,14 +17,10 @@ public:
|
|||||||
SkyboxPipeline();
|
SkyboxPipeline();
|
||||||
~SkyboxPipeline();
|
~SkyboxPipeline();
|
||||||
|
|
||||||
void init(
|
void init(GfxDevice& gfxDevice, RenderResources& resources, VkFormat drawImageFormat, VkFormat depthImageFormat);
|
||||||
GfxDevice& gfxDevice,
|
|
||||||
VkFormat drawImageFormat,
|
|
||||||
VkFormat depthImageFormat
|
|
||||||
);
|
|
||||||
void cleanup(VkDevice device);
|
void cleanup(VkDevice device);
|
||||||
|
|
||||||
void draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera);
|
void draw(VkCommandBuffer cmd, RenderResources& resources, const Camera& camera);
|
||||||
|
|
||||||
void setSkyboxImage(const ImageID skyboxId);
|
void setSkyboxImage(const ImageID skyboxId);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#ifndef RENDER_RESOURCES_H
|
||||||
|
#define RENDER_RESOURCES_H
|
||||||
|
|
||||||
|
#include <destrum/Graphics/Caches/ImageCache.h>
|
||||||
|
#include <destrum/Graphics/Caches/MeshCache.h>
|
||||||
|
#include <destrum/Graphics/Caches/MaterialCache.h>
|
||||||
|
#include <destrum/Graphics/ids.h>
|
||||||
|
#include <destrum/Graphics/Util.h>
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class GfxDevice;
|
||||||
|
|
||||||
|
class RenderResources {
|
||||||
|
public:
|
||||||
|
RenderResources();
|
||||||
|
RenderResources(const RenderResources&) = delete;
|
||||||
|
RenderResources& operator=(const RenderResources&) = delete;
|
||||||
|
|
||||||
|
void init(GfxDevice& gfxDevice);
|
||||||
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
|
|
||||||
|
ImageID createImage(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const vkutil::CreateImageInfo& createInfo,
|
||||||
|
const std::string& debugName = "",
|
||||||
|
void* pixelData = nullptr,
|
||||||
|
ImageID imageId = NULL_IMAGE_ID);
|
||||||
|
|
||||||
|
ImageID createDrawImage(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
VkFormat format,
|
||||||
|
glm::ivec2 size,
|
||||||
|
const std::string& debugName = "",
|
||||||
|
ImageID imageId = NULL_IMAGE_ID);
|
||||||
|
|
||||||
|
ImageID loadImageFromFile(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const std::filesystem::path& path,
|
||||||
|
VkImageUsageFlags usage = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
|
bool mipMap = false,
|
||||||
|
TextureIntent intent = TextureIntent::ColorSrgb);
|
||||||
|
|
||||||
|
ImageID addImageToCache(GPUImage image);
|
||||||
|
|
||||||
|
[[nodiscard]] const GPUImage& getImage(ImageID id) const;
|
||||||
|
|
||||||
|
[[nodiscard]] ImageID getWhiteTextureID() const { return whiteImageId; }
|
||||||
|
[[nodiscard]] ImageID getErrorTextureID() const { return errorImageId; }
|
||||||
|
|
||||||
|
BindlessSetManager& getBindlessSetManager();
|
||||||
|
VkDescriptorSetLayout getBindlessDescSetLayout() const;
|
||||||
|
const VkDescriptorSet& getBindlessDescSet() const;
|
||||||
|
void bindBindlessDescSet(VkCommandBuffer cmd, VkPipelineLayout layout) const;
|
||||||
|
|
||||||
|
MeshCache& meshes() { return *meshCache; }
|
||||||
|
const MeshCache& meshes() const { return *meshCache; }
|
||||||
|
|
||||||
|
MaterialCache& materials() { return *materialCache; }
|
||||||
|
const MaterialCache& materials() const { return *materialCache; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint32_t BytesPerTexel(VkFormat fmt);
|
||||||
|
|
||||||
|
std::unique_ptr<ImageCache> imageCache;
|
||||||
|
std::unique_ptr<MeshCache> meshCache;
|
||||||
|
std::unique_ptr<MaterialCache> materialCache;
|
||||||
|
|
||||||
|
ImageID whiteImageId{NULL_IMAGE_ID};
|
||||||
|
ImageID errorImageId{NULL_IMAGE_ID};
|
||||||
|
ImageID defaultNormalImageId{NULL_IMAGE_ID};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,15 +5,16 @@
|
|||||||
|
|
||||||
#include <destrum/Graphics/Camera.h>
|
#include <destrum/Graphics/Camera.h>
|
||||||
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
||||||
#include <destrum/Graphics/MeshCache.h>
|
|
||||||
#include <destrum/Graphics/ids.h>
|
#include <destrum/Graphics/ids.h>
|
||||||
#include <destrum/Graphics/MeshDrawCommand.h>
|
#include <destrum/Graphics/MeshDrawCommand.h>
|
||||||
#include <destrum/Graphics/Resources/NBuffer.h>
|
#include <destrum/Graphics/Resources/NBuffer.h>
|
||||||
#include <destrum/Graphics/MaterialCache.h>
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <destrum/Graphics/Pipelines/SkinningPipeline.h>
|
#include <destrum/Graphics/Pipelines/SkinningPipeline.h>
|
||||||
|
|
||||||
#include "Pipelines/SkyboxPipeline.h"
|
#include "Pipelines/SkyboxPipeline.h"
|
||||||
|
|
||||||
class GameRenderer {
|
class GameRenderer {
|
||||||
@@ -26,9 +27,9 @@ public:
|
|||||||
float fogDensity;
|
float fogDensity;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GameRenderer(MeshCache& meshCache, MaterialCache& matCache);
|
explicit GameRenderer();
|
||||||
|
|
||||||
void init(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize);
|
void init(GfxDevice& gfxDevice, RenderResources& _resources, glm::ivec2 drawImageSize);
|
||||||
void beginDrawing(GfxDevice& gfxDevice);
|
void beginDrawing(GfxDevice& gfxDevice);
|
||||||
void endDrawing();
|
void endDrawing();
|
||||||
|
|
||||||
@@ -36,12 +37,8 @@ public:
|
|||||||
void cleanup(GfxDevice& gfxDevice);
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
|
|
||||||
void drawMesh(MeshID id, const glm::mat4& transform, MaterialID materialId);
|
void drawMesh(MeshID id, const glm::mat4& transform, MaterialID materialId);
|
||||||
void drawSkinnedMesh(MeshID id,
|
void drawSkinnedMesh(MeshID id, const glm::mat4& transform, MaterialID materialId, SkinnedMesh* skinnedMesh, std::size_t jointMatricesStartIndex);
|
||||||
const glm::mat4& transform,
|
const GPUImage& getDrawImage() const;
|
||||||
MaterialID materialId,
|
|
||||||
SkinnedMesh* skinnedMesh,
|
|
||||||
std::size_t jointMatricesStartIndex);
|
|
||||||
const GPUImage& getDrawImage(const GfxDevice& gfx_device) const;
|
|
||||||
|
|
||||||
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize) {
|
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize) {
|
||||||
createDrawImage(gfxDevice, newSize, false);
|
createDrawImage(gfxDevice, newSize, false);
|
||||||
@@ -53,9 +50,6 @@ public:
|
|||||||
void setSkyboxTexture(ImageID skyboxImageId);
|
void setSkyboxTexture(ImageID skyboxImageId);
|
||||||
|
|
||||||
void flushMaterialUpdates(GfxDevice& gfxDevice);
|
void flushMaterialUpdates(GfxDevice& gfxDevice);
|
||||||
[[nodiscard]] MeshCache& GetMeshCache() const {
|
|
||||||
return meshCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] SkinningPipeline& getSkinningPipeline() const {
|
[[nodiscard]] SkinningPipeline& getSkinningPipeline() const {
|
||||||
return *skinningPipeline;
|
return *skinningPipeline;
|
||||||
@@ -69,11 +63,16 @@ public:
|
|||||||
return meshPipeline->getRenderWireframe();
|
return meshPipeline->getRenderWireframe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderResources* getResources()
|
||||||
|
{
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
||||||
|
|
||||||
MeshCache& meshCache;
|
RenderResources* resources = nullptr;
|
||||||
MaterialCache& materialCache;
|
|
||||||
std::vector<MaterialID> pendingMaterialUploads;
|
std::vector<MaterialID> pendingMaterialUploads;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,65 +2,115 @@
|
|||||||
#define CUBEMAP_H
|
#define CUBEMAP_H
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/ids.h>
|
#include <destrum/Graphics/ids.h>
|
||||||
|
#include <destrum/Graphics/Pipeline.h>
|
||||||
|
|
||||||
#include "destrum/Graphics/Pipeline.h"
|
class GfxDevice;
|
||||||
|
class RenderResources;
|
||||||
|
|
||||||
class CubeMap {
|
class CubeMap {
|
||||||
public:
|
public:
|
||||||
explicit CubeMap();
|
explicit CubeMap();
|
||||||
~CubeMap();
|
~CubeMap();
|
||||||
|
|
||||||
void LoadCubeMap(const std::filesystem::path &directoryPath);
|
CubeMap(const CubeMap&) = delete;
|
||||||
void RenderToCubemap(ImageID inputImage, VkImage outputImage, std::array<VkImageView, 6> faceViews, uint32_t size);
|
CubeMap& operator=(const CubeMap&) = delete;
|
||||||
|
|
||||||
void InitCubemapPipeline(const std::string& vertPath, const std::string& fragPath);
|
void cleanup(GfxDevice& gfxDevice);
|
||||||
void CreateCubeMap();
|
|
||||||
ImageID GetCubeMapImageID();
|
void LoadCubeMap(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
const std::filesystem::path& directoryPath);
|
||||||
|
|
||||||
|
void RenderToCubemap(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
ImageID inputImage,
|
||||||
|
VkImage outputImage,
|
||||||
|
std::array<VkImageView, 6> faceViews,
|
||||||
|
std::uint32_t size);
|
||||||
|
|
||||||
|
void InitCubemapPipeline(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
const std::string& vertPath,
|
||||||
|
const std::string& fragPath);
|
||||||
|
|
||||||
|
void CreateCubeMap(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources);
|
||||||
|
|
||||||
|
[[nodiscard]] ImageID GetCubeMapImageID() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::array<glm::mat4, 6> viewMatrices = {
|
const std::array<glm::mat4, 6> viewMatrices = {
|
||||||
// POSITIVE_X
|
// POSITIVE_X
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f)),
|
||||||
|
|
||||||
// NEGATIVE_X
|
// NEGATIVE_X
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(-1.0f, 0.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f)),
|
||||||
|
|
||||||
// POSITIVE_Y
|
// POSITIVE_Y
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f)),
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, 1.0f)),
|
||||||
|
|
||||||
// NEGATIVE_Y
|
// NEGATIVE_Y
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f)),
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f)),
|
||||||
|
|
||||||
// POSITIVE_Z
|
// POSITIVE_Z
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.0f, -1.0f, 0.0f)),
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, 1.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f)),
|
||||||
|
|
||||||
// NEGATIVE_Z
|
// NEGATIVE_Z
|
||||||
glm::lookAt(glm::vec3(0.0f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, -1.0f, 0.0f))
|
glm::lookAt(
|
||||||
|
glm::vec3(0.0f),
|
||||||
|
glm::vec3(0.0f, 0.0f, -1.0f),
|
||||||
|
glm::vec3(0.0f, -1.0f, 0.0f))
|
||||||
};
|
};
|
||||||
|
|
||||||
struct alignas(16) PC {
|
struct alignas(16) PC {
|
||||||
glm::mat4 viewMtx; // 64
|
glm::mat4 viewMtx;
|
||||||
glm::mat4 projMtx; // 64
|
glm::mat4 projMtx;
|
||||||
std::uint32_t inputImageId; // 4
|
std::uint32_t inputImageId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
glm::mat4 m_projection{};
|
glm::mat4 m_projection{};
|
||||||
|
|
||||||
ImageID m_hdrImage{};
|
ImageID m_hdrImage{NULL_IMAGE_ID};
|
||||||
|
ImageID m_cubemapImageID{NULL_IMAGE_ID};
|
||||||
|
|
||||||
uint32_t m_cubeMapSize = 1024; // Default size for cube map
|
std::uint32_t m_cubeMapSize{1024};
|
||||||
VkImageView m_skyboxView;
|
|
||||||
|
|
||||||
VkPipelineLayout m_cubemapPipelineLayout = VK_NULL_HANDLE;
|
VkPipelineLayout m_cubemapPipelineLayout{VK_NULL_HANDLE};
|
||||||
std::unique_ptr<Pipeline> m_cubemapPipeline;
|
std::unique_ptr<Pipeline> m_cubemapPipeline;
|
||||||
|
|
||||||
std::string m_cubemapVert;
|
std::string m_cubemapVert;
|
||||||
std::string m_cubemapFrag;
|
std::string m_cubemapFrag;
|
||||||
|
|
||||||
|
|
||||||
ImageID m_cubemapImageID;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CUBEMAP_H
|
#endif // CUBEMAP_H
|
||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
return *m_renderer;
|
return *m_renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GfxDevice* m_gfxDevice{nullptr};
|
GfxDevice* m_gfxDevice{nullptr};
|
||||||
GameRenderer* m_renderer{nullptr};
|
GameRenderer* m_renderer{nullptr};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void MeshRendererComponent::Start() {
|
|||||||
Component::Start();
|
Component::Start();
|
||||||
if (auto* animator = GetGameObject()->GetComponent<Animator>()) {
|
if (auto* animator = GetGameObject()->GetComponent<Animator>()) {
|
||||||
const auto& gfxDevice = GameState::GetInstance().Gfx();
|
const auto& gfxDevice = GameState::GetInstance().Gfx();
|
||||||
const auto& mesh = GameState::GetInstance().Renderer().GetMeshCache().getMesh(meshID);
|
const auto& mesh = GameState::GetInstance().Renderer().getResources()->meshes().getMesh(meshID);
|
||||||
|
|
||||||
m_skinnedMesh = std::make_unique<SkinnedMesh>();
|
m_skinnedMesh = std::make_unique<SkinnedMesh>();
|
||||||
m_skinnedMesh->skinnedVertexBuffer = gfxDevice.createBuffer(
|
m_skinnedMesh->skinnedVertexBuffer = gfxDevice.createBuffer(
|
||||||
@@ -33,7 +33,7 @@ void MeshRendererComponent::Render(const RenderContext& ctx) {
|
|||||||
if (meshID == NULL_MESH_ID || materialID == NULL_MATERIAL_ID) return;
|
if (meshID == NULL_MESH_ID || materialID == NULL_MATERIAL_ID) return;
|
||||||
|
|
||||||
if (auto* animator = GetGameObject()->GetComponent<Animator>(); animator && m_skinnedMesh) {
|
if (auto* animator = GetGameObject()->GetComponent<Animator>(); animator && m_skinnedMesh) {
|
||||||
const auto& mesh = ctx.renderer.GetMeshCache().getCPUMesh(meshID);
|
const auto& mesh = ctx.renderer.getResources()->meshes().getCPUMesh(meshID);
|
||||||
const auto skeleton = GetGameObject()->GetComponent<Animator>()->getSkeleton();
|
const auto skeleton = GetGameObject()->GetComponent<Animator>()->getSkeleton();
|
||||||
std::uint32_t frameIdx = GameState::GetInstance().Gfx().getCurrentFrameIndex();
|
std::uint32_t frameIdx = GameState::GetInstance().Gfx().getCurrentFrameIndex();
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,43 @@
|
|||||||
#include <destrum/Graphics/ImageCache.h>
|
#include <../../include/destrum/Graphics/Caches/ImageCache.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/GfxDevice.h>
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
ImageCache::ImageCache(GfxDevice& gfxDevice) : gfxDevice(gfxDevice) {
|
ImageCache::ImageCache(GfxDevice& gfxDevice) : gfxDevice(gfxDevice) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageID ImageCache::loadImageFromFile(const std::filesystem::path& path, VkImageUsageFlags usage, bool mipMap, TextureIntent intent) {
|
ImageID ImageCache::loadImageFromFile(
|
||||||
for (const auto& [id, info]: loadedImagesInfo) {
|
const std::filesystem::path& path,
|
||||||
if (info.path == path && info.intent == intent && info.usage == usage && info.mipMap == mipMap) {
|
VkImageUsageFlags usage,
|
||||||
|
bool mipMap,
|
||||||
|
TextureIntent intent)
|
||||||
|
{
|
||||||
|
for (const auto& [id, info] : loadedImagesInfo) {
|
||||||
|
if (info.path == path &&
|
||||||
|
info.intent == intent &&
|
||||||
|
info.usage == usage &&
|
||||||
|
info.mipMap == mipMap)
|
||||||
|
{
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto image = gfxDevice.loadImageFromFileRaw(path, usage, mipMap, intent);
|
auto imageOpt = gfxDevice.loadImageFromFileRaw(path, usage, mipMap, intent);
|
||||||
if (image.isInitialized() && image.getBindlessId() == errorImageId) {
|
|
||||||
|
if (!imageOpt.has_value()) {
|
||||||
|
spdlog::warn(
|
||||||
|
"Using error texture for failed image load: '{}'",
|
||||||
|
path.string()
|
||||||
|
);
|
||||||
|
|
||||||
return errorImageId;
|
return errorImageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto image = std::move(imageOpt.value());
|
||||||
|
|
||||||
const auto id = getFreeImageId();
|
const auto id = getFreeImageId();
|
||||||
|
|
||||||
addImage(id, std::move(image));
|
addImage(id, std::move(image));
|
||||||
|
|
||||||
loadedImagesInfo.emplace(
|
loadedImagesInfo.emplace(
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
#include <../../include/destrum/Graphics/Caches/MaterialCache.h>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
|
#include <destrum/Graphics/Util.h>
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
void MaterialCache::init(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
MaterialDefaultTextures defaults)
|
||||||
|
{
|
||||||
|
defaultTextures = defaults;
|
||||||
|
|
||||||
|
materialDataBuffer = gfxDevice.createBuffer(
|
||||||
|
MAX_MATERIALS * sizeof(MaterialData),
|
||||||
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||||
|
|
||||||
|
vkutil::addDebugLabel(
|
||||||
|
gfxDevice.getDevice(),
|
||||||
|
materialDataBuffer.buffer,
|
||||||
|
"material data");
|
||||||
|
|
||||||
|
Material placeholderMaterial{};
|
||||||
|
placeholderMaterial.name = "PLACEHOLDER_MATERIAL";
|
||||||
|
placeholderMaterial.diffuseTexture = defaultTextures.white;
|
||||||
|
|
||||||
|
placeholderMaterialId = addMaterial(placeholderMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialCache::cleanup(GfxDevice& gfxDevice)
|
||||||
|
{
|
||||||
|
gfxDevice.destroyBuffer(materialDataBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialID MaterialCache::addMaterial(Material material)
|
||||||
|
{
|
||||||
|
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
||||||
|
{
|
||||||
|
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
MaterialData* data = static_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
||||||
|
|
||||||
|
const auto id = getFreeMaterialId();
|
||||||
|
assert(id < MAX_MATERIALS);
|
||||||
|
|
||||||
|
data[id] = MaterialData{
|
||||||
|
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
||||||
|
|
||||||
|
.metalRoughnessEmissive = glm::vec4{
|
||||||
|
material.metallicFactor,
|
||||||
|
material.roughnessFactor,
|
||||||
|
material.emissiveFactor,
|
||||||
|
0.f
|
||||||
|
},
|
||||||
|
|
||||||
|
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
||||||
|
|
||||||
|
.diffuseTex = getTextureOrElse(
|
||||||
|
material.diffuseTexture,
|
||||||
|
defaultTextures.white),
|
||||||
|
|
||||||
|
.normalTex = defaultTextures.normal,
|
||||||
|
|
||||||
|
.metallicRoughnessTex = defaultTextures.metallicRoughness,
|
||||||
|
|
||||||
|
.emissiveTex = defaultTextures.emissive,
|
||||||
|
};
|
||||||
|
|
||||||
|
materials.push_back(std::move(material));
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialID MaterialCache::addSimpleTextureMaterial(ImageID textureID)
|
||||||
|
{
|
||||||
|
Material material{};
|
||||||
|
material.name = "simple texture material";
|
||||||
|
material.diffuseTexture = textureID;
|
||||||
|
material.metallicFactor = 0.0f;
|
||||||
|
material.roughnessFactor = 1.0f;
|
||||||
|
|
||||||
|
return addMaterial(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Material& MaterialCache::getMaterial(MaterialID id) const
|
||||||
|
{
|
||||||
|
return materials.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialID MaterialCache::getFreeMaterialId() const
|
||||||
|
{
|
||||||
|
return materials.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialID MaterialCache::getPlaceholderMaterialId() const
|
||||||
|
{
|
||||||
|
assert(placeholderMaterialId != NULL_MATERIAL_ID && "MaterialCache::init not called");
|
||||||
|
return placeholderMaterialId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Material& MaterialCache::getMaterialMutable(MaterialID id)
|
||||||
|
{
|
||||||
|
assert(id < materials.size());
|
||||||
|
return materials.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialCache::updateMaterialGPU(MaterialID id)
|
||||||
|
{
|
||||||
|
assert(id < materials.size());
|
||||||
|
assert(materialDataBuffer.info.pMappedData && "materialDataBuffer must be mapped");
|
||||||
|
|
||||||
|
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
||||||
|
{
|
||||||
|
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
||||||
|
};
|
||||||
|
|
||||||
|
Material& material = materials[id];
|
||||||
|
|
||||||
|
MaterialData* data =
|
||||||
|
reinterpret_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
||||||
|
|
||||||
|
data[id] = MaterialData{
|
||||||
|
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
||||||
|
|
||||||
|
.metalRoughnessEmissive = glm::vec4{
|
||||||
|
material.metallicFactor,
|
||||||
|
material.roughnessFactor,
|
||||||
|
material.emissiveFactor,
|
||||||
|
0.f
|
||||||
|
},
|
||||||
|
|
||||||
|
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
||||||
|
.diffuseTex = getTextureOrElse(material.diffuseTexture, defaultTextures.white),
|
||||||
|
.normalTex = defaultTextures.normal,
|
||||||
|
.metallicRoughnessTex = defaultTextures.metallicRoughness,
|
||||||
|
.emissiveTex = defaultTextures.emissive,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "tracy/Tracy.hpp"
|
#include "tracy/Tracy.hpp"
|
||||||
#include "tracy/TracyVulkan.hpp"
|
#include "tracy/TracyVulkan.hpp"
|
||||||
|
|
||||||
GfxDevice::GfxDevice(): imageCache(*this) {
|
GfxDevice::GfxDevice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxDevice::init(SDL_Window* window, const std::string& appName, bool vSync) {
|
void GfxDevice::init(SDL_Window* window, const std::string& appName, bool vSync) {
|
||||||
@@ -120,7 +120,7 @@ void GfxDevice::init(SDL_Window* window, const std::string& appName, bool vSync)
|
|||||||
VkPhysicalDeviceProperties props{};
|
VkPhysicalDeviceProperties props{};
|
||||||
vkGetPhysicalDeviceProperties(physicalDevice, &props);
|
vkGetPhysicalDeviceProperties(physicalDevice, &props);
|
||||||
|
|
||||||
imageCache.bindlessSetManager.init(device, props.limits.maxSamplerAnisotropy);
|
// imageCache.bindlessSetManager.init(device, props.limits.maxSamplerAnisotropy);
|
||||||
|
|
||||||
swapchain.initSync(device);
|
swapchain.initSync(device);
|
||||||
|
|
||||||
@@ -163,34 +163,34 @@ void GfxDevice::init(SDL_Window* window, const std::string& appName, bool vSync)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ // create white texture
|
// { // create white texture
|
||||||
std::uint32_t pixel = 0xFFFFFFFF;
|
// std::uint32_t pixel = 0xFFFFFFFF;
|
||||||
whiteImageId = createImage(
|
// whiteImageId = createImage(
|
||||||
{
|
// {
|
||||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
// .format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
// .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
.extent = VkExtent3D{1, 1, 1},
|
// .extent = VkExtent3D{1, 1, 1},
|
||||||
},
|
// },
|
||||||
"white texture",
|
// "white texture",
|
||||||
&pixel);
|
// &pixel);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
{ // create error texture (black/magenta checker)
|
// { // create error texture (black/magenta checker)
|
||||||
constexpr auto black = 0xFF000000;
|
// constexpr auto black = 0xFF000000;
|
||||||
constexpr auto magenta = 0xFFFF00FF;
|
// constexpr auto magenta = 0xFFFF00FF;
|
||||||
|
//
|
||||||
std::array<std::uint32_t, 4> pixels{black, magenta, magenta, black};
|
// std::array<std::uint32_t, 4> pixels{black, magenta, magenta, black};
|
||||||
errorImageId = createImage(
|
// errorImageId = createImage(
|
||||||
{
|
// {
|
||||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
// .format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
// .usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
// VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
.extent = VkExtent3D{2, 2, 1},
|
// .extent = VkExtent3D{2, 2, 1},
|
||||||
},
|
// },
|
||||||
"error texture",
|
// "error texture",
|
||||||
pixels.data());
|
// pixels.data());
|
||||||
imageCache.setErrorImageId(errorImageId);
|
// imageCache.setErrorImageId(errorImageId);
|
||||||
}
|
// }
|
||||||
|
|
||||||
GameState::GetInstance().SetGfxDevice(this);
|
GameState::GetInstance().SetGfxDevice(this);
|
||||||
}
|
}
|
||||||
@@ -359,29 +359,7 @@ void GfxDevice::waitIdle() {
|
|||||||
VK_CHECK(vkDeviceWaitIdle(device));
|
VK_CHECK(vkDeviceWaitIdle(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
BindlessSetManager& GfxDevice::getBindlessSetManager() {
|
|
||||||
return imageCache.bindlessSetManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDescriptorSetLayout GfxDevice::getBindlessDescSetLayout() const {
|
|
||||||
return imageCache.bindlessSetManager.getDescSetLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
const VkDescriptorSet& GfxDevice::getBindlessDescSet() const {
|
|
||||||
return imageCache.bindlessSetManager.getDescSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GfxDevice::bindBindlessDescSet(VkCommandBuffer cmd, VkPipelineLayout layout) const {
|
|
||||||
vkCmdBindDescriptorSets(
|
|
||||||
cmd,
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
||||||
layout,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
&imageCache.bindlessSetManager.getDescSet(),
|
|
||||||
0,
|
|
||||||
nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GfxDevice::immediateSubmit(ImmediateExecuteFunction&& f) const {
|
void GfxDevice::immediateSubmit(ImmediateExecuteFunction&& f) const {
|
||||||
executor.immediateSubmit(std::move(f));
|
executor.immediateSubmit(std::move(f));
|
||||||
@@ -463,69 +441,6 @@ void GfxDevice::destroyBuffer(const GPUBuffer& buffer) const {
|
|||||||
// return image;
|
// return image;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
ImageID GfxDevice::createImage(
|
|
||||||
const vkutil::CreateImageInfo& createInfo,
|
|
||||||
const std::string& debugName,
|
|
||||||
void* pixelData,
|
|
||||||
ImageID imageId) {
|
|
||||||
auto image = createImageRaw(createInfo);
|
|
||||||
if (!debugName.empty()) {
|
|
||||||
vkutil::addDebugLabel(device, image.image, debugName.c_str());
|
|
||||||
image.debugName = debugName;
|
|
||||||
}
|
|
||||||
if (pixelData) {
|
|
||||||
const std::size_t bytes =
|
|
||||||
std::size_t(image.extent.width) *
|
|
||||||
std::size_t(image.extent.height) *
|
|
||||||
std::size_t(image.extent.depth) *
|
|
||||||
BytesPerTexel(image.format);
|
|
||||||
|
|
||||||
uploadImageDataSized(image, pixelData, bytes, 0);
|
|
||||||
}
|
|
||||||
if (imageId != NULL_IMAGE_ID) {
|
|
||||||
return imageCache.addImage(imageId, std::move(image));
|
|
||||||
} else {
|
|
||||||
return addImageToCache(std::move(image));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageID GfxDevice::createDrawImage(
|
|
||||||
VkFormat format,
|
|
||||||
glm::ivec2 size,
|
|
||||||
const std::string& debugName,
|
|
||||||
ImageID imageId) {
|
|
||||||
assert(size.x > 0 && size.y > 0);
|
|
||||||
const auto extent = VkExtent3D{
|
|
||||||
.width = (std::uint32_t)size.x,
|
|
||||||
.height = (std::uint32_t)size.y,
|
|
||||||
.depth = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkImageUsageFlags usages{};
|
|
||||||
usages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
usages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
||||||
usages |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
||||||
usages |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
|
||||||
|
|
||||||
const auto createImageInfo = vkutil::CreateImageInfo{
|
|
||||||
.format = format,
|
|
||||||
.usage = usages,
|
|
||||||
.extent = extent,
|
|
||||||
};
|
|
||||||
return createImage(createImageInfo, debugName, nullptr, imageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageID GfxDevice::loadImageFromFile(const std::filesystem::path& path, VkImageUsageFlags usage, bool mipMap, TextureIntent intent) {
|
|
||||||
return imageCache.loadImageFromFile(path, usage, mipMap, intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
const GPUImage& GfxDevice::getImage(ImageID id) const {
|
|
||||||
return imageCache.getImage(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageID GfxDevice::addImageToCache(GPUImage img) {
|
|
||||||
return imageCache.addImage(std::move(img));
|
|
||||||
}
|
|
||||||
|
|
||||||
GPUImage GfxDevice::createImageRaw(
|
GPUImage GfxDevice::createImageRaw(
|
||||||
const vkutil::CreateImageInfo& createInfo,
|
const vkutil::CreateImageInfo& createInfo,
|
||||||
@@ -611,12 +526,20 @@ GPUImage GfxDevice::createImageRaw(
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUImage GfxDevice::loadImageFromFileRaw(const std::filesystem::path& path, VkImageUsageFlags usage, bool mipMap, TextureIntent intent) const {
|
std::optional<GPUImage> GfxDevice::loadImageFromFileRaw(
|
||||||
|
const std::filesystem::path& path,
|
||||||
|
VkImageUsageFlags usage,
|
||||||
|
bool mipMap,
|
||||||
|
TextureIntent intent) const
|
||||||
|
{
|
||||||
const auto data = util::loadImage(path, intent);
|
const auto data = util::loadImage(path, intent);
|
||||||
|
|
||||||
if (data.vkFormat == VK_FORMAT_UNDEFINED || data.byteSize == 0 || (data.hdr ? (data.hdrPixels == nullptr) : (data.pixels == nullptr))) {
|
if (data.vkFormat == VK_FORMAT_UNDEFINED ||
|
||||||
|
data.byteSize == 0 ||
|
||||||
|
(data.hdr ? data.hdrPixels == nullptr : data.pixels == nullptr))
|
||||||
|
{
|
||||||
spdlog::error("Failed to load image '{}'", path.string());
|
spdlog::error("Failed to load image '{}'", path.string());
|
||||||
return getImage(errorImageId);
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto image = createImageRaw({
|
auto image = createImageRaw({
|
||||||
@@ -632,7 +555,10 @@ GPUImage GfxDevice::loadImageFromFileRaw(const std::filesystem::path& path, VkIm
|
|||||||
.mipMap = mipMap,
|
.mipMap = mipMap,
|
||||||
});
|
});
|
||||||
|
|
||||||
const void* src = data.hdr ? static_cast<const void*>(data.hdrPixels) : static_cast<const void*>(data.pixels);
|
const void* src =
|
||||||
|
data.hdr
|
||||||
|
? static_cast<const void*>(data.hdrPixels)
|
||||||
|
: static_cast<const void*>(data.pixels);
|
||||||
|
|
||||||
uploadImageDataSized(image, src, data.byteSize, 0);
|
uploadImageDataSized(image, src, data.byteSize, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
#include <destrum/Graphics/MaterialCache.h>
|
|
||||||
|
|
||||||
#include <destrum/Graphics/GfxDevice.h>
|
|
||||||
#include <destrum/Graphics/Util.h>
|
|
||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
|
||||||
|
|
||||||
void MaterialCache::init(GfxDevice& gfxDevice)
|
|
||||||
{
|
|
||||||
materialDataBuffer = gfxDevice.createBuffer(
|
|
||||||
MAX_MATERIALS * sizeof(MaterialData),
|
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
|
||||||
vkutil::addDebugLabel(gfxDevice.getDevice(), materialDataBuffer.buffer, "material data");
|
|
||||||
|
|
||||||
{ // create default normal map texture
|
|
||||||
std::uint32_t normal = 0xFFFF8080; // (0.5, 0.5, 1.0, 1.0)
|
|
||||||
defaultNormalMapTextureID = gfxDevice.createImage(
|
|
||||||
{
|
|
||||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
|
||||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
|
||||||
.extent = VkExtent3D{1, 1, 1},
|
|
||||||
},
|
|
||||||
"normal map placeholder texture",
|
|
||||||
&normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
Material placeholderMaterial{.diffuseTexture = defaultNormalMapTextureID, .name = "PLACEHOLDER_MATERIAL"};
|
|
||||||
placeholderMaterialId = addMaterial(gfxDevice, placeholderMaterial);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialCache::cleanup(GfxDevice& gfxDevice)
|
|
||||||
{
|
|
||||||
gfxDevice.destroyBuffer(materialDataBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialID MaterialCache::addMaterial(GfxDevice& gfxDevice, Material material)
|
|
||||||
{
|
|
||||||
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder) {
|
|
||||||
spdlog::warn("Using placeholder texture for material given texture ID: {}", imageId);
|
|
||||||
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
|
||||||
};
|
|
||||||
|
|
||||||
// store on GPU
|
|
||||||
MaterialData* data = static_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
|
||||||
const auto whiteTextureID = gfxDevice.getWhiteTextureID();
|
|
||||||
const auto id = getFreeMaterialId();
|
|
||||||
assert(id < MAX_MATERIALS);
|
|
||||||
data[id] = MaterialData{
|
|
||||||
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
|
||||||
.metalRoughnessEmissive = glm::vec4{material.metallicFactor, material.roughnessFactor, material.emissiveFactor, 0.f},
|
|
||||||
.textureFilteringMode = static_cast<std::uint32_t>(material.textureFilteringMode),
|
|
||||||
.diffuseTex = getTextureOrElse(material.diffuseTexture, whiteTextureID),
|
|
||||||
.normalTex = whiteTextureID,
|
|
||||||
.metallicRoughnessTex = whiteTextureID,
|
|
||||||
.emissiveTex = whiteTextureID,
|
|
||||||
};
|
|
||||||
|
|
||||||
// store on CPU
|
|
||||||
materials.push_back(std::move(material));
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialID MaterialCache::addSimpleTextureMaterial(GfxDevice& gfxDevice, ImageID textureID) {
|
|
||||||
Material material{};
|
|
||||||
material.name = "idk";
|
|
||||||
material.diffuseTexture = textureID;
|
|
||||||
material.metallicFactor = 0.0f;
|
|
||||||
material.roughnessFactor = 1.0f;
|
|
||||||
return addMaterial(gfxDevice, material);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Material& MaterialCache::getMaterial(MaterialID id) const
|
|
||||||
{
|
|
||||||
return materials.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialID MaterialCache::getFreeMaterialId() const
|
|
||||||
{
|
|
||||||
return materials.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialID MaterialCache::getPlaceholderMaterialId() const
|
|
||||||
{
|
|
||||||
assert(placeholderMaterialId != NULL_MATERIAL_ID && "MaterialCache::init not called");
|
|
||||||
return placeholderMaterialId;
|
|
||||||
}
|
|
||||||
|
|
||||||
Material& MaterialCache::getMaterialMutable(MaterialID id) {
|
|
||||||
assert(id < materials.size());
|
|
||||||
return materials.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialCache::updateMaterialGPU(GfxDevice& gfxDevice, MaterialID id)
|
|
||||||
{
|
|
||||||
assert(id < materials.size());
|
|
||||||
assert(materialDataBuffer.info.pMappedData && "materialDataBuffer must be mapped");
|
|
||||||
|
|
||||||
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder) {
|
|
||||||
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
|
||||||
};
|
|
||||||
|
|
||||||
Material& material = materials[id];
|
|
||||||
|
|
||||||
MaterialData* data = reinterpret_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
|
||||||
|
|
||||||
const ImageID whiteTextureID = gfxDevice.getWhiteTextureID();
|
|
||||||
|
|
||||||
data[id] = MaterialData{
|
|
||||||
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
|
||||||
.metalRoughnessEmissive = glm::vec4(material.metallicFactor, material.roughnessFactor, material.emissiveFactor, 0.f),
|
|
||||||
.diffuseTex = getTextureOrElse(material.diffuseTexture, whiteTextureID),
|
|
||||||
.normalTex = whiteTextureID,
|
|
||||||
.metallicRoughnessTex = whiteTextureID,
|
|
||||||
.emissiveTex = whiteTextureID,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include <destrum/Graphics/MeshCache.h>
|
#include <../../include/destrum/Graphics/Caches/MeshCache.h>
|
||||||
|
|
||||||
#include <destrum/Graphics/Resources/Mesh.h>
|
#include <destrum/Graphics/Resources/Mesh.h>
|
||||||
#include <destrum/Graphics/GfxDevice.h>
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
@@ -114,7 +114,7 @@ const CPUMesh& MeshCache::getCPUMesh(MeshID id) const
|
|||||||
return cpuMeshes.at(id);
|
return cpuMeshes.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCache::cleanup(const GfxDevice& gfxDevice)
|
void MeshCache::cleanup(GfxDevice& gfxDevice)
|
||||||
{
|
{
|
||||||
for (const auto& mesh : meshes) {
|
for (const auto& mesh : meshes) {
|
||||||
gfxDevice.destroyBuffer(mesh.indexBuffer);
|
gfxDevice.destroyBuffer(mesh.indexBuffer);
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
#include <destrum/Graphics/Pipelines/MeshPipeline.h>
|
||||||
#include <destrum/FS/AssetFS.h>
|
|
||||||
|
|
||||||
#include "destrum/Graphics/Frustum.h"
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <destrum/FS/AssetFS.h>
|
||||||
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
#include <destrum/Graphics/Caches/MeshCache.h>
|
||||||
|
#include <destrum/Graphics/Frustum.h>
|
||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
MeshPipeline::MeshPipeline(): m_pipelineLayout{nullptr} {
|
MeshPipeline::MeshPipeline() = default;
|
||||||
}
|
|
||||||
|
|
||||||
MeshPipeline::~MeshPipeline() {
|
MeshPipeline::~MeshPipeline() = default;
|
||||||
}
|
|
||||||
|
|
||||||
void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat) {
|
void MeshPipeline::init(
|
||||||
const auto& device = gfxDevice.getDevice();
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
const auto vertexShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.vert");
|
VkFormat drawImageFormat,
|
||||||
const auto fragShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.frag");
|
VkFormat depthImageFormat)
|
||||||
|
{
|
||||||
|
const auto vertexShader =
|
||||||
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.vert");
|
||||||
|
|
||||||
|
const auto fragShader =
|
||||||
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/mesh.frag");
|
||||||
|
|
||||||
const auto bufferRange = VkPushConstantRange{
|
const auto bufferRange = VkPushConstantRange{
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
@@ -24,24 +35,31 @@ void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat
|
|||||||
};
|
};
|
||||||
|
|
||||||
const auto pushConstantRanges = std::array{bufferRange};
|
const auto pushConstantRanges = std::array{bufferRange};
|
||||||
const auto layouts = std::array{gfxDevice.getBindlessDescSetLayout()};
|
|
||||||
// m_pipelineLayout = vkutil::createPipelineLayout(device, layouts, pushConstantRanges);
|
const auto layouts = std::array{
|
||||||
// vkutil::addDebugLabel(device, pipelineLayout, "mesh pipeline layout");
|
resources.getBindlessDescSetLayout()
|
||||||
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(layouts.size());
|
pipelineLayoutInfo.setLayoutCount = static_cast<std::uint32_t>(layouts.size());
|
||||||
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
||||||
|
pipelineLayoutInfo.pushConstantRangeCount =
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
static_cast<std::uint32_t>(pushConstantRanges.size());
|
||||||
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(gfxDevice.getDevice().device, &pipelineLayoutInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
|
if (vkCreatePipelineLayout(
|
||||||
throw std::runtime_error("Could not make pipleine layout");
|
gfxDevice.getDevice().device,
|
||||||
|
&pipelineLayoutInfo,
|
||||||
|
nullptr,
|
||||||
|
&m_pipelineLayout) != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Could not create mesh pipeline layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineConfigInfo pipelineConfig{};
|
PipelineConfigInfo pipelineConfig{};
|
||||||
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
|
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
|
||||||
|
|
||||||
pipelineConfig.name = "Mesh Pipeline";
|
pipelineConfig.name = "Mesh Pipeline";
|
||||||
pipelineConfig.pipelineLayout = m_pipelineLayout;
|
pipelineConfig.pipelineLayout = m_pipelineLayout;
|
||||||
|
|
||||||
@@ -59,78 +77,119 @@ void MeshPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPipeline::draw(VkCommandBuffer cmd,
|
void MeshPipeline::draw(
|
||||||
VkExtent2D renderExtent,
|
VkCommandBuffer cmd,
|
||||||
const GfxDevice& gfxDevice,
|
VkExtent2D renderExtent,
|
||||||
const MeshCache& meshCache,
|
const RenderResources& resources,
|
||||||
const MaterialCache& materialCache,
|
const Camera& camera,
|
||||||
const Camera& camera,
|
const GPUBuffer& sceneDataBuffer,
|
||||||
const GPUBuffer& sceneDataBuffer,
|
const std::vector<MeshDrawCommand>& drawCommands,
|
||||||
const std::vector<MeshDrawCommand>& drawCommands,
|
const std::vector<std::size_t>& sortedDrawCommands)
|
||||||
const std::vector<std::size_t>& sortedDrawCommands) {
|
{
|
||||||
m_pipeline->bind(cmd);
|
if (!m_pipeline) {
|
||||||
gfxDevice.bindBindlessDescSet(cmd, m_pipelineLayout);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int ActualDrawCalls = 0;
|
const MeshCache& meshCache = resources.meshes();
|
||||||
|
|
||||||
|
m_pipeline->bind(cmd);
|
||||||
|
|
||||||
|
resources.bindBindlessDescSet(cmd, m_pipelineLayout);
|
||||||
|
|
||||||
const auto viewport = VkViewport{
|
const auto viewport = VkViewport{
|
||||||
.x = 0,
|
.x = 0.f,
|
||||||
.y = 0,
|
.y = 0.f,
|
||||||
.width = (float)renderExtent.width,
|
.width = static_cast<float>(renderExtent.width),
|
||||||
.height = (float)renderExtent.height,
|
.height = static_cast<float>(renderExtent.height),
|
||||||
.minDepth = 0.f,
|
.minDepth = 0.f,
|
||||||
.maxDepth = 1.f,
|
.maxDepth = 1.f,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
vkCmdSetViewport(cmd, 0, 1, &viewport);
|
||||||
|
|
||||||
const auto scissor = VkRect2D{
|
const auto scissor = VkRect2D{
|
||||||
.offset = {},
|
.offset = {},
|
||||||
.extent = renderExtent,
|
.extent = renderExtent,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
vkCmdSetScissor(cmd, 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdSetPolygonModeEXT(cmd, m_renderWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL);
|
vkCmdSetPolygonModeEXT(
|
||||||
|
cmd,
|
||||||
|
m_renderWireframe ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL
|
||||||
|
);
|
||||||
|
|
||||||
auto prevMeshId = NULL_MESH_ID;
|
MeshID prevMeshId = NULL_MESH_ID;
|
||||||
|
int actualDrawCalls = 0;
|
||||||
|
|
||||||
const auto frustum = edge::createFrustumFromCamera(camera);
|
const auto frustum = edge::createFrustumFromCamera(camera);
|
||||||
|
|
||||||
for (const auto& dcIdx : drawCommands) {
|
const auto drawOne = [&](const MeshDrawCommand& dc) {
|
||||||
const auto& dc = dcIdx;
|
|
||||||
|
|
||||||
if (!edge::isInFrustum(frustum, dc.worldBoundingSphere)) {
|
if (!edge::isInFrustum(frustum, dc.worldBoundingSphere)) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActualDrawCalls++;
|
++actualDrawCalls;
|
||||||
|
|
||||||
const auto& mesh = meshCache.getMesh(dc.meshId);
|
const auto& mesh = meshCache.getMesh(dc.meshId);
|
||||||
|
|
||||||
if (dc.meshId != prevMeshId) {
|
if (dc.meshId != prevMeshId) {
|
||||||
prevMeshId = dc.meshId;
|
prevMeshId = dc.meshId;
|
||||||
vkCmdBindIndexBuffer(cmd, mesh.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
||||||
|
vkCmdBindIndexBuffer(
|
||||||
|
cmd,
|
||||||
|
mesh.indexBuffer.buffer,
|
||||||
|
0,
|
||||||
|
VK_INDEX_TYPE_UINT32
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(dc.materialId != NULL_MATERIAL_ID);
|
assert(dc.materialId != NULL_MATERIAL_ID);
|
||||||
|
|
||||||
const auto pushConstants = PushConstants{
|
const auto pushConstants = PushConstants{
|
||||||
.transform = dc.transformMatrix,
|
.transform = dc.transformMatrix,
|
||||||
.sceneDataBuffer = sceneDataBuffer.address,
|
.sceneDataBuffer = sceneDataBuffer.address,
|
||||||
.vertexBuffer = dc.skinnedMesh != nullptr ? dc.skinnedMesh->skinnedVertexBuffer.address : mesh.vertexBuffer.address,
|
.vertexBuffer =
|
||||||
|
dc.skinnedMesh != nullptr
|
||||||
|
? dc.skinnedMesh->skinnedVertexBuffer.address
|
||||||
|
: mesh.vertexBuffer.address,
|
||||||
.materialId = dc.materialId,
|
.materialId = dc.materialId,
|
||||||
|
.padding = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkCmdPushConstants(
|
vkCmdPushConstants(
|
||||||
cmd,
|
cmd,
|
||||||
m_pipelineLayout,
|
m_pipelineLayout,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
0,
|
0,
|
||||||
sizeof(PushConstants),
|
sizeof(PushConstants),
|
||||||
&pushConstants);
|
&pushConstants
|
||||||
|
);
|
||||||
|
|
||||||
vkCmdDrawIndexed(cmd, mesh.numIndices, 1, 0, 0, 0);
|
vkCmdDrawIndexed(cmd, mesh.numIndices, 1, 0, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!sortedDrawCommands.empty()) {
|
||||||
|
for (std::size_t drawIndex : sortedDrawCommands) {
|
||||||
|
assert(drawIndex < drawCommands.size());
|
||||||
|
drawOne(drawCommands[drawIndex]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const MeshDrawCommand& dc : drawCommands) {
|
||||||
|
drawOne(dc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional:
|
||||||
|
// spdlog::debug("Actual mesh draw calls: {}", actualDrawCalls);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshPipeline::cleanup(VkDevice device)
|
||||||
|
{
|
||||||
|
m_pipeline.reset();
|
||||||
|
|
||||||
|
if (m_pipelineLayout != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
|
||||||
|
m_pipelineLayout = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshPipeline::cleanup(VkDevice device) {
|
|
||||||
vkDestroyPipelineLayout(device, m_pipelineLayout, nullptr);
|
|
||||||
m_pipeline.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <destrum/Graphics/Pipelines/SkinningPipeline.h>
|
#include <destrum/Graphics/Pipelines/SkinningPipeline.h>
|
||||||
|
|
||||||
#include "destrum/FS/AssetFS.h"
|
#include "destrum/FS/AssetFS.h"
|
||||||
#include "destrum/Graphics/MeshCache.h"
|
#include "../../../include/destrum/Graphics/Caches/MeshCache.h"
|
||||||
#include "destrum/Graphics/MeshDrawCommand.h"
|
#include "destrum/Graphics/MeshDrawCommand.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|||||||
@@ -13,49 +13,63 @@ SkyboxPipeline::SkyboxPipeline(): pipelineLayout{nullptr} {
|
|||||||
SkyboxPipeline::~SkyboxPipeline() {
|
SkyboxPipeline::~SkyboxPipeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyboxPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkFormat depthImageFormat) {
|
void SkyboxPipeline::init(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
VkFormat drawImageFormat,
|
||||||
|
VkFormat depthImageFormat)
|
||||||
|
{
|
||||||
|
const auto vertexShader =
|
||||||
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/fullscreen_triangle.vert");
|
||||||
|
|
||||||
const auto vertexShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/fullscreen_triangle.vert");
|
const auto fragShader =
|
||||||
const auto fragShader = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/skybox.frag");
|
AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/skybox.frag");
|
||||||
|
|
||||||
constexpr auto bufferRange = VkPushConstantRange{
|
constexpr auto bufferRange = VkPushConstantRange{
|
||||||
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(SkyboxPushConstants),
|
.size = sizeof(SkyboxPushConstants),
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto pushConstantRanges = std::array{bufferRange};
|
constexpr auto pushConstantRanges = std::array{bufferRange};
|
||||||
const auto layouts = std::array{gfxDevice.getBindlessDescSetLayout()};
|
|
||||||
|
const auto layouts = std::array{
|
||||||
|
resources.getBindlessDescSetLayout()
|
||||||
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{};
|
||||||
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||||
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(layouts.size());
|
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(layouts.size());
|
||||||
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
||||||
|
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
|
pipelineLayoutInfo.pushConstantRangeCount = static_cast<uint32_t>(pushConstantRanges.size());
|
||||||
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
pipelineLayoutInfo.pPushConstantRanges = pushConstantRanges.data();
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(gfxDevice.getDevice().device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
|
if (vkCreatePipelineLayout(
|
||||||
throw std::runtime_error("Could not make pipleine layout");
|
gfxDevice.getDevice().device,
|
||||||
|
&pipelineLayoutInfo,
|
||||||
|
nullptr,
|
||||||
|
&pipelineLayout) != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Could not make skybox pipeline layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineConfigInfo pipelineConfig{};
|
PipelineConfigInfo pipelineConfig{};
|
||||||
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
|
Pipeline::DefaultPipelineConfigInfo(pipelineConfig);
|
||||||
|
|
||||||
pipelineConfig.name = "skybox pipeline";
|
pipelineConfig.name = "skybox pipeline";
|
||||||
pipelineConfig.pipelineLayout = pipelineLayout;
|
pipelineConfig.pipelineLayout = pipelineLayout;
|
||||||
|
|
||||||
pipelineConfig.vertexAttributeDescriptions = {};
|
pipelineConfig.vertexAttributeDescriptions = {};
|
||||||
pipelineConfig.vertexBindingDescriptions = {};
|
pipelineConfig.vertexBindingDescriptions = {};
|
||||||
|
|
||||||
pipelineConfig.colorAttachments = { drawImageFormat };
|
pipelineConfig.colorAttachments = { drawImageFormat };
|
||||||
pipelineConfig.depthAttachment = depthImageFormat;
|
pipelineConfig.depthAttachment = depthImageFormat;
|
||||||
|
|
||||||
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
||||||
|
|
||||||
pipelineConfig.depthStencilInfo.depthTestEnable = VK_TRUE;
|
pipelineConfig.depthStencilInfo.depthTestEnable = VK_TRUE;
|
||||||
pipelineConfig.depthStencilInfo.depthWriteEnable = VK_FALSE;
|
pipelineConfig.depthStencilInfo.depthWriteEnable = VK_FALSE;
|
||||||
pipelineConfig.depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
pipelineConfig.depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||||
|
|
||||||
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
|
||||||
|
|
||||||
pipeline = std::make_unique<Pipeline>(
|
pipeline = std::make_unique<Pipeline>(
|
||||||
gfxDevice,
|
gfxDevice,
|
||||||
@@ -65,34 +79,58 @@ void SkyboxPipeline::init(GfxDevice& gfxDevice, VkFormat drawImageFormat, VkForm
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyboxPipeline::cleanup(VkDevice device) {
|
void SkyboxPipeline::cleanup(VkDevice device)
|
||||||
|
{
|
||||||
pipeline.reset();
|
pipeline.reset();
|
||||||
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
|
||||||
|
if (pipelineLayout != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
|
||||||
|
pipelineLayout = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkyboxPipeline::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera) {
|
void SkyboxPipeline::draw(
|
||||||
|
VkCommandBuffer cmd,
|
||||||
|
RenderResources& resources,
|
||||||
|
const Camera& camera)
|
||||||
|
{
|
||||||
if (skyboxTextureId == NULL_IMAGE_ID) {
|
if (skyboxTextureId == NULL_IMAGE_ID) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//rotate skybox slowly for visual interest
|
const float rotationSpeed = 0.01f;
|
||||||
const float rotationSpeed = 0.01f; // radians per second
|
|
||||||
//Rotate over the Y axis
|
skyboxRotation = glm::rotate(
|
||||||
skyboxRotation = glm::rotate(skyboxRotation, rotationSpeed * static_cast<float>(Time::GetInstance().DeltaTime()), glm::vec3(0.f, 1.f, 0.f));
|
skyboxRotation,
|
||||||
|
rotationSpeed * static_cast<float>(Time::GetInstance().DeltaTime()),
|
||||||
|
glm::vec3(0.f, 1.f, 0.f));
|
||||||
|
|
||||||
pipeline->bind(cmd);
|
pipeline->bind(cmd);
|
||||||
|
|
||||||
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
||||||
|
|
||||||
gfxDevice.bindBindlessDescSet(cmd, pipelineLayout);
|
resources.bindBindlessDescSet(cmd, pipelineLayout);
|
||||||
|
|
||||||
const glm::mat3 r = glm::mat3(skyboxRotation);
|
const glm::mat3 r = glm::mat3(skyboxRotation);
|
||||||
|
|
||||||
const auto pcs = SkyboxPushConstants{
|
const auto pcs = SkyboxPushConstants{
|
||||||
.invViewProj = glm::inverse(camera.GetViewProjectionMatrix()),
|
.invViewProj = glm::inverse(camera.GetViewProjectionMatrix()),
|
||||||
.skyboxRot = { glm::vec4(r[0], 0.f), glm::vec4(r[1], 0.f), glm::vec4(r[2], 0.f) },
|
.skyboxRot = {
|
||||||
.cameraPos = camera.GetPosition(),
|
glm::vec4(r[0], 0.f),
|
||||||
|
glm::vec4(r[1], 0.f),
|
||||||
|
glm::vec4(r[2], 0.f)
|
||||||
|
},
|
||||||
|
.cameraPos = camera.GetPosition(),
|
||||||
.skyboxTextureId = static_cast<std::uint32_t>(skyboxTextureId),
|
.skyboxTextureId = static_cast<std::uint32_t>(skyboxTextureId),
|
||||||
};
|
};
|
||||||
vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(SkyboxPushConstants), &pcs);
|
|
||||||
|
vkCmdPushConstants(
|
||||||
|
cmd,
|
||||||
|
pipelineLayout,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0,
|
||||||
|
sizeof(SkyboxPushConstants),
|
||||||
|
&pcs);
|
||||||
|
|
||||||
vkCmdDraw(cmd, 3, 1, 0, 0);
|
vkCmdDraw(cmd, 3, 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
|
||||||
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
|
#include <destrum/Graphics/Util.h>
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
RenderResources::RenderResources() = default;
|
||||||
|
|
||||||
|
void RenderResources::init(GfxDevice& gfxDevice)
|
||||||
|
{
|
||||||
|
imageCache = std::make_unique<ImageCache>(gfxDevice);
|
||||||
|
meshCache = std::make_unique<MeshCache>();
|
||||||
|
materialCache = std::make_unique<MaterialCache>();
|
||||||
|
|
||||||
|
VkPhysicalDeviceProperties props{};
|
||||||
|
vkGetPhysicalDeviceProperties(gfxDevice.getVkPhysicalDevice(), &props);
|
||||||
|
|
||||||
|
imageCache->bindlessSetManager.init(
|
||||||
|
gfxDevice.getVkDevice(),
|
||||||
|
props.limits.maxSamplerAnisotropy);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::uint32_t white = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
whiteImageId = createImage(
|
||||||
|
gfxDevice,
|
||||||
|
{
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
.extent = VkExtent3D{1, 1, 1},
|
||||||
|
},
|
||||||
|
"white texture",
|
||||||
|
&white);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::uint32_t normal = 0xFFFF8080; // tangent-space normal: 0.5, 0.5, 1.0, 1.0
|
||||||
|
|
||||||
|
defaultNormalImageId = createImage(
|
||||||
|
gfxDevice,
|
||||||
|
{
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
.extent = VkExtent3D{1, 1, 1},
|
||||||
|
},
|
||||||
|
"default normal texture",
|
||||||
|
&normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
constexpr auto black = 0xFF000000;
|
||||||
|
constexpr auto magenta = 0xFFFF00FF;
|
||||||
|
|
||||||
|
std::array<std::uint32_t, 4> pixels{
|
||||||
|
black, magenta,
|
||||||
|
magenta, black
|
||||||
|
};
|
||||||
|
|
||||||
|
errorImageId = createImage(
|
||||||
|
gfxDevice,
|
||||||
|
{
|
||||||
|
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
.usage = VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
|
.extent = VkExtent3D{2, 2, 1},
|
||||||
|
},
|
||||||
|
"error texture",
|
||||||
|
pixels.data());
|
||||||
|
|
||||||
|
imageCache->setErrorImageId(errorImageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
materialCache->init(
|
||||||
|
gfxDevice,
|
||||||
|
MaterialDefaultTextures{
|
||||||
|
.white = whiteImageId,
|
||||||
|
.normal = defaultNormalImageId,
|
||||||
|
.metallicRoughness = whiteImageId,
|
||||||
|
.emissive = whiteImageId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageID RenderResources::createImage(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const vkutil::CreateImageInfo& createInfo,
|
||||||
|
const std::string& debugName,
|
||||||
|
void* pixelData,
|
||||||
|
ImageID imageId)
|
||||||
|
{
|
||||||
|
auto image = gfxDevice.createImageRaw(createInfo);
|
||||||
|
|
||||||
|
if (!debugName.empty()) {
|
||||||
|
vkutil::addDebugLabel(gfxDevice.getVkDevice(), image.image, debugName.c_str());
|
||||||
|
image.debugName = debugName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelData) {
|
||||||
|
const std::size_t bytes =
|
||||||
|
std::size_t(image.extent.width) *
|
||||||
|
std::size_t(image.extent.height) *
|
||||||
|
std::size_t(image.extent.depth) *
|
||||||
|
BytesPerTexel(image.format);
|
||||||
|
|
||||||
|
gfxDevice.uploadImageDataSized(image, pixelData, bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageId != NULL_IMAGE_ID) {
|
||||||
|
return imageCache->addImage(imageId, std::move(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
return addImageToCache(std::move(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageID RenderResources::createDrawImage(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
VkFormat format,
|
||||||
|
glm::ivec2 size,
|
||||||
|
const std::string& debugName,
|
||||||
|
ImageID imageId)
|
||||||
|
{
|
||||||
|
assert(size.x > 0 && size.y > 0);
|
||||||
|
|
||||||
|
const auto extent = VkExtent3D{
|
||||||
|
.width = static_cast<std::uint32_t>(size.x),
|
||||||
|
.height = static_cast<std::uint32_t>(size.y),
|
||||||
|
.depth = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkImageUsageFlags usages{};
|
||||||
|
usages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
usages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
usages |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
usages |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
|
||||||
|
const auto createImageInfo = vkutil::CreateImageInfo{
|
||||||
|
.format = format,
|
||||||
|
.usage = usages,
|
||||||
|
.extent = extent,
|
||||||
|
};
|
||||||
|
|
||||||
|
return createImage(gfxDevice, createImageInfo, debugName, nullptr, imageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageID RenderResources::loadImageFromFile(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
const std::filesystem::path& path,
|
||||||
|
VkImageUsageFlags usage,
|
||||||
|
bool mipMap,
|
||||||
|
TextureIntent intent)
|
||||||
|
{
|
||||||
|
return imageCache->loadImageFromFile(path, usage, mipMap, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GPUImage& RenderResources::getImage(ImageID id) const {
|
||||||
|
return imageCache->getImage(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageID RenderResources::addImageToCache(GPUImage image) {
|
||||||
|
return imageCache->addImage(std::move(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
BindlessSetManager& RenderResources::getBindlessSetManager() {
|
||||||
|
return imageCache->bindlessSetManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorSetLayout RenderResources::getBindlessDescSetLayout() const {
|
||||||
|
return imageCache->bindlessSetManager.getDescSetLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
const VkDescriptorSet& RenderResources::getBindlessDescSet() const {
|
||||||
|
return imageCache->bindlessSetManager.getDescSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderResources::bindBindlessDescSet(VkCommandBuffer cmd, VkPipelineLayout layout) const {
|
||||||
|
vkCmdBindDescriptorSets(
|
||||||
|
cmd,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
layout,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
&imageCache->bindlessSetManager.getDescSet(),
|
||||||
|
0,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t RenderResources::BytesPerTexel(VkFormat fmt)
|
||||||
|
{
|
||||||
|
switch (fmt) {
|
||||||
|
case VK_FORMAT_R8_UNORM:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||||
|
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||||
|
return 16;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("RenderResources::BytesPerTexel: unsupported format");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,10 +7,13 @@
|
|||||||
|
|
||||||
#include "tracy/TracyVulkan.hpp"
|
#include "tracy/TracyVulkan.hpp"
|
||||||
|
|
||||||
GameRenderer::GameRenderer(MeshCache& meshCache, MaterialCache& matCache): meshCache{meshCache}, materialCache{matCache} {
|
GameRenderer::GameRenderer()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::init(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize) {
|
void GameRenderer::init(GfxDevice& gfxDevice, RenderResources& _resources, glm::ivec2 drawImageSize)
|
||||||
|
{
|
||||||
|
resources = &_resources;
|
||||||
sceneDataBuffer.init(
|
sceneDataBuffer.init(
|
||||||
gfxDevice,
|
gfxDevice,
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||||
@@ -20,10 +23,10 @@ void GameRenderer::init(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize) {
|
|||||||
createDrawImage(gfxDevice, drawImageSize, true);
|
createDrawImage(gfxDevice, drawImageSize, true);
|
||||||
|
|
||||||
meshPipeline = std::make_unique<MeshPipeline>();
|
meshPipeline = std::make_unique<MeshPipeline>();
|
||||||
meshPipeline->init(gfxDevice, drawImageFormat, depthImageFormat);
|
meshPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||||
|
|
||||||
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
skyboxPipeline = std::make_unique<SkyboxPipeline>();
|
||||||
skyboxPipeline->init(gfxDevice, drawImageFormat, depthImageFormat);
|
skyboxPipeline->init(gfxDevice, _resources, drawImageFormat, depthImageFormat);
|
||||||
|
|
||||||
skinningPipeline = std::make_unique<SkinningPipeline>();
|
skinningPipeline = std::make_unique<SkinningPipeline>();
|
||||||
skinningPipeline->init(gfxDevice);
|
skinningPipeline->init(gfxDevice);
|
||||||
@@ -32,28 +35,33 @@ void GameRenderer::init(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize) {
|
|||||||
GameState::GetInstance().SetRenderer(this);
|
GameState::GetInstance().SetRenderer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::beginDrawing(GfxDevice& gfxDevice) {
|
void GameRenderer::beginDrawing(GfxDevice& gfxDevice)
|
||||||
|
{
|
||||||
flushMaterialUpdates(gfxDevice);
|
flushMaterialUpdates(gfxDevice);
|
||||||
meshDrawCommands.clear();
|
meshDrawCommands.clear();
|
||||||
skinningPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
skinningPipeline->beginDrawing(gfxDevice.getCurrentFrameIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::endDrawing() {
|
void GameRenderer::endDrawing()
|
||||||
|
{
|
||||||
//Sort the drawlist
|
//Sort the drawlist
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera, const SceneData& sceneData) {
|
void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera& camera, const SceneData& sceneData)
|
||||||
|
{
|
||||||
ZoneScopedN("GameRenderer::draw");
|
ZoneScopedN("GameRenderer::draw");
|
||||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "GameRenderer::draw");
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "GameRenderer::draw");
|
||||||
|
|
||||||
{
|
{
|
||||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Skinning");
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Skinning");
|
||||||
|
|
||||||
for (const auto& dc : meshDrawCommands) {
|
for (const auto& dc : meshDrawCommands)
|
||||||
if (!dc.skinnedMesh) {
|
{
|
||||||
|
if (!dc.skinnedMesh)
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
skinningPipeline->doSkinning(cmd, gfxDevice.getCurrentFrameIndex(), meshCache, dc);
|
skinningPipeline->doSkinning(cmd, gfxDevice.getCurrentFrameIndex(), resources->meshes(), dc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +74,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
.ambientIntensity = sceneData.ambientIntensity,
|
.ambientIntensity = sceneData.ambientIntensity,
|
||||||
.fogColor = {sceneData.fogColor},
|
.fogColor = {sceneData.fogColor},
|
||||||
.fogDensity = sceneData.fogDensity,
|
.fogDensity = sceneData.fogDensity,
|
||||||
.materialsBuffer = materialCache.getMaterialDataBufferAddress(),
|
.materialsBuffer = resources->materials().getMaterialDataBufferAddress(),
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -74,7 +82,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
|
|
||||||
vkutil::bufferHostWriteToShaderReadBarrier(
|
vkutil::bufferHostWriteToShaderReadBarrier(
|
||||||
cmd,
|
cmd,
|
||||||
materialCache.getMaterialDataBuffer().buffer,
|
resources->materials().getMaterialDataBuffer().buffer,
|
||||||
0,
|
0,
|
||||||
VK_WHOLE_SIZE
|
VK_WHOLE_SIZE
|
||||||
);
|
);
|
||||||
@@ -91,10 +99,9 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& drawImage = gfxDevice.getImage(drawImageId);
|
const auto& drawImage = resources->getImage(drawImageId);
|
||||||
const auto& depthImage = gfxDevice.getImage(depthImageId);
|
const auto& depthImage = resources->getImage(depthImageId);
|
||||||
|
|
||||||
// vkutil::cmdBeginLabel(cmd, "Geometry");
|
|
||||||
{
|
{
|
||||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Transition Draw Image");
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "Transition Draw Image");
|
||||||
|
|
||||||
@@ -135,9 +142,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
meshPipeline->draw(
|
meshPipeline->draw(
|
||||||
cmd,
|
cmd,
|
||||||
drawImage.getExtent2D(),
|
drawImage.getExtent2D(),
|
||||||
gfxDevice,
|
*resources,
|
||||||
meshCache,
|
|
||||||
materialCache,
|
|
||||||
camera,
|
camera,
|
||||||
sceneDataBuffer.getBuffer(),
|
sceneDataBuffer.getBuffer(),
|
||||||
meshDrawCommands,
|
meshDrawCommands,
|
||||||
@@ -147,7 +152,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
{
|
{
|
||||||
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "SkyboxPipeline::draw");
|
TracyVkZone(gfxDevice.getTracyVkCtx(), cmd, "SkyboxPipeline::draw");
|
||||||
|
|
||||||
skyboxPipeline->draw(cmd, gfxDevice, camera);
|
skyboxPipeline->draw(cmd, *resources, camera);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -158,7 +163,8 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
|||||||
// vkutil::cmdEndLabel(cmd);
|
// vkutil::cmdEndLabel(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::cleanup(GfxDevice& gfxDevice) {
|
void GameRenderer::cleanup(GfxDevice& gfxDevice)
|
||||||
|
{
|
||||||
VkDevice device = gfxDevice.getDevice().device;
|
VkDevice device = gfxDevice.getDevice().device;
|
||||||
|
|
||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
@@ -175,17 +181,18 @@ void GameRenderer::cleanup(GfxDevice& gfxDevice) {
|
|||||||
sceneDataBuffer.cleanup(gfxDevice);
|
sceneDataBuffer.cleanup(gfxDevice);
|
||||||
|
|
||||||
// if (drawImageId != NULL_IMAGE_ID)
|
// if (drawImageId != NULL_IMAGE_ID)
|
||||||
// gfxDevice.destroyImage();
|
// gfxDevice.destroyImage();
|
||||||
|
|
||||||
// if (depthImageId != NULL_IMAGE_ID)
|
// if (depthImageId != NULL_IMAGE_ID)
|
||||||
// gfxDevice.destroyImage(depthImageId);
|
// gfxDevice.destroyImage(depthImageId);
|
||||||
|
|
||||||
drawImageId = NULL_IMAGE_ID;
|
drawImageId = NULL_IMAGE_ID;
|
||||||
depthImageId = NULL_IMAGE_ID;
|
depthImageId = NULL_IMAGE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::drawMesh(MeshID id, const glm::mat4& transform, MaterialID materialId) {
|
void GameRenderer::drawMesh(MeshID id, const glm::mat4& transform, MaterialID materialId)
|
||||||
const auto& mesh = meshCache.getMesh(id);
|
{
|
||||||
|
const auto& mesh = resources->meshes().getMesh(id);
|
||||||
const auto worldBoundingSphere = edge::calculateBoundingSphereWorld(transform, mesh.boundingSphere, false);
|
const auto worldBoundingSphere = edge::calculateBoundingSphereWorld(transform, mesh.boundingSphere, false);
|
||||||
assert(materialId != NULL_MATERIAL_ID);
|
assert(materialId != NULL_MATERIAL_ID);
|
||||||
|
|
||||||
@@ -197,46 +204,54 @@ void GameRenderer::drawMesh(MeshID id, const glm::mat4& transform, MaterialID ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::drawSkinnedMesh(MeshID id,
|
void GameRenderer::drawSkinnedMesh(MeshID id,
|
||||||
const glm::mat4& transform,
|
const glm::mat4& transform,
|
||||||
MaterialID materialId,
|
MaterialID materialId,
|
||||||
SkinnedMesh* skinnedMesh,
|
SkinnedMesh* skinnedMesh,
|
||||||
std::size_t jointMatricesStartIndex) {
|
std::size_t jointMatricesStartIndex)
|
||||||
const auto& mesh = meshCache.getMesh(id);
|
{
|
||||||
const auto worldBoundingSphere = edge::calculateBoundingSphereWorld(transform, mesh.boundingSphere, false);
|
const auto& mesh = resources->meshes().getMesh(id);
|
||||||
|
const auto worldBoundingSphere = edge::calculateBoundingSphereWorld(transform, mesh.boundingSphere, false);
|
||||||
assert(materialId != NULL_MATERIAL_ID);
|
assert(materialId != NULL_MATERIAL_ID);
|
||||||
assert(skinnedMesh != nullptr);
|
assert(skinnedMesh != nullptr);
|
||||||
|
|
||||||
meshDrawCommands.push_back(MeshDrawCommand{
|
meshDrawCommands.push_back(MeshDrawCommand{
|
||||||
.meshId = id,
|
.meshId = id,
|
||||||
.transformMatrix = transform,
|
.transformMatrix = transform,
|
||||||
.materialId = materialId,
|
.materialId = materialId,
|
||||||
.skinnedMesh = skinnedMesh,
|
.skinnedMesh = skinnedMesh,
|
||||||
.jointMatricesStartIndex = static_cast<std::uint32_t>(jointMatricesStartIndex),
|
.jointMatricesStartIndex = static_cast<std::uint32_t>(jointMatricesStartIndex),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const GPUImage& GameRenderer::getDrawImage(const GfxDevice& gfx_device) const {
|
const GPUImage& GameRenderer::getDrawImage() const
|
||||||
return gfx_device.getImage(drawImageId);
|
{
|
||||||
|
assert(resources);
|
||||||
|
return resources->getImage(drawImageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Material& GameRenderer::getMaterialMutable(MaterialID id) {
|
Material& GameRenderer::getMaterialMutable(MaterialID id)
|
||||||
|
{
|
||||||
assert(id != NULL_MATERIAL_ID);
|
assert(id != NULL_MATERIAL_ID);
|
||||||
return materialCache.getMaterialMutable(id);
|
return resources->materials().getMaterialMutable(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::updateMaterialGPU(MaterialID id) {
|
void GameRenderer::updateMaterialGPU(MaterialID id)
|
||||||
|
{
|
||||||
assert(id != NULL_MATERIAL_ID);
|
assert(id != NULL_MATERIAL_ID);
|
||||||
pendingMaterialUploads.push_back(id);
|
pendingMaterialUploads.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::setSkyboxTexture(ImageID skyboxImageId) {
|
void GameRenderer::setSkyboxTexture(ImageID skyboxImageId)
|
||||||
|
{
|
||||||
spdlog::debug("Set skybox texture to image id {}", skyboxImageId);
|
spdlog::debug("Set skybox texture to image id {}", skyboxImageId);
|
||||||
skyboxPipeline->setSkyboxImage(skyboxImageId);
|
skyboxPipeline->setSkyboxImage(skyboxImageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameRenderer::flushMaterialUpdates(GfxDevice& gfxDevice) {
|
void GameRenderer::flushMaterialUpdates(GfxDevice& gfxDevice)
|
||||||
for (MaterialID id : pendingMaterialUploads) {
|
{
|
||||||
materialCache.updateMaterialGPU(gfxDevice, id);
|
for (MaterialID id : pendingMaterialUploads)
|
||||||
|
{
|
||||||
|
resources->materials().updateMaterialGPU(id);
|
||||||
// if non-coherent: flush mapped range for that id here
|
// if non-coherent: flush mapped range for that id here
|
||||||
}
|
}
|
||||||
pendingMaterialUploads.clear();
|
pendingMaterialUploads.clear();
|
||||||
@@ -247,14 +262,15 @@ void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
|||||||
bool firstCreate)
|
bool firstCreate)
|
||||||
{
|
{
|
||||||
const VkExtent3D drawImageExtent{
|
const VkExtent3D drawImageExtent{
|
||||||
.width = (std::uint32_t)drawImageSize.x,
|
.width = (std::uint32_t)drawImageSize.x,
|
||||||
.height = (std::uint32_t)drawImageSize.y,
|
.height = (std::uint32_t)drawImageSize.y,
|
||||||
.depth = 1,
|
.depth = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr VkSampleCountFlagBits noMsaa = VK_SAMPLE_COUNT_1_BIT;
|
constexpr VkSampleCountFlagBits noMsaa = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
|
||||||
{ // setup draw image (single-sampled)
|
{
|
||||||
|
// setup draw image (single-sampled)
|
||||||
VkImageUsageFlags usages{};
|
VkImageUsageFlags usages{};
|
||||||
usages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
usages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
usages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
usages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
@@ -262,32 +278,33 @@ void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
|||||||
usages |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
usages |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
|
||||||
auto createImageInfo = vkutil::CreateImageInfo{
|
auto createImageInfo = vkutil::CreateImageInfo{
|
||||||
.format = drawImageFormat,
|
.format = drawImageFormat,
|
||||||
.usage = usages,
|
.usage = usages,
|
||||||
.extent = drawImageExtent,
|
.extent = drawImageExtent,
|
||||||
.samples = noMsaa,
|
.samples = noMsaa,
|
||||||
};
|
};
|
||||||
|
|
||||||
// reuse the same id if creating again
|
// reuse the same id if creating again
|
||||||
drawImageId = gfxDevice.createImage(createImageInfo, "draw image", nullptr, drawImageId);
|
drawImageId = resources->createImage(gfxDevice, createImageInfo, "draw image", nullptr, drawImageId);
|
||||||
|
|
||||||
if (firstCreate) {
|
if (firstCreate)
|
||||||
|
{
|
||||||
// Optional: a separate post-fx target (ping-pong)
|
// Optional: a separate post-fx target (ping-pong)
|
||||||
// postFXDrawImageId = gfxDevice.createImage(createImageInfo, "post FX draw image");
|
// postFXDrawImageId = gfxDevice.createImage(createImageInfo, "post FX draw image");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{ // setup depth image (single-sampled)
|
{
|
||||||
|
// setup depth image (single-sampled)
|
||||||
auto createInfo = vkutil::CreateImageInfo{
|
auto createInfo = vkutil::CreateImageInfo{
|
||||||
.format = depthImageFormat,
|
.format = depthImageFormat,
|
||||||
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
.extent = drawImageExtent,
|
.extent = drawImageExtent,
|
||||||
.samples = noMsaa,
|
.samples = noMsaa,
|
||||||
};
|
};
|
||||||
|
|
||||||
depthImageId = gfxDevice.createImage(createInfo, "depth image", nullptr, depthImageId);
|
depthImageId = resources->createImage(gfxDevice, createInfo, "depth image", nullptr, depthImageId);
|
||||||
spdlog::info("Created depth image with id {}", depthImageId);
|
spdlog::info("Created depth image with id {}", depthImageId);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,76 @@
|
|||||||
#include <destrum/Graphics/Resources/Cubemap.h>
|
#include <destrum/Graphics/Resources/Cubemap.h>
|
||||||
|
|
||||||
#include "destrum/FS/AssetFS.h"
|
#include <destrum/Graphics/GfxDevice.h>
|
||||||
#include "destrum/Graphics/GfxDevice.h"
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
#include "destrum/Graphics/Pipeline.h"
|
#include <destrum/Graphics/Pipeline.h>
|
||||||
#include "destrum/Util/GameState.h"
|
|
||||||
#include <destrum/Graphics/Util.h>
|
#include <destrum/Graphics/Util.h>
|
||||||
|
|
||||||
#include "glm/ext/matrix_clip_space.hpp"
|
#include <glm/ext/matrix_clip_space.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
CubeMap::CubeMap()
|
||||||
CubeMap::CubeMap() {
|
{
|
||||||
m_projection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f);;
|
m_projection = glm::perspective(
|
||||||
|
glm::radians(90.0f),
|
||||||
|
1.0f,
|
||||||
|
0.1f,
|
||||||
|
10.0f
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
CubeMap::~CubeMap() {
|
CubeMap::~CubeMap() = default;
|
||||||
auto& gfx = GameState::GetInstance().Gfx();
|
|
||||||
VkDevice device = gfx.getDevice();
|
|
||||||
|
|
||||||
if (m_skyboxView) {
|
void CubeMap::cleanup(GfxDevice& gfxDevice)
|
||||||
vkDestroyImageView(device, m_skyboxView, nullptr);
|
{
|
||||||
m_skyboxView = VK_NULL_HANDLE;
|
VkDevice device = gfxDevice.getDevice();
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cubemapPipelineLayout) {
|
m_cubemapPipeline.reset();
|
||||||
|
|
||||||
|
if (m_cubemapPipelineLayout != VK_NULL_HANDLE) {
|
||||||
vkDestroyPipelineLayout(device, m_cubemapPipelineLayout, nullptr);
|
vkDestroyPipelineLayout(device, m_cubemapPipelineLayout, nullptr);
|
||||||
m_cubemapPipelineLayout = VK_NULL_HANDLE;
|
m_cubemapPipelineLayout = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_cubemapImageID = NULL_IMAGE_ID;
|
||||||
|
m_hdrImage = NULL_IMAGE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeMap::LoadCubeMap(const std::filesystem::path& directoryPath) {
|
void CubeMap::LoadCubeMap(
|
||||||
// m_hdrImage = GameState::GetInstance().Gfx().loadImageFromFile(directoryPath, VK_FORMAT_R8G8B8A8_SRGB, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, false);
|
GfxDevice& gfxDevice,
|
||||||
m_hdrImage = GameState::GetInstance().Gfx().loadImageFromFile(directoryPath, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, false);
|
RenderResources& resources,
|
||||||
|
const std::filesystem::path& directoryPath)
|
||||||
|
{
|
||||||
|
m_hdrImage = resources.loadImageFromFile(
|
||||||
|
gfxDevice,
|
||||||
|
directoryPath,
|
||||||
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeMap::RenderToCubemap(ImageID inputImage,
|
void CubeMap::RenderToCubemap(
|
||||||
VkImage outputImage,
|
GfxDevice& gfxDevice,
|
||||||
std::array<VkImageView, 6> faceViews,
|
RenderResources& resources,
|
||||||
uint32_t size)
|
ImageID inputImage,
|
||||||
|
VkImage outputImage,
|
||||||
|
std::array<VkImageView, 6> faceViews,
|
||||||
|
std::uint32_t size)
|
||||||
{
|
{
|
||||||
// Ensure pipeline exists
|
|
||||||
if (!m_cubemapPipeline || m_cubemapPipelineLayout == VK_NULL_HANDLE) {
|
if (!m_cubemapPipeline || m_cubemapPipelineLayout == VK_NULL_HANDLE) {
|
||||||
throw std::runtime_error("Cubemap pipeline not initialized. Call InitCubemapPipeline first.");
|
throw std::runtime_error(
|
||||||
|
"Cubemap pipeline not initialized. Call InitCubemapPipeline first."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& gfx = GameState::GetInstance().Gfx();
|
gfxDevice.GetImmediateExecuter().immediateSubmit([&](VkCommandBuffer cmd) {
|
||||||
|
VkImageMemoryBarrier barrier{VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||||
gfx.GetImmediateExecuter().immediateSubmit([&](VkCommandBuffer cmd) {
|
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
@@ -75,7 +97,7 @@ void CubeMap::RenderToCubemap(ImageID inputImage,
|
|||||||
VkViewport viewport{};
|
VkViewport viewport{};
|
||||||
viewport.x = 0.0f;
|
viewport.x = 0.0f;
|
||||||
viewport.y = 0.0f;
|
viewport.y = 0.0f;
|
||||||
viewport.width = static_cast<float>(size);
|
viewport.width = static_cast<float>(size);
|
||||||
viewport.height = static_cast<float>(size);
|
viewport.height = static_cast<float>(size);
|
||||||
viewport.minDepth = 0.0f;
|
viewport.minDepth = 0.0f;
|
||||||
viewport.maxDepth = 1.0f;
|
viewport.maxDepth = 1.0f;
|
||||||
@@ -84,20 +106,24 @@ void CubeMap::RenderToCubemap(ImageID inputImage,
|
|||||||
scissor.offset = {0, 0};
|
scissor.offset = {0, 0};
|
||||||
scissor.extent = {size, size};
|
scissor.extent = {size, size};
|
||||||
|
|
||||||
for (uint32_t face = 0; face < 6; ++face) {
|
for (std::uint32_t face = 0; face < 6; ++face) {
|
||||||
PC pc{};
|
PC pc{};
|
||||||
pc.viewMtx = viewMatrices[face];
|
pc.viewMtx = viewMatrices[face];
|
||||||
pc.projMtx = m_projection;
|
pc.projMtx = m_projection;
|
||||||
pc.inputImageId = m_hdrImage;
|
pc.inputImageId = static_cast<std::uint32_t>(inputImage);
|
||||||
|
|
||||||
VkRenderingAttachmentInfoKHR colorAttachment{ VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR };
|
VkRenderingAttachmentInfoKHR colorAttachment{
|
||||||
|
VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR
|
||||||
|
};
|
||||||
colorAttachment.imageView = faceViews[face];
|
colorAttachment.imageView = faceViews[face];
|
||||||
colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
colorAttachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||||
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||||
colorAttachment.clearValue.color = {0.f, 0.f, 0.f, 1.f};
|
colorAttachment.clearValue.color = {0.f, 0.f, 0.f, 1.f};
|
||||||
|
|
||||||
VkRenderingInfoKHR renderingInfo{ VK_STRUCTURE_TYPE_RENDERING_INFO_KHR };
|
VkRenderingInfoKHR renderingInfo{
|
||||||
|
VK_STRUCTURE_TYPE_RENDERING_INFO_KHR
|
||||||
|
};
|
||||||
renderingInfo.renderArea.offset = {0, 0};
|
renderingInfo.renderArea.offset = {0, 0};
|
||||||
renderingInfo.renderArea.extent = {size, size};
|
renderingInfo.renderArea.extent = {size, size};
|
||||||
renderingInfo.layerCount = 1;
|
renderingInfo.layerCount = 1;
|
||||||
@@ -111,7 +137,8 @@ void CubeMap::RenderToCubemap(ImageID inputImage,
|
|||||||
|
|
||||||
m_cubemapPipeline->bind(cmd);
|
m_cubemapPipeline->bind(cmd);
|
||||||
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
vkCmdSetPolygonModeEXT(cmd, VK_POLYGON_MODE_FILL);
|
||||||
gfx.bindBindlessDescSet(cmd, m_cubemapPipelineLayout);
|
|
||||||
|
resources.bindBindlessDescSet(cmd, m_cubemapPipelineLayout);
|
||||||
|
|
||||||
vkCmdPushConstants(
|
vkCmdPushConstants(
|
||||||
cmd,
|
cmd,
|
||||||
@@ -127,7 +154,6 @@ void CubeMap::RenderToCubemap(ImageID inputImage,
|
|||||||
vkCmdEndRendering(cmd);
|
vkCmdEndRendering(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transition to shader read
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
@@ -145,54 +171,40 @@ void CubeMap::RenderToCubemap(ImageID inputImage,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeMap::CreateCubeMap() {
|
void CubeMap::CreateCubeMap(
|
||||||
const uint32_t mipLevels = static_cast<uint32_t>(std::floor(std::log2(m_cubeMapSize))) + 1;
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources)
|
||||||
|
{
|
||||||
|
if (m_hdrImage == NULL_IMAGE_ID) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Cannot create cubemap before loading HDR image. Call LoadCubeMap first."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
VkImageCreateInfo imageInfo{};
|
GPUImage cubeMapImage = gfxDevice.createImageRaw({
|
||||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
||||||
imageInfo.extent.height = m_cubeMapSize;
|
|
||||||
imageInfo.extent.width = m_cubeMapSize;
|
|
||||||
imageInfo.extent.depth = 1;
|
|
||||||
imageInfo.mipLevels = mipLevels;
|
|
||||||
imageInfo.arrayLayers = 6; // 6 faces for cubemap
|
|
||||||
imageInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; // Create a cubemap
|
|
||||||
|
|
||||||
VmaAllocationCreateInfo allocInfo{};
|
|
||||||
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
|
||||||
|
|
||||||
auto& device = GameState::GetInstance().Gfx();
|
|
||||||
GPUImage cubeMapID = device.createImageRaw({
|
|
||||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
.usage =
|
||||||
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||||
|
VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
|
||||||
.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
|
.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
|
||||||
.extent =
|
.extent = VkExtent3D{
|
||||||
VkExtent3D{
|
.width = m_cubeMapSize,
|
||||||
.width = m_cubeMapSize,
|
.height = m_cubeMapSize,
|
||||||
.height = m_cubeMapSize,
|
.depth = 1,
|
||||||
.depth = 1,
|
},
|
||||||
},
|
|
||||||
.numLayers = 6,
|
.numLayers = 6,
|
||||||
.mipMap = true,
|
.mipMap = false,
|
||||||
.isCubemap = true
|
.isCubemap = true
|
||||||
});
|
});
|
||||||
|
|
||||||
// if (vmaCreateImage(device.getAllocator(), &imageInfo, &allocInfo, &cubeMapID.image, &cubeMapID.allocation, nullptr) != VK_SUCCESS) {
|
|
||||||
// throw std::runtime_error("Failed to create image with VMA!");
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
std::array<VkImageView, 6> faceViews{};
|
std::array<VkImageView, 6> faceViews{};
|
||||||
for (uint32_t face = 0; face < 6; ++face) {
|
|
||||||
|
for (std::uint32_t face = 0; face < 6; ++face) {
|
||||||
VkImageViewCreateInfo viewInfo{};
|
VkImageViewCreateInfo viewInfo{};
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
viewInfo.image = cubeMapID.image;
|
viewInfo.image = cubeMapImage.image;
|
||||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
viewInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
viewInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
@@ -201,70 +213,81 @@ void CubeMap::CreateCubeMap() {
|
|||||||
viewInfo.subresourceRange.baseArrayLayer = face;
|
viewInfo.subresourceRange.baseArrayLayer = face;
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
if (vkCreateImageView(device.getDevice(), &viewInfo, nullptr, &faceViews[face]) != VK_SUCCESS) {
|
if (vkCreateImageView(
|
||||||
throw std::runtime_error("Failed to create image view!");
|
gfxDevice.getDevice(),
|
||||||
|
&viewInfo,
|
||||||
|
nullptr,
|
||||||
|
&faceViews[face]) != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to create cubemap face image view.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo{};
|
spdlog::info("HDRI image id = {}", m_hdrImage);
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
viewInfo.image = cubeMapID.image;
|
|
||||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
|
|
||||||
viewInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
|
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
||||||
viewInfo.subresourceRange.layerCount = 6;
|
|
||||||
|
|
||||||
|
RenderToCubemap(
|
||||||
|
gfxDevice,
|
||||||
|
resources,
|
||||||
|
m_hdrImage,
|
||||||
|
cubeMapImage.image,
|
||||||
|
faceViews,
|
||||||
|
m_cubeMapSize
|
||||||
|
);
|
||||||
|
|
||||||
if (vkCreateImageView(device.getDevice(), &viewInfo, nullptr, &m_skyboxView) != VK_SUCCESS) {
|
m_cubemapImageID = resources.addImageToCache(std::move(cubeMapImage));
|
||||||
throw std::runtime_error("Failed to create image view!");
|
|
||||||
}
|
|
||||||
const auto vertPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.vert");
|
|
||||||
const auto fragPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag");
|
|
||||||
spdlog::info("hdriImage id = {}", m_hdrImage);
|
|
||||||
RenderToCubemap(m_hdrImage, cubeMapID.image, faceViews, m_cubeMapSize);
|
|
||||||
|
|
||||||
m_cubemapImageID = GameState::GetInstance().Gfx().addImageToCache(cubeMapID);
|
for (VkImageView view : faceViews) {
|
||||||
|
if (view != VK_NULL_HANDLE) {
|
||||||
for (auto v : faceViews) {
|
vkDestroyImageView(gfxDevice.getDevice(), view, nullptr);
|
||||||
vkDestroyImageView(device.getDevice(), v, nullptr);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageID CubeMap::GetCubeMapImageID() {
|
ImageID CubeMap::GetCubeMapImageID() const
|
||||||
|
{
|
||||||
return m_cubemapImageID;
|
return m_cubemapImageID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CubeMap::InitCubemapPipeline(const std::string& vertPath, const std::string& fragPath)
|
void CubeMap::InitCubemapPipeline(
|
||||||
|
GfxDevice& gfxDevice,
|
||||||
|
RenderResources& resources,
|
||||||
|
const std::string& vertPath,
|
||||||
|
const std::string& fragPath)
|
||||||
{
|
{
|
||||||
auto& gfx = GameState::GetInstance().Gfx();
|
if (m_cubemapPipeline) {
|
||||||
VkDevice device = gfx.getDevice();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_cubemapPipeline) return; // already created
|
VkDevice device = gfxDevice.getDevice();
|
||||||
|
|
||||||
// Save paths if you want
|
|
||||||
m_cubemapVert = vertPath;
|
m_cubemapVert = vertPath;
|
||||||
m_cubemapFrag = fragPath;
|
m_cubemapFrag = fragPath;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VkPushConstantRange pushConstantRange{};
|
VkPushConstantRange pushConstantRange{};
|
||||||
pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
pushConstantRange.stageFlags =
|
||||||
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
pushConstantRange.offset = 0;
|
pushConstantRange.offset = 0;
|
||||||
pushConstantRange.size = sizeof(PC);
|
pushConstantRange.size = sizeof(PC);
|
||||||
|
|
||||||
const auto layouts = std::array{ gfx.getBindlessDescSetLayout() };
|
const auto layouts = std::array{
|
||||||
|
resources.getBindlessDescSetLayout()
|
||||||
|
};
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
|
VkPipelineLayoutCreateInfo pipelineLayoutInfo{
|
||||||
pipelineLayoutInfo.setLayoutCount = static_cast<uint32_t>(layouts.size());
|
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
|
||||||
|
};
|
||||||
|
pipelineLayoutInfo.setLayoutCount = static_cast<std::uint32_t>(layouts.size());
|
||||||
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
pipelineLayoutInfo.pSetLayouts = layouts.data();
|
||||||
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
pipelineLayoutInfo.pushConstantRangeCount = 1;
|
||||||
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
|
pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
|
||||||
|
|
||||||
if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &m_cubemapPipelineLayout) != VK_SUCCESS) {
|
if (vkCreatePipelineLayout(
|
||||||
throw std::runtime_error("Failed to create cubemap pipeline layout!");
|
device,
|
||||||
|
&pipelineLayoutInfo,
|
||||||
|
nullptr,
|
||||||
|
&m_cubemapPipelineLayout) != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to create cubemap pipeline layout.");
|
||||||
}
|
}
|
||||||
|
|
||||||
PipelineConfigInfo pipelineConfig{};
|
PipelineConfigInfo pipelineConfig{};
|
||||||
@@ -273,14 +296,14 @@ void CubeMap::InitCubemapPipeline(const std::string& vertPath, const std::string
|
|||||||
pipelineConfig.vertexAttributeDescriptions = {};
|
pipelineConfig.vertexAttributeDescriptions = {};
|
||||||
pipelineConfig.vertexBindingDescriptions = {};
|
pipelineConfig.vertexBindingDescriptions = {};
|
||||||
pipelineConfig.pipelineLayout = m_cubemapPipelineLayout;
|
pipelineConfig.pipelineLayout = m_cubemapPipelineLayout;
|
||||||
pipelineConfig.colorAttachments = { VK_FORMAT_R32G32B32A32_SFLOAT }; // must match cubemap image view format
|
pipelineConfig.colorAttachments = {VK_FORMAT_R32G32B32A32_SFLOAT};
|
||||||
pipelineConfig.depthAttachment = VK_FORMAT_UNDEFINED;
|
pipelineConfig.depthAttachment = VK_FORMAT_UNDEFINED;
|
||||||
pipelineConfig.depthStencilInfo.depthTestEnable = VK_FALSE;
|
pipelineConfig.depthStencilInfo.depthTestEnable = VK_FALSE;
|
||||||
pipelineConfig.depthStencilInfo.depthWriteEnable = VK_FALSE;
|
pipelineConfig.depthStencilInfo.depthWriteEnable = VK_FALSE;
|
||||||
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
pipelineConfig.rasterizationInfo.cullMode = VK_CULL_MODE_NONE;
|
||||||
|
|
||||||
m_cubemapPipeline = std::make_unique<Pipeline>(
|
m_cubemapPipeline = std::make_unique<Pipeline>(
|
||||||
gfx,
|
gfxDevice,
|
||||||
vertPath,
|
vertPath,
|
||||||
fragPath,
|
fragPath,
|
||||||
pipelineConfig
|
pipelineConfig
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <destrum/App.h>
|
#include <destrum/App.h>
|
||||||
#include <destrum/Scene/SceneManager.h>
|
#include <destrum/Scene/SceneManager.h>
|
||||||
|
#include <destrum/Graphics/RenderResources.h>
|
||||||
|
|
||||||
#include "destrum/Graphics/Resources/Cubemap.h"
|
#include "destrum/Graphics/Resources/Cubemap.h"
|
||||||
#include "destrum/ObjectModel/GameObject.h"
|
#include "destrum/ObjectModel/GameObject.h"
|
||||||
@@ -19,10 +20,6 @@ public:
|
|||||||
|
|
||||||
void onWindowResize(int newWidth, int newHeight) override;
|
void onWindowResize(int newWidth, int newHeight) override;
|
||||||
private:
|
private:
|
||||||
MeshCache meshCache;
|
|
||||||
MaterialCache materialCache;
|
|
||||||
GameRenderer renderer;
|
|
||||||
|
|
||||||
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
|
Camera camera{glm::vec3(0.f, 0.f, -5.f), glm::vec3(0, 1, 0)};
|
||||||
|
|
||||||
MeshID sphereMesh;
|
MeshID sphereMesh;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "destrum/Util/ModelDocUtils.h"
|
#include "destrum/Util/ModelDocUtils.h"
|
||||||
|
|
||||||
|
|
||||||
LightKeeper::LightKeeper() : App(), renderer(meshCache, materialCache)
|
LightKeeper::LightKeeper() : App()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,8 +34,8 @@ LightKeeper::~LightKeeper()
|
|||||||
|
|
||||||
void LightKeeper::customInit()
|
void LightKeeper::customInit()
|
||||||
{
|
{
|
||||||
materialCache.init(gfxDevice);
|
resources.init(gfxDevice);
|
||||||
renderer.init(gfxDevice, m_params.renderSize);
|
renderer.init(gfxDevice, resources, m_params.renderSize);
|
||||||
|
|
||||||
const float aspectRatio = static_cast<float>(m_params.renderSize.x) / static_cast<float>(m_params.renderSize.y);
|
const float aspectRatio = static_cast<float>(m_params.renderSize.x) / static_cast<float>(m_params.renderSize.y);
|
||||||
camera.setAspectRatio(aspectRatio);
|
camera.setAspectRatio(aspectRatio);
|
||||||
@@ -56,7 +56,7 @@ void LightKeeper::customInit()
|
|||||||
auto testMesh = kittyPrimitive.mesh;
|
auto testMesh = kittyPrimitive.mesh;
|
||||||
testMesh.name = "Test Mesh";
|
testMesh.name = "Test Mesh";
|
||||||
|
|
||||||
auto testMeshID = meshCache.addMesh(gfxDevice, testMesh);
|
auto testMeshID = resources.meshes().addMesh(gfxDevice, testMesh);
|
||||||
spdlog::info("TestMesh uploaded with id: {}", testMeshID);
|
spdlog::info("TestMesh uploaded with id: {}", testMeshID);
|
||||||
|
|
||||||
const auto testTexturePath = ModelDocUtils::PickTexturePath(
|
const auto testTexturePath = ModelDocUtils::PickTexturePath(
|
||||||
@@ -65,10 +65,10 @@ void LightKeeper::customInit()
|
|||||||
AssetFS::GetInstance().GetFullPath("game://kitty.png")
|
AssetFS::GetInstance().GetFullPath("game://kitty.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto testimgID = gfxDevice.loadImageFromFile(testTexturePath);
|
const auto testimgID = resources.loadImageFromFile(gfxDevice, testTexturePath);
|
||||||
spdlog::info("Test image loaded from '{}' with id: {}", testTexturePath.generic_string(), testimgID);
|
spdlog::info("Test image loaded from '{}' with id: {}", testTexturePath.generic_string(), testimgID);
|
||||||
|
|
||||||
auto testMaterialID = materialCache.addMaterial(gfxDevice, {
|
auto testMaterialID = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
||||||
kittyModel, kittyPrimitive),
|
kittyModel, kittyPrimitive),
|
||||||
.diffuseTexture = testimgID,
|
.diffuseTexture = testimgID,
|
||||||
@@ -93,9 +93,9 @@ void LightKeeper::customInit()
|
|||||||
const auto fragShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag");
|
const auto fragShaderPath = AssetFS::GetInstance().GetCookedPathForFile("engine://shaders/cubemap.frag");
|
||||||
//
|
//
|
||||||
skyboxCubemap = std::make_unique<CubeMap>();
|
skyboxCubemap = std::make_unique<CubeMap>();
|
||||||
skyboxCubemap->LoadCubeMap(skyboxID.generic_string());
|
skyboxCubemap->LoadCubeMap(gfxDevice, resources, skyboxID.generic_string());
|
||||||
skyboxCubemap->InitCubemapPipeline(vertShaderPath.generic_string(), fragShaderPath.generic_string());
|
skyboxCubemap->InitCubemapPipeline(gfxDevice, resources, vertShaderPath.generic_string(), fragShaderPath.generic_string());
|
||||||
skyboxCubemap->CreateCubeMap();
|
skyboxCubemap->CreateCubeMap(gfxDevice, resources);
|
||||||
|
|
||||||
renderer.setSkyboxTexture(skyboxCubemap->GetCubeMapImageID());
|
renderer.setSkyboxTexture(skyboxCubemap->GetCubeMapImageID());
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ void LightKeeper::customInit()
|
|||||||
ModelDocUtils::LogModelDocSummary(planeModel, "plane.glb");
|
ModelDocUtils::LogModelDocSummary(planeModel, "plane.glb");
|
||||||
|
|
||||||
const auto& planePrimitive = ModelDocUtils::GetFirstPrimitiveOrThrow(planeModel, "game://plane.glb");
|
const auto& planePrimitive = ModelDocUtils::GetFirstPrimitiveOrThrow(planeModel, "game://plane.glb");
|
||||||
const auto planeMeshID = meshCache.addMesh(gfxDevice, planePrimitive.mesh);
|
const auto planeMeshID = resources.meshes().addMesh(gfxDevice, planePrimitive.mesh);
|
||||||
|
|
||||||
const auto planeTexturePath = ModelDocUtils::PickTexturePath(
|
const auto planeTexturePath = ModelDocUtils::PickTexturePath(
|
||||||
planeModel,
|
planeModel,
|
||||||
@@ -117,8 +117,8 @@ void LightKeeper::customInit()
|
|||||||
AssetFS::GetInstance().GetFullPath("game://grass.png")
|
AssetFS::GetInstance().GetFullPath("game://grass.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto planeTextureID = gfxDevice.loadImageFromFile(planeTexturePath);
|
const auto planeTextureID = resources.loadImageFromFile(gfxDevice, planeTexturePath);
|
||||||
const auto planeMaterialID = materialCache.addMaterial(gfxDevice, {
|
const auto planeMaterialID = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
||||||
planeModel, planePrimitive),
|
planeModel, planePrimitive),
|
||||||
.textureFilteringMode = TextureFilteringMode::Nearest,
|
.textureFilteringMode = TextureFilteringMode::Nearest,
|
||||||
@@ -157,7 +157,7 @@ void LightKeeper::customInit()
|
|||||||
"engine://cotw-capybara-male/source/capybara.fbx"
|
"engine://cotw-capybara-male/source/capybara.fbx"
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto charMeshID = meshCache.addMesh(gfxDevice, charPrimitive.mesh);
|
const auto charMeshID = resources.meshes().addMesh(gfxDevice, charPrimitive.mesh);
|
||||||
|
|
||||||
const auto charTexturePath = ModelDocUtils::PickTexturePath(
|
const auto charTexturePath = ModelDocUtils::PickTexturePath(
|
||||||
charModel,
|
charModel,
|
||||||
@@ -166,9 +166,9 @@ void LightKeeper::customInit()
|
|||||||
"engine://cotw-capybara-male/textures/capybara_male_light_brown_dif.ddsc.DECA.RE.pngballs")
|
"engine://cotw-capybara-male/textures/capybara_male_light_brown_dif.ddsc.DECA.RE.pngballs")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto charTextureID = gfxDevice.loadImageFromFile(charTexturePath);
|
const auto charTextureID = resources.loadImageFromFile(gfxDevice, charTexturePath);
|
||||||
// const auto charTextureID = gfxDevice.loadImageFromFile(AssetFS::GetInstance().GetFullPath("engine://char.jpg"));
|
// const auto charTextureID = gfxDevice.loadImageFromFile(AssetFS::GetInstance().GetFullPath("engine://char.jpg"));
|
||||||
const auto charMaterialID = materialCache.addMaterial(gfxDevice, {
|
const auto charMaterialID = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
||||||
charModel, charPrimitive),
|
charModel, charPrimitive),
|
||||||
.diffuseTexture = charTextureID,
|
.diffuseTexture = charTextureID,
|
||||||
@@ -282,13 +282,13 @@ void LightKeeper::customInit()
|
|||||||
"engine://characterMedium.fbx"
|
"engine://characterMedium.fbx"
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto charMeshID = meshCache.addMesh(gfxDevice, charPrimitive.mesh);
|
const auto charMeshID = resources.meshes().addMesh(gfxDevice, charPrimitive.mesh);
|
||||||
|
|
||||||
const auto charTextureID = gfxDevice.loadImageFromFile(
|
const auto charTextureID = resources.loadImageFromFile(gfxDevice,
|
||||||
AssetFS::GetInstance().GetFullPath("engine://textures/criminalMaleA.png")
|
AssetFS::GetInstance().GetFullPath("engine://textures/criminalMaleA.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto charMaterialID = materialCache.addMaterial(gfxDevice, {
|
const auto charMaterialID = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
||||||
charModel, charPrimitive),
|
charModel, charPrimitive),
|
||||||
.diffuseTexture = charTextureID,
|
.diffuseTexture = charTextureID,
|
||||||
@@ -345,8 +345,8 @@ void LightKeeper::customInit()
|
|||||||
AssetFS::GetInstance().GetFullPath("game://grass.png")
|
AssetFS::GetInstance().GetFullPath("game://grass.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto eliasTextueID = gfxDevice.loadImageFromFile(eliasTextuerPath);
|
const auto eliasTextueID = resources.loadImageFromFile(gfxDevice, eliasTextuerPath);
|
||||||
const auto eliasMaterialID = materialCache.addMaterial(gfxDevice, {
|
const auto eliasMaterialID = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
.baseColor = ModelDocUtils::GetImportedBaseColor(
|
||||||
planeModel, planePrimitive),
|
planeModel, planePrimitive),
|
||||||
.textureFilteringMode =
|
.textureFilteringMode =
|
||||||
@@ -356,7 +356,7 @@ void LightKeeper::customInit()
|
|||||||
planeModel, planePrimitive, "GroundPlaneMaterial"),
|
planeModel, planePrimitive, "GroundPlaneMaterial"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto cubeMeshID = meshCache.addMesh(gfxDevice, cubePrimitive.mesh);
|
const auto cubeMeshID = resources.meshes().addMesh(gfxDevice, cubePrimitive.mesh);
|
||||||
//
|
//
|
||||||
// for (int i{0}; i < 100; i++)
|
// for (int i{0}; i < 100; i++)
|
||||||
// {
|
// {
|
||||||
@@ -425,8 +425,8 @@ void LightKeeper::customInit()
|
|||||||
AssetFS::GetInstance().GetFullPath("game://238882.png")
|
AssetFS::GetInstance().GetFullPath("game://238882.png")
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto sphereTextureID = gfxDevice.loadImageFromFile(sphereTexturePath);
|
const auto sphereTextureID = resources.loadImageFromFile(gfxDevice, sphereTexturePath);
|
||||||
sphereMaterial = materialCache.addMaterial(gfxDevice, {
|
sphereMaterial = resources.materials().addMaterial({
|
||||||
.baseColor = ModelDocUtils::GetImportedBaseColor(planeModel, planePrimitive),
|
.baseColor = ModelDocUtils::GetImportedBaseColor(planeModel, planePrimitive),
|
||||||
.textureFilteringMode =TextureFilteringMode::Anisotropic,
|
.textureFilteringMode =TextureFilteringMode::Anisotropic,
|
||||||
.diffuseTexture = sphereTextureID,
|
.diffuseTexture = sphereTextureID,
|
||||||
@@ -435,7 +435,7 @@ void LightKeeper::customInit()
|
|||||||
"GroundPlaneMaterial"),
|
"GroundPlaneMaterial"),
|
||||||
});
|
});
|
||||||
|
|
||||||
sphereMesh = meshCache.addMesh(gfxDevice, spherePrimitive.mesh);
|
sphereMesh = resources.meshes().addMesh(gfxDevice, spherePrimitive.mesh);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -491,7 +491,7 @@ void LightKeeper::customDraw()
|
|||||||
renderer.endDrawing();
|
renderer.endDrawing();
|
||||||
|
|
||||||
const auto cmd = gfxDevice.beginFrame();
|
const auto cmd = gfxDevice.beginFrame();
|
||||||
const auto& drawImage = renderer.getDrawImage(gfxDevice);
|
const auto& drawImage = renderer.getDrawImage();
|
||||||
|
|
||||||
renderer.draw(
|
renderer.draw(
|
||||||
cmd, gfxDevice, camera, GameRenderer::SceneData{
|
cmd, gfxDevice, camera, GameRenderer::SceneData{
|
||||||
@@ -520,9 +520,6 @@ void LightKeeper::customCleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderer.cleanup(gfxDevice);
|
renderer.cleanup(gfxDevice);
|
||||||
|
|
||||||
materialCache.cleanup(gfxDevice);
|
|
||||||
meshCache.cleanup(gfxDevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightKeeper::customFixedUpdate(float dt)
|
void LightKeeper::customFixedUpdate(float dt)
|
||||||
|
|||||||
Reference in New Issue
Block a user