Skip to content
Snippets Groups Projects
Commit aca45eac authored by Christian Mattes's avatar Christian Mattes
Browse files

Added BatchingRenderer

parent 217c99ca
No related branches found
No related tags found
No related merge requests found
......@@ -10,4 +10,4 @@ add_library(lava-vr ${LAVA_LINK_TYPE}
)
target_include_directories(lava-vr PUBLIC ./src)
target_link_libraries(lava-vr PUBLIC lava lava-extras-openvr lava-extras-pipeline)
target_link_libraries(lava-vr PUBLIC lava lava-extras-openvr lava-extras-pipeline lava-extras-geometry)
......@@ -7,3 +7,7 @@ Higher-level utility classes and functions for VR-Applications based on lava and
## RopeLocomotion
Use two controllers to move around in the scene in a multi-touch / "Mime pulling an invisible rope" fashion.
## BatchingRenderer
Manages an arbitrary amount of meshes with texture and records drawing requests that can be executed at once with a single bind of pipeline and buffers.
#include "BatchingRenderer.hh"
#include <glm/glm.hpp>
#include <lava-extras/pack/pack.hh>
#include <lava/common/log.hh>
#include <lava/createinfos/Buffers.hh>
#include <lava/createinfos/DescriptorSetLayoutCreateInfo.hh>
#include <lava/createinfos/GraphicsPipelineCreateInfo.hh>
#include <lava/createinfos/Images.hh>
#include <lava/createinfos/Sampler.hh>
#include <lava/features/DebugMarkers.hh>
#include <lava/objects/Buffer.hh>
#include <lava/objects/DescriptorSet.hh>
#include <lava/objects/DescriptorSetLayout.hh>
#include <lava/objects/Device.hh>
#include <lava/objects/GraphicsPipeline.hh>
#include <lava/objects/Image.hh>
#include <lava/objects/ImageData.hh>
#include <lava/objects/RenderPass.hh>
#include <lava/raii/ActiveRenderPass.hh>
#include <lava-extras/geometry/IO.hh>
namespace lava {
namespace vr {
BatchingRenderer::BatchingRenderer(
const lava::Subpass &forwardPass,
const lava::SharedDescriptorSetLayout &cameraLayout) {
auto device = forwardPass.pass->device();
mMaterialLayout = lava::DescriptorSetLayoutCreateInfo() //
.addCombinedImageSampler()
.create(device, 100);
auto layout = device->createPipelineLayout<glm::mat4>(
{cameraLayout, mMaterialLayout});
auto ci = lava::GraphicsPipelineCreateInfo::defaults();
ci.setLayout(layout);
ci.depthStencilState.setDepthTestEnable(true).setDepthWriteEnable(true);
ci.rasterizationState.setFrontFace(vk::FrontFace::eClockwise);
ci.addStage(lava::pack::shader(device, "albedo.vert"));
ci.addStage(lava::pack::shader(device, "albedo.frag"));
ci.vertexInputState.addAttribute(&Vertex::pos, 0);
ci.vertexInputState.addAttribute(&Vertex::normal, 1);
ci.vertexInputState.addAttribute(&Vertex::texCoord, 2);
mPipeline = forwardPass.createPipeline(ci);
mSampler = device->createSampler({});
}
BatchingRenderer::MeshHandle BatchingRenderer::add(const std::string &modelfile,
const std::string &texture) {
MeshHandle result;
auto debug = mPipeline->device()->get<lava::features::DebugMarkers>();
{
std::vector<Vertex> vertices;
auto indices = lava::geometry::Importer().load(
modelfile,
[&](glm::vec3 position, glm::vec3 normal, glm::vec3 /* tangent */,
glm::vec3 texcoord, glm::vec4 /* color */) {
vertices.push_back({position, normal, glm::vec2(texcoord)});
});
uint32_t firstIndex = mIndices.size();
uint32_t offset = mVertices.size();
mVertices.insert(mVertices.end(), vertices.begin(), vertices.end());
std::transform(indices.begin(), indices.end(), back_inserter(mIndices),
[&](uint32_t idx) { return idx + offset; });
result.firstIndex = firstIndex;
result.count = indices.size();
}
{
auto image = lava::ImageData::createFromFile(texture)->uploadTo(
mPipeline->device());
image->changeLayout(vk::ImageLayout::eTransferSrcOptimal,
vk::ImageLayout::eShaderReadOnlyOptimal);
if (debug)
debug->mark(image, "BatchingRenderer - " + texture);
auto view = image->createView(vk::ImageViewType::e2D);
auto set = mMaterialLayout->createDescriptorSet();
set->write().combinedImageSampler(mSampler, view);
mMaterials.push_back(set);
result.material = mMaterials.size() - 1;
}
return result;
}
void BatchingRenderer::upload() {
auto const &device = mPipeline->device();
mVertexBuffer = device->createBuffer(lava::arrayBuffer());
mVertexBuffer->setDataVRAM(mVertices);
mIndexBuffer = device->createBuffer(lava::indexBuffer());
mIndexBuffer->setDataVRAM(mIndices);
}
void BatchingRenderer::draw(lava::InlineSubpass &sub,
lava::SharedDescriptorSet const &cameraSet) {
sub.bindPipeline(mPipeline);
sub.bindVertexBuffers({mVertexBuffer});
sub.bindIndexBuffer(mIndexBuffer);
sub.bindDescriptorSets({cameraSet});
for (auto const &d : mDraws) {
sub.bindDescriptorSets({mMaterials[d.first.material]}, 1);
sub.pushConstantBlock(d.second);
sub.drawIndexed(d.first.count, 1, 0, d.first.firstIndex);
}
}
} // namespace vr
} // namespace lava
#pragma once
#include <glm/common.hpp>
#include <glm/mat4x4.hpp>
#include <lava/fwd.hh>
#include <vector>
namespace lava {
namespace vr {
class BatchingRenderer {
public:
struct Vertex {
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 texCoord;
};
struct MeshHandle {
uint32_t firstIndex;
uint32_t count;
uint32_t material;
};
BatchingRenderer(lava::Subpass const &forwardPass,
lava::SharedDescriptorSetLayout const &cameraLayout);
MeshHandle add(std::string const &modelfile, std::string const &texture);
void upload();
void reset() { mDraws.clear(); }
void enqueue(MeshHandle const &handle, glm::mat4 const &modelMatrix) {
mDraws.emplace_back(handle, modelMatrix);
}
void draw(lava::InlineSubpass &sub,
const lava::SharedDescriptorSet &cameraSet);
protected:
std::vector<Vertex> mVertices;
std::vector<uint32_t> mIndices;
std::vector<lava::SharedDescriptorSet> mMaterials;
std::vector<std::pair<MeshHandle, glm::mat4>> mDraws;
lava::SharedBuffer mVertexBuffer;
lava::SharedBuffer mIndexBuffer;
lava::SharedGraphicsPipeline mPipeline;
lava::SharedDescriptorSetLayout mMaterialLayout;
lava::SharedSampler mSampler;
};
} // namespace vr
} // namespace lava
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment