mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-24 08:00:14 +00:00
- MSAA: conditional 2-att (off) vs 3-att (on) render pass with auto-resolve - MSAA: multisampled color+depth images, query max supported sample count - MSAA: .setMultisample() on all 25+ main-pass pipelines across 17 renderers - MSAA: recreatePipelines() on every sub-renderer for runtime MSAA changes - MSAA: Renderer::setMsaaSamples() orchestrates swapchain+pipeline+ImGui rebuild - MSAA: Anti-Aliasing combo (Off/2x/4x/8x) in Video settings, persisted - Update auth screen assets and terrain fragment shader
495 lines
17 KiB
C++
495 lines
17 KiB
C++
#include "rendering/celestial.hpp"
|
||
#include "rendering/vk_context.hpp"
|
||
#include "rendering/vk_shader.hpp"
|
||
#include "rendering/vk_pipeline.hpp"
|
||
#include "rendering/vk_frame_data.hpp"
|
||
#include "rendering/vk_utils.hpp"
|
||
#include "core/logger.hpp"
|
||
#include <glm/gtc/matrix_transform.hpp>
|
||
#include <cmath>
|
||
#include <vector>
|
||
|
||
namespace wowee {
|
||
namespace rendering {
|
||
|
||
Celestial::Celestial() = default;
|
||
|
||
Celestial::~Celestial() {
|
||
shutdown();
|
||
}
|
||
|
||
bool Celestial::initialize(VkContext* ctx, VkDescriptorSetLayout perFrameLayout) {
|
||
LOG_INFO("Initializing celestial renderer (Vulkan)");
|
||
|
||
vkCtx_ = ctx;
|
||
VkDevice device = vkCtx_->getDevice();
|
||
|
||
// ------------------------------------------------------------------ shaders
|
||
VkShaderModule vertModule;
|
||
if (!vertModule.loadFromFile(device, "assets/shaders/celestial.vert.spv")) {
|
||
LOG_ERROR("Failed to load celestial vertex shader");
|
||
return false;
|
||
}
|
||
|
||
VkShaderModule fragModule;
|
||
if (!fragModule.loadFromFile(device, "assets/shaders/celestial.frag.spv")) {
|
||
LOG_ERROR("Failed to load celestial fragment shader");
|
||
return false;
|
||
}
|
||
|
||
VkPipelineShaderStageCreateInfo vertStage = vertModule.stageInfo(VK_SHADER_STAGE_VERTEX_BIT);
|
||
VkPipelineShaderStageCreateInfo fragStage = fragModule.stageInfo(VK_SHADER_STAGE_FRAGMENT_BIT);
|
||
|
||
// ------------------------------------------------------------------ push constants
|
||
// Layout: mat4(64) + vec4(16) + float*3(12) + pad(4) = 96 bytes
|
||
VkPushConstantRange pushRange{};
|
||
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||
pushRange.offset = 0;
|
||
pushRange.size = sizeof(CelestialPush); // 96 bytes
|
||
|
||
// ------------------------------------------------------------------ pipeline layout
|
||
pipelineLayout_ = createPipelineLayout(device, {perFrameLayout}, {pushRange});
|
||
if (pipelineLayout_ == VK_NULL_HANDLE) {
|
||
LOG_ERROR("Failed to create celestial pipeline layout");
|
||
return false;
|
||
}
|
||
|
||
// ------------------------------------------------------------------ vertex input
|
||
// Vertex: vec3 pos + vec2 texCoord, stride = 20 bytes
|
||
VkVertexInputBindingDescription binding{};
|
||
binding.binding = 0;
|
||
binding.stride = 5 * sizeof(float); // 20 bytes
|
||
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||
|
||
VkVertexInputAttributeDescription posAttr{};
|
||
posAttr.location = 0;
|
||
posAttr.binding = 0;
|
||
posAttr.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||
posAttr.offset = 0;
|
||
|
||
VkVertexInputAttributeDescription uvAttr{};
|
||
uvAttr.location = 1;
|
||
uvAttr.binding = 0;
|
||
uvAttr.format = VK_FORMAT_R32G32_SFLOAT;
|
||
uvAttr.offset = 3 * sizeof(float);
|
||
|
||
std::vector<VkDynamicState> dynamicStates = {
|
||
VK_DYNAMIC_STATE_VIEWPORT,
|
||
VK_DYNAMIC_STATE_SCISSOR
|
||
};
|
||
|
||
// ------------------------------------------------------------------ pipeline
|
||
pipeline_ = PipelineBuilder()
|
||
.setShaders(vertStage, fragStage)
|
||
.setVertexInput({binding}, {posAttr, uvAttr})
|
||
.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||
.setRasterization(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE)
|
||
.setDepthTest(true, false, VK_COMPARE_OP_LESS_OR_EQUAL) // test on, write off (sky layer)
|
||
.setColorBlendAttachment(PipelineBuilder::blendAlpha())
|
||
.setMultisample(vkCtx_->getMsaaSamples())
|
||
.setLayout(pipelineLayout_)
|
||
.setRenderPass(vkCtx_->getImGuiRenderPass())
|
||
.setDynamicStates(dynamicStates)
|
||
.build(device);
|
||
|
||
vertModule.destroy();
|
||
fragModule.destroy();
|
||
|
||
if (pipeline_ == VK_NULL_HANDLE) {
|
||
LOG_ERROR("Failed to create celestial pipeline");
|
||
return false;
|
||
}
|
||
|
||
// ------------------------------------------------------------------ geometry
|
||
createQuad();
|
||
|
||
LOG_INFO("Celestial renderer initialized");
|
||
return true;
|
||
}
|
||
|
||
void Celestial::recreatePipelines() {
|
||
if (!vkCtx_) return;
|
||
VkDevice device = vkCtx_->getDevice();
|
||
|
||
if (pipeline_ != VK_NULL_HANDLE) { vkDestroyPipeline(device, pipeline_, nullptr); pipeline_ = VK_NULL_HANDLE; }
|
||
|
||
VkShaderModule vertModule;
|
||
if (!vertModule.loadFromFile(device, "assets/shaders/celestial.vert.spv")) {
|
||
LOG_ERROR("Celestial::recreatePipelines: failed to load vertex shader");
|
||
return;
|
||
}
|
||
VkShaderModule fragModule;
|
||
if (!fragModule.loadFromFile(device, "assets/shaders/celestial.frag.spv")) {
|
||
LOG_ERROR("Celestial::recreatePipelines: failed to load fragment shader");
|
||
vertModule.destroy();
|
||
return;
|
||
}
|
||
|
||
VkPipelineShaderStageCreateInfo vertStage = vertModule.stageInfo(VK_SHADER_STAGE_VERTEX_BIT);
|
||
VkPipelineShaderStageCreateInfo fragStage = fragModule.stageInfo(VK_SHADER_STAGE_FRAGMENT_BIT);
|
||
|
||
// Vertex input (same as initialize)
|
||
VkVertexInputBindingDescription binding{};
|
||
binding.binding = 0;
|
||
binding.stride = 5 * sizeof(float);
|
||
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
||
|
||
VkVertexInputAttributeDescription posAttr{};
|
||
posAttr.location = 0;
|
||
posAttr.binding = 0;
|
||
posAttr.format = VK_FORMAT_R32G32B32_SFLOAT;
|
||
posAttr.offset = 0;
|
||
|
||
VkVertexInputAttributeDescription uvAttr{};
|
||
uvAttr.location = 1;
|
||
uvAttr.binding = 0;
|
||
uvAttr.format = VK_FORMAT_R32G32_SFLOAT;
|
||
uvAttr.offset = 3 * sizeof(float);
|
||
|
||
std::vector<VkDynamicState> dynamicStates = {
|
||
VK_DYNAMIC_STATE_VIEWPORT,
|
||
VK_DYNAMIC_STATE_SCISSOR
|
||
};
|
||
|
||
pipeline_ = PipelineBuilder()
|
||
.setShaders(vertStage, fragStage)
|
||
.setVertexInput({binding}, {posAttr, uvAttr})
|
||
.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||
.setRasterization(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE)
|
||
.setDepthTest(true, false, VK_COMPARE_OP_LESS_OR_EQUAL)
|
||
.setColorBlendAttachment(PipelineBuilder::blendAlpha())
|
||
.setMultisample(vkCtx_->getMsaaSamples())
|
||
.setLayout(pipelineLayout_)
|
||
.setRenderPass(vkCtx_->getImGuiRenderPass())
|
||
.setDynamicStates(dynamicStates)
|
||
.build(device);
|
||
|
||
vertModule.destroy();
|
||
fragModule.destroy();
|
||
|
||
if (pipeline_ == VK_NULL_HANDLE) {
|
||
LOG_ERROR("Celestial::recreatePipelines: failed to create pipeline");
|
||
}
|
||
}
|
||
|
||
void Celestial::shutdown() {
|
||
destroyQuad();
|
||
|
||
if (vkCtx_) {
|
||
VkDevice device = vkCtx_->getDevice();
|
||
if (pipeline_ != VK_NULL_HANDLE) {
|
||
vkDestroyPipeline(device, pipeline_, nullptr);
|
||
pipeline_ = VK_NULL_HANDLE;
|
||
}
|
||
if (pipelineLayout_ != VK_NULL_HANDLE) {
|
||
vkDestroyPipelineLayout(device, pipelineLayout_, nullptr);
|
||
pipelineLayout_ = VK_NULL_HANDLE;
|
||
}
|
||
}
|
||
|
||
vkCtx_ = nullptr;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Public render entry point
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void Celestial::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet,
|
||
float timeOfDay,
|
||
const glm::vec3* sunDir, const glm::vec3* sunColor,
|
||
float gameTime) {
|
||
if (!renderingEnabled_ || pipeline_ == VK_NULL_HANDLE) {
|
||
return;
|
||
}
|
||
|
||
// Update moon phases from server game time if provided
|
||
if (gameTime >= 0.0f) {
|
||
updatePhasesFromGameTime(gameTime);
|
||
}
|
||
|
||
// Bind pipeline and per-frame descriptor set once — reused for all draws
|
||
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
||
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_,
|
||
0, 1, &perFrameSet, 0, nullptr);
|
||
|
||
// Bind the shared quad buffers
|
||
VkDeviceSize offset = 0;
|
||
vkCmdBindVertexBuffers(cmd, 0, 1, &vertexBuffer_, &offset);
|
||
vkCmdBindIndexBuffer(cmd, indexBuffer_, 0, VK_INDEX_TYPE_UINT32);
|
||
|
||
// Draw sun, then moon(s) — each call pushes different constants
|
||
renderSun(cmd, perFrameSet, timeOfDay, sunDir, sunColor);
|
||
renderMoon(cmd, perFrameSet, timeOfDay);
|
||
if (dualMoonMode_) {
|
||
renderBlueChild(cmd, perFrameSet, timeOfDay);
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Private per-body render helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void Celestial::renderSun(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
||
float timeOfDay,
|
||
const glm::vec3* sunDir, const glm::vec3* sunColor) {
|
||
// Sun visible 5:00–19:00
|
||
if (timeOfDay < 5.0f || timeOfDay >= 19.0f) {
|
||
return;
|
||
}
|
||
|
||
// Resolve sun direction — prefer opposite of incoming light ray, clamp below horizon
|
||
glm::vec3 lightDir = sunDir ? glm::normalize(*sunDir) : glm::vec3(0.0f, 0.0f, -1.0f);
|
||
glm::vec3 dir = -lightDir;
|
||
if (dir.z < 0.0f) {
|
||
dir = lightDir;
|
||
}
|
||
|
||
const float sunDistance = 800.0f;
|
||
glm::vec3 sunPos = dir * sunDistance;
|
||
|
||
glm::mat4 model = glm::mat4(1.0f);
|
||
model = glm::translate(model, sunPos);
|
||
model = glm::scale(model, glm::vec3(95.0f, 95.0f, 1.0f));
|
||
|
||
glm::vec3 color = sunColor ? *sunColor : getSunColor(timeOfDay);
|
||
const glm::vec3 warmSun(1.0f, 0.88f, 0.55f);
|
||
color = glm::mix(color, warmSun, 0.52f);
|
||
float intensity = getSunIntensity(timeOfDay) * 0.92f;
|
||
|
||
CelestialPush push{};
|
||
push.model = model;
|
||
push.celestialColor = glm::vec4(color, 1.0f);
|
||
push.intensity = intensity;
|
||
push.moonPhase = 0.5f; // unused for sun
|
||
push.animTime = sunHazeTimer_;
|
||
|
||
vkCmdPushConstants(cmd, pipelineLayout_,
|
||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||
0, sizeof(push), &push);
|
||
|
||
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
||
}
|
||
|
||
void Celestial::renderMoon(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
||
float timeOfDay) {
|
||
// Moon (White Lady) visible 19:00–5:00
|
||
if (timeOfDay >= 5.0f && timeOfDay < 19.0f) {
|
||
return;
|
||
}
|
||
|
||
glm::vec3 moonPos = getMoonPosition(timeOfDay);
|
||
|
||
glm::mat4 model = glm::mat4(1.0f);
|
||
model = glm::translate(model, moonPos);
|
||
model = glm::scale(model, glm::vec3(40.0f, 40.0f, 1.0f));
|
||
|
||
glm::vec3 color = glm::vec3(0.8f, 0.85f, 1.0f);
|
||
|
||
float intensity = 1.0f;
|
||
if (timeOfDay >= 19.0f && timeOfDay < 21.0f) {
|
||
intensity = (timeOfDay - 19.0f) / 2.0f; // Fade in
|
||
} else if (timeOfDay >= 3.0f && timeOfDay < 5.0f) {
|
||
intensity = 1.0f - (timeOfDay - 3.0f) / 2.0f; // Fade out
|
||
}
|
||
|
||
CelestialPush push{};
|
||
push.model = model;
|
||
push.celestialColor = glm::vec4(color, 1.0f);
|
||
push.intensity = intensity;
|
||
push.moonPhase = whiteLadyPhase_;
|
||
push.animTime = sunHazeTimer_;
|
||
|
||
vkCmdPushConstants(cmd, pipelineLayout_,
|
||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||
0, sizeof(push), &push);
|
||
|
||
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
||
}
|
||
|
||
void Celestial::renderBlueChild(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
||
float timeOfDay) {
|
||
// Blue Child visible 19:00–5:00
|
||
if (timeOfDay >= 5.0f && timeOfDay < 19.0f) {
|
||
return;
|
||
}
|
||
|
||
// Offset slightly from White Lady
|
||
glm::vec3 moonPos = getMoonPosition(timeOfDay);
|
||
moonPos.x += 80.0f;
|
||
moonPos.z -= 40.0f;
|
||
|
||
glm::mat4 model = glm::mat4(1.0f);
|
||
model = glm::translate(model, moonPos);
|
||
model = glm::scale(model, glm::vec3(30.0f, 30.0f, 1.0f));
|
||
|
||
glm::vec3 color = glm::vec3(0.7f, 0.8f, 1.0f);
|
||
|
||
float intensity = 1.0f;
|
||
if (timeOfDay >= 19.0f && timeOfDay < 21.0f) {
|
||
intensity = (timeOfDay - 19.0f) / 2.0f;
|
||
} else if (timeOfDay >= 3.0f && timeOfDay < 5.0f) {
|
||
intensity = 1.0f - (timeOfDay - 3.0f) / 2.0f;
|
||
}
|
||
intensity *= 0.7f; // Blue Child is dimmer
|
||
|
||
CelestialPush push{};
|
||
push.model = model;
|
||
push.celestialColor = glm::vec4(color, 1.0f);
|
||
push.intensity = intensity;
|
||
push.moonPhase = blueChildPhase_;
|
||
push.animTime = sunHazeTimer_;
|
||
|
||
vkCmdPushConstants(cmd, pipelineLayout_,
|
||
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
||
0, sizeof(push), &push);
|
||
|
||
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Position / colour query helpers (identical logic to GL version)
|
||
// ---------------------------------------------------------------------------
|
||
|
||
glm::vec3 Celestial::getSunPosition(float timeOfDay) const {
|
||
float angle = calculateCelestialAngle(timeOfDay, 6.0f, 18.0f);
|
||
const float radius = 800.0f;
|
||
const float height = 600.0f;
|
||
float x = radius * std::cos(angle);
|
||
float z = height * std::sin(angle);
|
||
return glm::vec3(x, 0.0f, z);
|
||
}
|
||
|
||
glm::vec3 Celestial::getMoonPosition(float timeOfDay) const {
|
||
float moonTime = timeOfDay + 12.0f;
|
||
if (moonTime >= 24.0f) moonTime -= 24.0f;
|
||
float angle = calculateCelestialAngle(moonTime, 6.0f, 18.0f);
|
||
const float radius = 800.0f;
|
||
const float height = 600.0f;
|
||
float x = radius * std::cos(angle);
|
||
float z = height * std::sin(angle);
|
||
return glm::vec3(x, 0.0f, z);
|
||
}
|
||
|
||
glm::vec3 Celestial::getSunColor(float timeOfDay) const {
|
||
if (timeOfDay >= 5.0f && timeOfDay < 7.0f) {
|
||
return glm::vec3(1.0f, 0.6f, 0.2f); // Sunrise orange
|
||
} else if (timeOfDay >= 7.0f && timeOfDay < 9.0f) {
|
||
float t = (timeOfDay - 7.0f) / 2.0f;
|
||
return glm::mix(glm::vec3(1.0f, 0.6f, 0.2f), glm::vec3(1.0f, 1.0f, 0.9f), t);
|
||
} else if (timeOfDay >= 9.0f && timeOfDay < 16.0f) {
|
||
return glm::vec3(1.0f, 1.0f, 0.9f); // Day yellow-white
|
||
} else if (timeOfDay >= 16.0f && timeOfDay < 18.0f) {
|
||
float t = (timeOfDay - 16.0f) / 2.0f;
|
||
return glm::mix(glm::vec3(1.0f, 1.0f, 0.9f), glm::vec3(1.0f, 0.5f, 0.1f), t);
|
||
} else {
|
||
return glm::vec3(1.0f, 0.4f, 0.1f); // Sunset orange
|
||
}
|
||
}
|
||
|
||
float Celestial::getSunIntensity(float timeOfDay) const {
|
||
if (timeOfDay >= 5.0f && timeOfDay < 6.0f) {
|
||
return timeOfDay - 5.0f; // Fade in
|
||
} else if (timeOfDay >= 6.0f && timeOfDay < 18.0f) {
|
||
return 1.0f; // Full day
|
||
} else if (timeOfDay >= 18.0f && timeOfDay < 19.0f) {
|
||
return 1.0f - (timeOfDay - 18.0f); // Fade out
|
||
} else {
|
||
return 0.0f;
|
||
}
|
||
}
|
||
|
||
float Celestial::calculateCelestialAngle(float timeOfDay, float riseTime, float setTime) const {
|
||
float duration = setTime - riseTime;
|
||
float elapsed = timeOfDay - riseTime;
|
||
float t = elapsed / duration;
|
||
return t * static_cast<float>(M_PI);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Moon phase helpers
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void Celestial::update(float deltaTime) {
|
||
sunHazeTimer_ += deltaTime;
|
||
|
||
if (!moonPhaseCycling_) {
|
||
return;
|
||
}
|
||
|
||
moonPhaseTimer_ += deltaTime;
|
||
whiteLadyPhase_ = std::fmod(moonPhaseTimer_ / MOON_CYCLE_DURATION, 1.0f);
|
||
|
||
constexpr float BLUE_CHILD_CYCLE = 210.0f; // Slightly faster: 3.5 minutes
|
||
blueChildPhase_ = std::fmod(moonPhaseTimer_ / BLUE_CHILD_CYCLE, 1.0f);
|
||
}
|
||
|
||
void Celestial::setMoonPhase(float phase) {
|
||
whiteLadyPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
||
moonPhaseTimer_ = whiteLadyPhase_ * MOON_CYCLE_DURATION;
|
||
}
|
||
|
||
void Celestial::setBlueChildPhase(float phase) {
|
||
blueChildPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
||
}
|
||
|
||
float Celestial::computePhaseFromGameTime(float gameTime, float cycleDays) const {
|
||
constexpr float SECONDS_PER_GAME_DAY = 1440.0f; // 24 real minutes
|
||
float gameDays = gameTime / SECONDS_PER_GAME_DAY;
|
||
float phase = std::fmod(gameDays / cycleDays, 1.0f);
|
||
if (phase < 0.0f) phase += 1.0f;
|
||
return phase;
|
||
}
|
||
|
||
void Celestial::updatePhasesFromGameTime(float gameTime) {
|
||
whiteLadyPhase_ = computePhaseFromGameTime(gameTime, WHITE_LADY_CYCLE_DAYS);
|
||
blueChildPhase_ = computePhaseFromGameTime(gameTime, BLUE_CHILD_CYCLE_DAYS);
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// GPU buffer management
|
||
// ---------------------------------------------------------------------------
|
||
|
||
void Celestial::createQuad() {
|
||
// Billboard quad centred at origin, vertices: pos(vec3) + uv(vec2)
|
||
float vertices[] = {
|
||
// Position TexCoord
|
||
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // Top-left
|
||
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // Top-right
|
||
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // Bottom-right
|
||
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // Bottom-left
|
||
};
|
||
|
||
uint32_t indices[] = { 0, 1, 2, 0, 2, 3 };
|
||
|
||
AllocatedBuffer vbuf = uploadBuffer(*vkCtx_,
|
||
vertices, sizeof(vertices),
|
||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||
vertexBuffer_ = vbuf.buffer;
|
||
vertexAlloc_ = vbuf.allocation;
|
||
|
||
AllocatedBuffer ibuf = uploadBuffer(*vkCtx_,
|
||
indices, sizeof(indices),
|
||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||
indexBuffer_ = ibuf.buffer;
|
||
indexAlloc_ = ibuf.allocation;
|
||
}
|
||
|
||
void Celestial::destroyQuad() {
|
||
if (!vkCtx_) return;
|
||
|
||
VmaAllocator allocator = vkCtx_->getAllocator();
|
||
|
||
if (vertexBuffer_ != VK_NULL_HANDLE) {
|
||
vmaDestroyBuffer(allocator, vertexBuffer_, vertexAlloc_);
|
||
vertexBuffer_ = VK_NULL_HANDLE;
|
||
vertexAlloc_ = VK_NULL_HANDLE;
|
||
}
|
||
if (indexBuffer_ != VK_NULL_HANDLE) {
|
||
vmaDestroyBuffer(allocator, indexBuffer_, indexAlloc_);
|
||
indexBuffer_ = VK_NULL_HANDLE;
|
||
indexAlloc_ = VK_NULL_HANDLE;
|
||
}
|
||
}
|
||
|
||
} // namespace rendering
|
||
} // namespace wowee
|