MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
walk::RawWallRenderer Class Reference

Classes

struct  WallUniforms
struct  WallVertex

Public Member Functions

void cleanup (mxvk::VK_Window *targetWindow)
void cleanup (mxvk::VK_Window *targetWindow)
void load (mxvk::VK_Window *targetWindow, const std::string &textureManifestPath, const std::string &textureBasePath, const std::vector< char > &vertexShaderSpv, const std::vector< char > &fragmentShaderSpv)
void load (mxvk::VK_Window *targetWindow, const std::string &textureManifestPath, const std::string &textureBasePath, const std::vector< char > &vertexShaderSpv, const std::vector< char > &fragmentShaderSpv)
void reloadFragShader (const std::vector< char > &newFragSpv)
 Hot-swap the fragment shader without rebuilding geometry or descriptors.
void reloadFragShader (const std::vector< char > &newFragSpv)
 Hot-swap the fragment shader without rebuilding geometry or descriptors.
void render (VkCommandBuffer cmd, uint32_t imageIndex, const std::vector< WallSegment > &walls, float wallThickness, const glm::mat4 &view, const glm::mat4 &proj, const glm::vec4 &fx)
void render (VkCommandBuffer cmd, uint32_t imageIndex, const std::vector< WallSegment > &walls, float wallThickness, const glm::mat4 &view, const glm::mat4 &proj, const glm::vec4 &fx)
void resize (mxvk::VK_Window *targetWindow)
void resize (mxvk::VK_Window *targetWindow)

Detailed Description

Definition at line 1519 of file room.cpp.

Member Function Documentation

◆ cleanup() [1/2]

void walk::RawWallRenderer::cleanup ( mxvk::VK_Window * targetWindow)
inline

Definition at line 1586 of file room.cpp.

1586 {
1587 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
1588 return;
1589 }
1590
1591 window = targetWindow;
1592 destroyPipeline();
1593 destroyDescriptors();
1594 destroyTexture();
1595 destroyBuffers();
1596 window = nullptr;
1597 }
VkDevice getDevice() const noexcept
Get the Vulkan logical device handle.
Definition mxvk.hpp:168

◆ cleanup() [2/2]

void walk::RawWallRenderer::cleanup ( mxvk::VK_Window * targetWindow)
inline

Definition at line 1588 of file room.cpp.

1588 {
1589 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
1590 return;
1591 }
1592
1593 window = targetWindow;
1594 destroyPipeline();
1595 destroyDescriptors();
1596 destroyTexture();
1597 destroyBuffers();
1598 window = nullptr;
1599 }

◆ load() [1/2]

void walk::RawWallRenderer::load ( mxvk::VK_Window * targetWindow,
const std::string & textureManifestPath,
const std::string & textureBasePath,
const std::vector< char > & vertexShaderSpv,
const std::vector< char > & fragmentShaderSpv )
inline

Definition at line 1533 of file room.cpp.

1537 {
1538 if (targetWindow == nullptr) {
1539 throw mxvk::Exception("walk: raw wall renderer requires a valid window");
1540 }
1541 window = targetWindow;
1542 vertSpv = vertexShaderSpv;
1543 fragSpv = fragmentShaderSpv;
1544
1545 if (!window->ensureRenderResources()) {
1546 throw mxvk::Exception("walk: raw wall renderer requires render resources");
1547 }
1548
1549 buildGeometry();
1550 loadTexture(textureManifestPath, textureBasePath);
1551 createTextureSampler();
1552 createDescriptorSetLayout();
1553 createUniformBuffers();
1554 createDescriptorPool();
1555 createDescriptorSets();
1556 createPipeline();
1557 }

◆ load() [2/2]

void walk::RawWallRenderer::load ( mxvk::VK_Window * targetWindow,
const std::string & textureManifestPath,
const std::string & textureBasePath,
const std::vector< char > & vertexShaderSpv,
const std::vector< char > & fragmentShaderSpv )
inline

Definition at line 1535 of file room.cpp.

