mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Vulcan Nightmare
Experimentally bringing up vulcan support
This commit is contained in:
parent
863a786c48
commit
83b576e8d9
189 changed files with 12147 additions and 7820 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
|
@ -19,12 +20,13 @@ namespace pipeline {
|
|||
namespace rendering {
|
||||
|
||||
class Camera;
|
||||
class Shader;
|
||||
class Frustum;
|
||||
class M2Renderer;
|
||||
class VkContext;
|
||||
class VkTexture;
|
||||
|
||||
/**
|
||||
* WMO (World Model Object) Renderer
|
||||
* WMO (World Model Object) Renderer (Vulkan)
|
||||
*
|
||||
* Renders buildings, dungeons, and large structures from WMO files.
|
||||
* Features:
|
||||
|
|
@ -32,7 +34,6 @@ class M2Renderer;
|
|||
* - Batched rendering per group
|
||||
* - Frustum culling
|
||||
* - Portal visibility (future)
|
||||
* - Dynamic lighting support (future)
|
||||
*/
|
||||
class WMORenderer {
|
||||
public:
|
||||
|
|
@ -40,10 +41,13 @@ public:
|
|||
~WMORenderer();
|
||||
|
||||
/**
|
||||
* Initialize renderer and create shaders
|
||||
* Initialize renderer (Vulkan)
|
||||
* @param ctx Vulkan context
|
||||
* @param perFrameLayout Descriptor set layout for set 0 (per-frame UBO)
|
||||
* @param assetManager Asset manager for loading textures (optional)
|
||||
*/
|
||||
bool initialize(pipeline::AssetManager* assetManager = nullptr);
|
||||
bool initialize(VkContext* ctx, VkDescriptorSetLayout perFrameLayout,
|
||||
pipeline::AssetManager* assetManager = nullptr);
|
||||
|
||||
/**
|
||||
* Cleanup GPU resources
|
||||
|
|
@ -132,12 +136,22 @@ public:
|
|||
void clearInstances();
|
||||
|
||||
/**
|
||||
* Render all WMO instances
|
||||
* @param camera Camera for view/projection matrices
|
||||
* @param view View matrix
|
||||
* @param projection Projection matrix
|
||||
* Render all WMO instances (Vulkan)
|
||||
* @param cmd Command buffer to record into
|
||||
* @param perFrameSet Per-frame descriptor set (set 0)
|
||||
* @param camera Camera for frustum culling
|
||||
*/
|
||||
void render(const Camera& camera, const glm::mat4& view, const glm::mat4& projection);
|
||||
void render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const Camera& camera);
|
||||
|
||||
/**
|
||||
* Initialize shadow pipeline (Phase 7)
|
||||
*/
|
||||
bool initializeShadow(VkRenderPass shadowRenderPass);
|
||||
|
||||
/**
|
||||
* Render depth-only for shadow casting
|
||||
*/
|
||||
void renderShadow(VkCommandBuffer cmd, const glm::mat4& lightSpaceMatrix);
|
||||
|
||||
/**
|
||||
* Get number of loaded models
|
||||
|
|
@ -204,32 +218,22 @@ public:
|
|||
uint32_t getDistanceCulledGroups() const { return lastDistanceCulledGroups; }
|
||||
|
||||
/**
|
||||
* Enable/disable GPU occlusion query culling
|
||||
* Enable/disable GPU occlusion query culling (stubbed in Vulkan)
|
||||
*/
|
||||
void setOcclusionCulling(bool enabled) { occlusionCulling = enabled; }
|
||||
bool isOcclusionCullingEnabled() const { return occlusionCulling; }
|
||||
void setOcclusionCulling(bool /*enabled*/) { /* stubbed */ }
|
||||
bool isOcclusionCullingEnabled() const { return false; }
|
||||
|
||||
/**
|
||||
* Get number of groups culled by occlusion queries last frame
|
||||
*/
|
||||
uint32_t getOcclusionCulledGroups() const { return lastOcclusionCulledGroups; }
|
||||
uint32_t getOcclusionCulledGroups() const { return 0; }
|
||||
|
||||
void setFog(const glm::vec3& color, float start, float end) {
|
||||
fogColor = color; fogStart = start; fogEnd = end;
|
||||
}
|
||||
|
||||
void setLighting(const float lightDir[3], const float lightColor[3],
|
||||
const float ambientColor[3]);
|
||||
|
||||
void setShadowMap(GLuint depthTex, const glm::mat4& lightSpace) {
|
||||
shadowDepthTex = depthTex; lightSpaceMatrix = lightSpace; shadowEnabled = true;
|
||||
}
|
||||
void clearShadowMap() { shadowEnabled = false; }
|
||||
|
||||
/**
|
||||
* Render depth-only for shadow casting (reuses VAOs)
|
||||
*/
|
||||
void renderShadow(const glm::mat4& lightView, const glm::mat4& lightProj, Shader& shadowShader);
|
||||
// Lighting/fog/shadow are now in the per-frame UBO; these are no-ops for API compat
|
||||
void setFog(const glm::vec3& /*color*/, float /*start*/, float /*end*/) {}
|
||||
void setLighting(const float /*lightDir*/[3], const float /*lightColor*/[3],
|
||||
const float /*ambientColor*/[3]) {}
|
||||
void setShadowMap(uint32_t /*depthTex*/, const glm::mat4& /*lightSpace*/) {}
|
||||
void clearShadowMap() {}
|
||||
|
||||
/**
|
||||
* Get floor height at a GL position via ray-triangle intersection.
|
||||
|
|
@ -297,13 +301,23 @@ public:
|
|||
void precomputeFloorCache();
|
||||
|
||||
private:
|
||||
// WMO material UBO — matches WMOMaterial in wmo.frag.glsl
|
||||
struct WMOMaterialUBO {
|
||||
int32_t hasTexture;
|
||||
int32_t alphaTest;
|
||||
int32_t unlit;
|
||||
int32_t isInterior;
|
||||
float specularIntensity;
|
||||
};
|
||||
|
||||
/**
|
||||
* WMO group GPU resources
|
||||
*/
|
||||
struct GroupResources {
|
||||
GLuint vao = 0;
|
||||
GLuint vbo = 0;
|
||||
GLuint ebo = 0;
|
||||
::VkBuffer vertexBuffer = VK_NULL_HANDLE;
|
||||
VmaAllocation vertexAlloc = VK_NULL_HANDLE;
|
||||
::VkBuffer indexBuffer = VK_NULL_HANDLE;
|
||||
VmaAllocation indexAlloc = VK_NULL_HANDLE;
|
||||
uint32_t indexCount = 0;
|
||||
uint32_t vertexCount = 0;
|
||||
glm::vec3 boundingBoxMin;
|
||||
|
|
@ -322,13 +336,17 @@ private:
|
|||
|
||||
// Pre-merged batches for efficient rendering (computed at load time)
|
||||
struct MergedBatch {
|
||||
GLuint texId;
|
||||
bool hasTexture;
|
||||
bool alphaTest;
|
||||
VkTexture* texture = nullptr; // from cache, NOT owned
|
||||
VkDescriptorSet materialSet = VK_NULL_HANDLE; // set 1
|
||||
::VkBuffer materialUBO = VK_NULL_HANDLE;
|
||||
VmaAllocation materialUBOAlloc = VK_NULL_HANDLE;
|
||||
bool hasTexture = false;
|
||||
bool alphaTest = false;
|
||||
bool unlit = false;
|
||||
uint32_t blendMode = 0;
|
||||
std::vector<GLsizei> counts;
|
||||
std::vector<const void*> offsets;
|
||||
bool isTransparent = false; // blendMode >= 2
|
||||
// For multi-draw: store index ranges
|
||||
struct DrawRange { uint32_t firstIndex; uint32_t indexCount; };
|
||||
std::vector<DrawRange> draws;
|
||||
};
|
||||
std::vector<MergedBatch> mergedBatches;
|
||||
|
||||
|
|
@ -401,7 +419,7 @@ private:
|
|||
std::vector<DoodadTemplate> doodadTemplates;
|
||||
|
||||
// Texture handles for this model (indexed by texture path order)
|
||||
std::vector<GLuint> textures;
|
||||
std::vector<VkTexture*> textures; // non-owning, from cache
|
||||
|
||||
// Material texture indices (materialId -> texture index)
|
||||
std::vector<uint32_t> materialTextureIndices;
|
||||
|
|
@ -458,13 +476,6 @@ private:
|
|||
*/
|
||||
bool createGroupResources(const pipeline::WMOGroup& group, GroupResources& resources, uint32_t groupFlags = 0);
|
||||
|
||||
/**
|
||||
* Render a single group
|
||||
*/
|
||||
void renderGroup(const GroupResources& group, const ModelData& model,
|
||||
const glm::mat4& modelMatrix,
|
||||
const glm::mat4& view, const glm::mat4& projection);
|
||||
|
||||
/**
|
||||
* Check if group is visible in frustum
|
||||
*/
|
||||
|
|
@ -479,11 +490,6 @@ private:
|
|||
|
||||
/**
|
||||
* Get visible groups via portal traversal
|
||||
* @param model The WMO model data
|
||||
* @param cameraLocalPos Camera position in model space
|
||||
* @param frustum Frustum for portal visibility testing
|
||||
* @param modelMatrix Transform for world-space frustum test
|
||||
* @param outVisibleGroups Output set of visible group indices
|
||||
*/
|
||||
void getVisibleGroupsViaPortals(const ModelData& model,
|
||||
const glm::vec3& cameraLocalPos,
|
||||
|
|
@ -502,23 +508,17 @@ private:
|
|||
/**
|
||||
* Load a texture from path
|
||||
*/
|
||||
GLuint loadTexture(const std::string& path);
|
||||
VkTexture* loadTexture(const std::string& path);
|
||||
|
||||
/**
|
||||
* Initialize occlusion query resources (bbox VAO, shader)
|
||||
* Allocate a material descriptor set from the pool
|
||||
*/
|
||||
void initOcclusionResources();
|
||||
VkDescriptorSet allocateMaterialSet();
|
||||
|
||||
/**
|
||||
* Run occlusion query pre-pass for an instance
|
||||
* Destroy GPU resources for a single group
|
||||
*/
|
||||
void runOcclusionQueries(const WMOInstance& instance, const ModelData& model,
|
||||
const glm::mat4& view, const glm::mat4& projection);
|
||||
|
||||
/**
|
||||
* Check if a group passed occlusion test (uses previous frame results)
|
||||
*/
|
||||
bool isGroupOccluded(uint32_t instanceId, uint32_t groupIndex) const;
|
||||
void destroyGroupGPU(GroupResources& group);
|
||||
|
||||
struct GridCell {
|
||||
int x;
|
||||
|
|
@ -541,8 +541,8 @@ private:
|
|||
void rebuildSpatialIndex();
|
||||
void gatherCandidates(const glm::vec3& queryMin, const glm::vec3& queryMax, std::vector<size_t>& outIndices) const;
|
||||
|
||||
// Shader
|
||||
std::unique_ptr<Shader> shader;
|
||||
// Vulkan context
|
||||
VkContext* vkCtx_ = nullptr;
|
||||
|
||||
// Asset manager for loading textures
|
||||
pipeline::AssetManager* assetManager = nullptr;
|
||||
|
|
@ -553,9 +553,31 @@ private:
|
|||
// Current map name for zone-specific floor cache
|
||||
std::string mapName_;
|
||||
|
||||
// Texture cache (path -> texture ID)
|
||||
// Vulkan pipelines
|
||||
VkPipeline opaquePipeline_ = VK_NULL_HANDLE;
|
||||
VkPipeline transparentPipeline_ = VK_NULL_HANDLE;
|
||||
VkPipeline wireframePipeline_ = VK_NULL_HANDLE;
|
||||
VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE;
|
||||
|
||||
// Shadow rendering (Phase 7)
|
||||
VkPipeline shadowPipeline_ = VK_NULL_HANDLE;
|
||||
VkPipelineLayout shadowPipelineLayout_ = VK_NULL_HANDLE;
|
||||
VkDescriptorSetLayout shadowParamsLayout_ = VK_NULL_HANDLE;
|
||||
VkDescriptorPool shadowParamsPool_ = VK_NULL_HANDLE;
|
||||
VkDescriptorSet shadowParamsSet_ = VK_NULL_HANDLE;
|
||||
::VkBuffer shadowParamsUBO_ = VK_NULL_HANDLE;
|
||||
VmaAllocation shadowParamsAlloc_ = VK_NULL_HANDLE;
|
||||
|
||||
// Descriptor set layouts
|
||||
VkDescriptorSetLayout materialSetLayout_ = VK_NULL_HANDLE;
|
||||
|
||||
// Descriptor pool for material sets
|
||||
VkDescriptorPool materialDescPool_ = VK_NULL_HANDLE;
|
||||
static constexpr uint32_t MAX_MATERIAL_SETS = 8192;
|
||||
|
||||
// Texture cache (path -> VkTexture)
|
||||
struct TextureCacheEntry {
|
||||
GLuint id = 0;
|
||||
std::unique_ptr<VkTexture> texture;
|
||||
size_t approxBytes = 0;
|
||||
uint64_t lastUse = 0;
|
||||
};
|
||||
|
|
@ -565,7 +587,7 @@ private:
|
|||
size_t textureCacheBudgetBytes_ = 2048ull * 1024 * 1024; // Default, overridden at init
|
||||
|
||||
// Default white texture
|
||||
GLuint whiteTexture = 0;
|
||||
std::unique_ptr<VkTexture> whiteTexture_;
|
||||
|
||||
// Loaded models (modelId -> ModelData)
|
||||
std::unordered_map<uint32_t, ModelData> loadedModels;
|
||||
|
|
@ -581,38 +603,11 @@ private:
|
|||
bool frustumCulling = true;
|
||||
bool portalCulling = false; // Disabled by default - needs debugging
|
||||
bool distanceCulling = false; // Disabled - causes ground to disappear
|
||||
bool occlusionCulling = false; // GPU occlusion queries - disabled, adds overhead
|
||||
float maxGroupDistance = 500.0f;
|
||||
float maxGroupDistanceSq = 250000.0f; // maxGroupDistance^2
|
||||
uint32_t lastDrawCalls = 0;
|
||||
mutable uint32_t lastPortalCulledGroups = 0;
|
||||
mutable uint32_t lastDistanceCulledGroups = 0;
|
||||
mutable uint32_t lastOcclusionCulledGroups = 0;
|
||||
|
||||
// Occlusion query resources
|
||||
GLuint bboxVao = 0;
|
||||
GLuint bboxVbo = 0;
|
||||
std::unique_ptr<Shader> occlusionShader;
|
||||
// Query objects per (instance, group) - reused each frame
|
||||
// Key: (instanceId << 16) | groupIndex
|
||||
mutable std::unordered_map<uint32_t, GLuint> occlusionQueries;
|
||||
// Results from previous frame (1 frame latency to avoid GPU stalls)
|
||||
mutable std::unordered_map<uint32_t, bool> occlusionResults;
|
||||
|
||||
// Fog parameters
|
||||
glm::vec3 fogColor = glm::vec3(0.5f, 0.6f, 0.7f);
|
||||
float fogStart = 3000.0f; // Increased to allow clearer visibility at distance
|
||||
float fogEnd = 4000.0f; // Increased to match extended view distance
|
||||
|
||||
// Lighting parameters
|
||||
float lightDir[3] = {-0.3f, -0.7f, -0.6f};
|
||||
float lightColor[3] = {1.5f, 1.4f, 1.3f};
|
||||
float ambientColor[3] = {0.55f, 0.55f, 0.6f};
|
||||
|
||||
// Shadow mapping
|
||||
GLuint shadowDepthTex = 0;
|
||||
glm::mat4 lightSpaceMatrix = glm::mat4(1.0f);
|
||||
bool shadowEnabled = false;
|
||||
|
||||
// Optional query-space culling for collision/raycast hot paths.
|
||||
bool collisionFocusEnabled = false;
|
||||
|
|
@ -636,7 +631,6 @@ private:
|
|||
std::vector<uint32_t> visibleGroups; // group indices that passed culling
|
||||
uint32_t portalCulled = 0;
|
||||
uint32_t distanceCulled = 0;
|
||||
uint32_t occlusionCulled = 0;
|
||||
};
|
||||
|
||||
// Collision query profiling (per frame).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue