Add renderer phase A textured scene path

This commit is contained in:
2026-03-26 20:43:17 +08:00
parent 0921f2a459
commit a78593e7e1
32 changed files with 2455 additions and 9 deletions

View File

@@ -0,0 +1,33 @@
#pragma once
#include <XCEngine/Components/Component.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
#include <XCEngine/Resources/Mesh/Mesh.h>
#include <string>
namespace XCEngine {
namespace Components {
class MeshFilterComponent : public Component {
public:
std::string GetName() const override { return "MeshFilter"; }
Resources::Mesh* GetMesh() const { return m_mesh.Get(); }
const Resources::ResourceHandle<Resources::Mesh>& GetMeshHandle() const { return m_mesh; }
const std::string& GetMeshPath() const { return m_meshPath; }
void SetMesh(const Resources::ResourceHandle<Resources::Mesh>& mesh);
void SetMesh(Resources::Mesh* mesh);
void ClearMesh();
void Serialize(std::ostream& os) const override;
void Deserialize(std::istream& is) override;
private:
Resources::ResourceHandle<Resources::Mesh> m_mesh;
std::string m_meshPath;
};
} // namespace Components
} // namespace XCEngine

View File

@@ -0,0 +1,52 @@
#pragma once
#include <XCEngine/Components/Component.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
#include <XCEngine/Resources/Material/Material.h>
#include <cstdint>
#include <string>
#include <vector>
namespace XCEngine {
namespace Components {
class MeshRendererComponent : public Component {
public:
std::string GetName() const override { return "MeshRenderer"; }
size_t GetMaterialCount() const { return m_materials.size(); }
Resources::Material* GetMaterial(size_t index) const;
const Resources::ResourceHandle<Resources::Material>& GetMaterialHandle(size_t index) const;
const std::vector<std::string>& GetMaterialPaths() const { return m_materialPaths; }
void SetMaterial(size_t index, const Resources::ResourceHandle<Resources::Material>& material);
void SetMaterial(size_t index, Resources::Material* material);
void SetMaterials(const std::vector<Resources::ResourceHandle<Resources::Material>>& materials);
void ClearMaterials();
bool GetCastShadows() const { return m_castShadows; }
void SetCastShadows(bool value) { m_castShadows = value; }
bool GetReceiveShadows() const { return m_receiveShadows; }
void SetReceiveShadows(bool value) { m_receiveShadows = value; }
uint32_t GetRenderLayer() const { return m_renderLayer; }
void SetRenderLayer(uint32_t value) { m_renderLayer = value; }
void Serialize(std::ostream& os) const override;
void Deserialize(std::istream& is) override;
private:
void EnsureMaterialSlot(size_t index);
static std::string MaterialPathFromHandle(const Resources::ResourceHandle<Resources::Material>& material);
std::vector<Resources::ResourceHandle<Resources::Material>> m_materials;
std::vector<std::string> m_materialPaths;
bool m_castShadows = true;
bool m_receiveShadows = true;
uint32_t m_renderLayer = 0;
};
} // namespace Components
} // namespace XCEngine

View File