1539 {
1540 if (targetWindow == nullptr) {
1541 throw mxvk::Exception("walk: raw wall renderer requires a valid window");
1542 }
1543 window = targetWindow;
1544 vertSpv = vertexShaderSpv;
1545 fragSpv = fragmentShaderSpv;
1546
1547 if (!window->ensureRenderResources()) {
1548 throw mxvk::Exception("walk: raw wall renderer requires render resources");
1549 }
1550
1551 buildGeometry();
1552 loadTexture(textureManifestPath, textureBasePath);
1553 createTextureSampler();
1554 createDescriptorSetLayout();
1555 createUniformBuffers();
1556 createDescriptorPool();
1557 createDescriptorSets();
1558 createPipeline();
1559 }

◆ reloadFragShader() [1/2]

void walk::RawWallRenderer::reloadFragShader ( const std::vector< char > & newFragSpv)
inline

Hot-swap the fragment shader without rebuilding geometry or descriptors.

Parameters
newFragSpvCompiled SPIR-V bytecode for the new fragment shader.

Definition at line 1576 of file room.cpp.

1576 {
1577 if (window == nullptr || window->getDevice() == VK_NULL_HANDLE || newFragSpv.empty()) {
1578 return;
1579 }
1580 vkDeviceWaitIdle(window->getDevice());
1581 fragSpv = newFragSpv;
1582 destroyPipeline();
1583 createPipeline();
1584 }

◆ reloadFragShader() [2/2]

void walk::RawWallRenderer::reloadFragShader ( const std::vector< char > & newFragSpv)
inline

Hot-swap the fragment shader without rebuilding geometry or descriptors.

Parameters
newFragSpvCompiled SPIR-V bytecode for the new fragment shader.

Definition at line 1578 of file room.cpp.

1578 {
1579 if (window == nullptr || window->getDevice() == VK_NULL_HANDLE || newFragSpv.empty()) {
1580 return;
1581 }
1582 vkDeviceWaitIdle(window->getDevice());
1583 fragSpv = newFragSpv;
1584 destroyPipeline();
1585 createPipeline();
1586 }

◆ render() [1/2]

void walk::RawWallRenderer::render ( VkCommandBuffer cmd,
uint32_t imageIndex,
const std::vector< WallSegment > & walls,
float wallThickness,
const glm::mat4 & view,
const glm::mat4 & proj,
const glm::vec4 & fx )
inline

Definition at line 1599 of file room.cpp.

1605 {
1606 if (cmd == VK_NULL_HANDLE || pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
1607 return;
1608 }
1609 if (imageIndex >= uniformBuffersMapped.size() || descriptorSets.empty() || vertexBuffer == VK_NULL_HANDLE || indexBuffer == VK_NULL_HANDLE) {
1610 return;
1611 }
1612
1613 WallUniforms uniforms{};
1614 uniforms.view = view;
1615 uniforms.proj = proj;
1616 uniforms.fx = fx;
1617 std::memcpy(uniformBuffersMapped[imageIndex], &uniforms, sizeof(WallUniforms));
1618
1619 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1620 vkCmdBindDescriptorSets(cmd,
1621 VK_PIPELINE_BIND_POINT_GRAPHICS,
1622 pipelineLayout,
1623 0,
1624 1,
1625 &descriptorSets[imageIndex],
1626 0,
1627 nullptr);
1628
1629 const VkDeviceSize offset = 0;
1630 vkCmdBindVertexBuffers(cmd, 0, 1, &vertexBuffer, &offset);
1631 vkCmdBindIndexBuffer(cmd, indexBuffer, 0, VK_INDEX_TYPE_UINT32);
1632
1633 const float thickness = std::max(0.02f, wallThickness);
1634 // Extend each wall by about half its thickness on both ends so adjoining
1635 // runs meet cleanly without visible seam slivers.
1636 const float wallOverlap = thickness * 0.55f;
1637 for (const WallSegment &segment : walls) {
1638 const glm::vec3 center = (segment.start + segment.end) * 0.5f;
1639 const glm::vec3 span = segment.end - segment.start;
1640 const float length = glm::length(span);
1641 if (length < 0.0001f) {
1642 continue;
1643 }
1644 // Unit wall geometry has Y in [0..1]. Sink slightly to avoid floor/wall
1645 // depth fighting where the floor top plane is also at y=0.
1646 constexpr float baseSink = 0.01f;
1647 glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(center.x, -baseSink, center.z));
1648 model = glm::rotate(model, std::atan2(span.z, span.x), glm::vec3(0.0f, 1.0f, 0.0f));
1649 model = glm::scale(model, glm::vec3(length + wallOverlap * 2.0f, segment.height, thickness));
1650 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model);
1651 vkCmdDrawIndexed(cmd, indexCount, 1, 0, 0, 0);
1652 }
1653 }