@@ -0,0 +1,77 @@
#pragma once
#include <XCEngine/Rendering/RenderPipeline.h>
#include <XCEngine/Rendering/RenderResourceCache.h>
#include <XCEngine/RHI/RHIDescriptorPool.h>
#include <XCEngine/RHI/RHIDescriptorSet.h>
#include <XCEngine/RHI/RHIPipelineLayout.h>
#include <XCEngine/RHI/RHIPipelineState.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHISampler.h>
#include <XCEngine/RHI/RHITexture.h>
namespace XCEngine {
namespace Resources {
class Material;
class Texture;
} // namespace Resources
namespace Rendering {
class RenderSurface;
namespace Pipelines {
class BuiltinForwardPipeline : public RenderPipeline {
public:
BuiltinForwardPipeline() = default;
~BuiltinForwardPipeline() override;
bool Initialize(const RenderContext& context) override;
void Shutdown() override;
bool Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) override;
private:
struct PerObjectConstants {
Math::Matrix4x4 projection = Math::Matrix4x4::Identity();
Math::Matrix4x4 view = Math::Matrix4x4::Identity();
Math::Matrix4x4 model = Math::Matrix4x4::Identity();
};
bool EnsureInitialized(const RenderContext& context);
bool CreatePipelineResources(const RenderContext& context);
void DestroyPipelineResources();
const Resources::Material* ResolveMaterial(const VisibleRenderObject& visibleObject, uint32_t materialIndex) const;
const Resources::Texture* ResolveTexture(const Resources::Material* material) const;
RHI::RHIResourceView* ResolveTextureView(const VisibleRenderObject& visibleObject, uint32_t materialIndex);
bool DrawVisibleObject(
const RenderContext& context,
const RenderSceneData& sceneData,
const VisibleRenderObject& visibleObject);
RHI::RHIDevice* m_device = nullptr;
RHI::RHIType m_backendType = RHI::RHIType::D3D12;
bool m_initialized = false;
RenderResourceCache m_resourceCache;
RHI::RHIDescriptorPool* m_constantPool = nullptr;
RHI::RHIDescriptorSet* m_constantSet = nullptr;
RHI::RHIDescriptorPool* m_texturePool = nullptr;
RHI::RHIDescriptorSet* m_textureSet = nullptr;
RHI::RHIDescriptorPool* m_samplerPool = nullptr;
RHI::RHIDescriptorSet* m_samplerSet = nullptr;
RHI::RHIPipelineLayout* m_pipelineLayout = nullptr;
RHI::RHIPipelineState* m_pipelineState = nullptr;
RHI::RHISampler* m_sampler = nullptr;
RHI::RHITexture* m_fallbackTexture = nullptr;
RHI::RHIResourceView* m_fallbackTextureView = nullptr;
};
} // namespace Pipelines
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,23 @@
#pragma once
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Core/Math/Matrix4.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <cstdint>
namespace XCEngine {
namespace Rendering {
struct RenderCameraData {
Math::Matrix4x4 view = Math::Matrix4x4::Identity();
Math::Matrix4x4 projection = Math::Matrix4x4::Identity();
Math::Matrix4x4 viewProjection = Math::Matrix4x4::Identity();
Math::Vector3 worldPosition = Math::Vector3::Zero();
Math::Color clearColor = Math::Color::Black();
uint32_t viewportWidth = 0;
uint32_t viewportHeight = 0;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,26 @@
#pragma once
#include <XCEngine/RHI/RHIEnums.h>
namespace XCEngine {
namespace RHI {
class RHICommandList;
class RHICommandQueue;
class RHIDevice;
} // namespace RHI
namespace Rendering {
struct RenderContext {
RHI::RHIDevice* device = nullptr;
RHI::RHICommandList* commandList = nullptr;
RHI::RHICommandQueue* commandQueue = nullptr;
RHI::RHIType backendType = RHI::RHIType::D3D12;
bool IsValid() const {
return device != nullptr && commandList != nullptr && commandQueue != nullptr;
}
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,24 @@
#pragma once
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderSceneExtractor.h>
namespace XCEngine {
namespace Rendering {
class RenderSurface;
class RenderPipeline {
public:
virtual ~RenderPipeline() = default;
virtual bool Initialize(const RenderContext& context) = 0;
virtual void Shutdown() = 0;
virtual bool Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) = 0;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,18 @@
#pragma once
#include <memory>
namespace XCEngine {
namespace Rendering {
class RenderPipeline;
class RenderPipelineAsset {
public:
virtual ~RenderPipelineAsset() = default;
virtual std::unique_ptr<RenderPipeline> CreatePipeline() const = 0;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,51 @@
#pragma once
#include <XCEngine/RHI/RHIBuffer.h>
#include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/Resources/Mesh/Mesh.h>
#include <XCEngine/Resources/Texture/Texture.h>
#include <unordered_map>
namespace XCEngine {
namespace Rendering {
class RenderResourceCache {
public:
struct CachedMesh {
RHI::RHIBuffer* vertexBuffer = nullptr;
RHI::RHIResourceView* vertexBufferView = nullptr;
RHI::RHIBuffer* indexBuffer = nullptr;
RHI::RHIResourceView* indexBufferView = nullptr;
uint32_t vertexCount = 0;
uint32_t indexCount = 0;
uint32_t vertexStride = 0;
bool uses32BitIndices = false;
};
struct CachedTexture {
RHI::RHITexture* texture = nullptr;
RHI::RHIResourceView* shaderResourceView = nullptr;
uint32_t width = 0;
uint32_t height = 0;
};
~RenderResourceCache();
void Shutdown();
const CachedMesh* GetOrCreateMesh(RHI::RHIDevice* device, const Resources::Mesh* mesh);
const CachedTexture* GetOrCreateTexture(RHI::RHIDevice* device, const Resources::Texture* texture);
private:
bool UploadMesh(RHI::RHIDevice* device, const Resources::Mesh* mesh, CachedMesh& cachedMesh);
bool UploadTexture(RHI::RHIDevice* device, const Resources::Texture* texture, CachedTexture& cachedTexture);
std::unordered_map<const Resources::Mesh*, CachedMesh> m_meshCache;
std::unordered_map<const Resources::Texture*, CachedTexture> m_textureCache;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,48 @@
#pragma once
#include <XCEngine/Rendering/RenderCameraData.h>
#include <XCEngine/Rendering/VisibleRenderObject.h>
#include <cstdint>
#include <vector>
namespace XCEngine {
namespace Components {
class CameraComponent;
class GameObject;
class Scene;
} // namespace Components
namespace Rendering {
struct RenderSceneData {
Components::CameraComponent* camera = nullptr;
RenderCameraData cameraData;
std::vector<VisibleRenderObject> visibleObjects;
bool HasCamera() const { return camera != nullptr; }
};
class RenderSceneExtractor {
public:
RenderSceneData Extract(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
uint32_t viewportWidth,
uint32_t viewportHeight) const;
private:
Components::CameraComponent* SelectCamera(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera) const;
RenderCameraData BuildCameraData(
const Components::CameraComponent& camera,
uint32_t viewportWidth,
uint32_t viewportHeight) const;
void ExtractVisibleObjects(
Components::GameObject* gameObject,
std::vector<VisibleRenderObject>& visibleObjects) const;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,59 @@
#pragma once
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/RHI/RHIEnums.h>
#include <cstdint>
#include <vector>
namespace XCEngine {
namespace RHI {
class RHIResourceView;
} // namespace RHI
namespace Rendering {
class RenderSurface {
public:
RenderSurface() = default;
RenderSurface(uint32_t width, uint32_t height);
uint32_t GetWidth() const { return m_width; }
uint32_t GetHeight() const { return m_height; }
void SetSize(uint32_t width, uint32_t height);
void SetColorAttachment(RHI::RHIResourceView* colorAttachment);
void SetColorAttachments(const std::vector<RHI::RHIResourceView*>& colorAttachments);
const std::vector<RHI::RHIResourceView*>& GetColorAttachments() const { return m_colorAttachments; }
void SetDepthAttachment(RHI::RHIResourceView* depthAttachment) { m_depthAttachment = depthAttachment; }
RHI::RHIResourceView* GetDepthAttachment() const { return m_depthAttachment; }
void SetClearColorOverride(const Math::Color& clearColor);
void ClearClearColorOverride();
bool HasClearColorOverride() const { return m_hasClearColorOverride; }
const Math::Color& GetClearColorOverride() const { return m_clearColorOverride; }
void SetAutoTransitionEnabled(bool enabled) { m_autoTransition = enabled; }
bool IsAutoTransitionEnabled() const { return m_autoTransition; }
void SetColorStateBefore(RHI::ResourceStates state) { m_colorStateBefore = state; }
RHI::ResourceStates GetColorStateBefore() const { return m_colorStateBefore; }
void SetColorStateAfter(RHI::ResourceStates state) { m_colorStateAfter = state; }
RHI::ResourceStates GetColorStateAfter() const { return m_colorStateAfter; }
private:
uint32_t m_width = 0;
uint32_t m_height = 0;
std::vector<RHI::RHIResourceView*> m_colorAttachments;
RHI::RHIResourceView* m_depthAttachment = nullptr;
bool m_hasClearColorOverride = false;
Math::Color m_clearColorOverride = Math::Color::Black();
bool m_autoTransition = true;
RHI::ResourceStates m_colorStateBefore = RHI::ResourceStates::Present;
RHI::ResourceStates m_colorStateAfter = RHI::ResourceStates::Present;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,36 @@
#pragma once
#include <XCEngine/Rendering/RenderPipeline.h>
#include <memory>
namespace XCEngine {
namespace Components {
class CameraComponent;
class Scene;
} // namespace Components
namespace Rendering {
class SceneRenderer {
public:
SceneRenderer();
explicit SceneRenderer(std::unique_ptr<RenderPipeline> pipeline);
~SceneRenderer();
void SetPipeline(std::unique_ptr<RenderPipeline> pipeline);
RenderPipeline* GetPipeline() const { return m_pipeline.get(); }
bool Render(
const Components::Scene& scene,
Components::CameraComponent* overrideCamera,
const RenderContext& context,
const RenderSurface& surface);
private:
RenderSceneExtractor m_sceneExtractor;
std::unique_ptr<RenderPipeline> m_pipeline;
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -0,0 +1,24 @@
#pragma once
#include <XCEngine/Core/Math/Matrix4.h>
#include <XCEngine/Resources/Mesh/Mesh.h>
namespace XCEngine {
namespace Components {
class GameObject;
class MeshFilterComponent;
class MeshRendererComponent;
} // namespace Components
namespace Rendering {
struct VisibleRenderObject {
Components::GameObject* gameObject = nullptr;
Components::MeshFilterComponent* meshFilter = nullptr;
Components::MeshRendererComponent* meshRenderer = nullptr;
Resources::Mesh* mesh = nullptr;
Math::Matrix4x4 localToWorld = Math::Matrix4x4::Identity();
};
} // namespace Rendering
} // namespace XCEngine