◆ render() [2/2]

void walk::RawWallRenderer::render ( VkCommandBuffer cmd,
uint32_t imageIndex,
const std::vector< WallSegment > & walls,
float wallThickness,
const glm::mat4 & view,
const glm::mat4 & proj,
const glm::vec4 & fx )
inline

Definition at line 1601 of file room.cpp.

1607 {
1608 if (cmd == VK_NULL_HANDLE || pipeline == VK_NULL_HANDLE || pipelineLayout == VK_NULL_HANDLE) {
1609 return;
1610 }
1611 if (imageIndex >= uniformBuffersMapped.size() || descriptorSets.empty() || vertexBuffer == VK_NULL_HANDLE || indexBuffer == VK_NULL_HANDLE) {
1612 return;
1613 }
1614
1615 WallUniforms uniforms{};
1616 uniforms.view = view;
1617 uniforms.proj = proj;
1618 uniforms.fx = fx;
1619 std::memcpy(uniformBuffersMapped[imageIndex], &uniforms, sizeof(WallUniforms));
1620
1621 vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1622 vkCmdBindDescriptorSets(cmd,
1623 VK_PIPELINE_BIND_POINT_GRAPHICS,
1624 pipelineLayout,
1625 0,
1626 1,
1627 &descriptorSets[imageIndex],
1628 0,
1629 nullptr);
1630
1631 const VkDeviceSize offset = 0;
1632 vkCmdBindVertexBuffers(cmd, 0, 1, &vertexBuffer, &offset);
1633 vkCmdBindIndexBuffer(cmd, indexBuffer, 0, VK_INDEX_TYPE_UINT32);
1634
1635 const float thickness = std::max(0.02f, wallThickness);
1636 // Extend each wall by about half its thickness on both ends so adjoining
1637 // runs meet cleanly without visible seam slivers.
1638 const float wallOverlap = thickness * 0.55f;
1639 for (const WallSegment &segment : walls) {
1640 const glm::vec3 center = (segment.start + segment.end) * 0.5f;
1641 const glm::vec3 span = segment.end - segment.start;
1642 const float length = glm::length(span);
1643 if (length < 0.0001f) {
1644 continue;
1645 }
1646 // Unit wall geometry has Y in [0..1]. Sink slightly to avoid floor/wall
1647 // depth fighting where the floor top plane is also at y=0.
1648 constexpr float baseSink = 0.01f;
1649 glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(center.x, -baseSink, center.z));
1650 model = glm::rotate(model, std::atan2(span.z, span.x), glm::vec3(0.0f, 1.0f, 0.0f));
1651 model = glm::scale(model, glm::vec3(length + wallOverlap * 2.0f, segment.height, thickness));
1652 vkCmdPushConstants(cmd, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model);
1653 vkCmdDrawIndexed(cmd, indexCount, 1, 0, 0, 0);
1654 }
1655 }

◆ resize() [1/2]

void walk::RawWallRenderer::resize ( mxvk::VK_Window * targetWindow)
inline

Definition at line 1559 of file room.cpp.

1559 {
1560 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
1561 return;
1562 }
1563
1564 window = targetWindow;
1565 destroyPipeline();
1566 destroyDescriptors();
1567 createDescriptorSetLayout();
1568 createUniformBuffers();
1569 createDescriptorPool();
1570 createDescriptorSets();
1571 createPipeline();
1572 }

◆ resize() [2/2]

void walk::RawWallRenderer::resize ( mxvk::VK_Window * targetWindow)
inline

Definition at line 1561 of file room.cpp.

1561 {
1562 if (targetWindow == nullptr || targetWindow->getDevice() == VK_NULL_HANDLE) {
1563 return;
1564 }
1565
1566 window = targetWindow;
1567 destroyPipeline();
1568 destroyDescriptors();
1569 createDescriptorSetLayout();
1570 createUniformBuffers();
1571 createDescriptorPool();
1572 createDescriptorSets();
1573 createPipeline();
1574 }

The documentation for this class was generated from the following files: