131 lines
6.2 KiB
C++
131 lines
6.2 KiB
C++
#include "vk_materials.h"
|
|
|
|
#include "core/vk_engine.h"
|
|
#include "render/vk_pipelines.h"
|
|
#include "core/vk_initializers.h"
|
|
#include "core/vk_pipeline_manager.h"
|
|
#include "core/asset_manager.h"
|
|
|
|
namespace vkutil { bool load_shader_module(const char*, VkDevice, VkShaderModule*); }
|
|
|
|
void GLTFMetallic_Roughness::build_pipelines(VulkanEngine *engine)
|
|
{
|
|
VkPushConstantRange matrixRange{};
|
|
matrixRange.offset = 0;
|
|
matrixRange.size = sizeof(GPUDrawPushConstants);
|
|
matrixRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
|
|
DescriptorLayoutBuilder layoutBuilder;
|
|
layoutBuilder.add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
layoutBuilder.add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
layoutBuilder.add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
layoutBuilder.add_binding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
|
|
materialLayout = layoutBuilder.build(engine->_deviceManager->device(),
|
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
nullptr, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT);
|
|
|
|
VkDescriptorSetLayout layouts[] = {
|
|
engine->_descriptorManager->gpuSceneDataLayout(),
|
|
materialLayout
|
|
};
|
|
|
|
// Register pipelines with the central PipelineManager
|
|
GraphicsPipelineCreateInfo opaqueInfo{};
|
|
opaqueInfo.vertexShaderPath = engine->_context->getAssets()->shaderPath("mesh.vert.spv");
|
|
opaqueInfo.fragmentShaderPath = engine->_context->getAssets()->shaderPath("mesh.frag.spv");
|
|
opaqueInfo.setLayouts.assign(std::begin(layouts), std::end(layouts));
|
|
opaqueInfo.pushConstants = {matrixRange};
|
|
opaqueInfo.configure = [engine](PipelineBuilder &b) {
|
|
b.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
|
b.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
|
b.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
|
b.set_multisampling_none();
|
|
b.disable_blending();
|
|
// Reverse-Z depth test configuration
|
|
b.enable_depthtest(true, VK_COMPARE_OP_GREATER_OR_EQUAL);
|
|
b.set_color_attachment_format(engine->_swapchainManager->drawImage().imageFormat);
|
|
b.set_depth_format(engine->_swapchainManager->depthImage().imageFormat);
|
|
};
|
|
engine->_pipelineManager->registerGraphics("mesh.opaque", opaqueInfo);
|
|
|
|
GraphicsPipelineCreateInfo transparentInfo = opaqueInfo;
|
|
transparentInfo.configure = [engine](PipelineBuilder &b) {
|
|
b.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
|
b.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
|
b.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
|
b.set_multisampling_none();
|
|
// Physically-based transparency uses standard alpha blending
|
|
b.enable_blending_alphablend();
|
|
// Transparent pass: keep reverse-Z test (no writes)
|
|
b.enable_depthtest(false, VK_COMPARE_OP_GREATER_OR_EQUAL);
|
|
b.set_color_attachment_format(engine->_swapchainManager->drawImage().imageFormat);
|
|
b.set_depth_format(engine->_swapchainManager->depthImage().imageFormat);
|
|
};
|
|
engine->_pipelineManager->registerGraphics("mesh.transparent", transparentInfo);
|
|
|
|
GraphicsPipelineCreateInfo gbufferInfo{};
|
|
gbufferInfo.vertexShaderPath = engine->_context->getAssets()->shaderPath("mesh.vert.spv");
|
|
gbufferInfo.fragmentShaderPath = engine->_context->getAssets()->shaderPath("gbuffer.frag.spv");
|
|
gbufferInfo.setLayouts.assign(std::begin(layouts), std::end(layouts));
|
|
gbufferInfo.pushConstants = {matrixRange};
|
|
gbufferInfo.configure = [engine](PipelineBuilder &b) {
|
|
b.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
|
|
b.set_polygon_mode(VK_POLYGON_MODE_FILL);
|
|
b.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
|
|
b.set_multisampling_none();
|
|
b.disable_blending();
|
|
// GBuffer uses reverse-Z depth
|
|
b.enable_depthtest(true, VK_COMPARE_OP_GREATER_OR_EQUAL);
|
|
VkFormat gFormats[] = {
|
|
engine->_swapchainManager->gBufferPosition().imageFormat,
|
|
engine->_swapchainManager->gBufferNormal().imageFormat,
|
|
engine->_swapchainManager->gBufferAlbedo().imageFormat
|
|
};
|
|
b.set_color_attachment_formats(std::span<VkFormat>(gFormats, 3));
|
|
b.set_depth_format(engine->_swapchainManager->depthImage().imageFormat);
|
|
};
|
|
engine->_pipelineManager->registerGraphics("mesh.gbuffer", gbufferInfo);
|
|
|
|
engine->_pipelineManager->getMaterialPipeline("mesh.opaque", opaquePipeline);
|
|
engine->_pipelineManager->getMaterialPipeline("mesh.transparent", transparentPipeline);
|
|
engine->_pipelineManager->getMaterialPipeline("mesh.gbuffer", gBufferPipeline);
|
|
}
|
|
|
|
void GLTFMetallic_Roughness::clear_resources(VkDevice device) const
|
|
{
|
|
vkDestroyDescriptorSetLayout(device, materialLayout, nullptr);
|
|
}
|
|
|
|
MaterialInstance GLTFMetallic_Roughness::write_material(VkDevice device, MaterialPass pass,
|
|
const MaterialResources &resources,
|
|
DescriptorAllocatorGrowable &descriptorAllocator)
|
|
{
|
|
MaterialInstance matData{};
|
|
matData.passType = pass;
|
|
if (pass == MaterialPass::Transparent)
|
|
{
|
|
matData.pipeline = &transparentPipeline;
|
|
}
|
|
else
|
|
{
|
|
matData.pipeline = &gBufferPipeline;
|
|
}
|
|
|
|
matData.materialSet = descriptorAllocator.allocate(device, materialLayout);
|
|
|
|
writer.clear();
|
|
writer.write_buffer(0, resources.dataBuffer, sizeof(MaterialConstants), resources.dataBufferOffset,
|
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
|
writer.write_image(1, resources.colorImage.imageView, resources.colorSampler,
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
writer.write_image(2, resources.metalRoughImage.imageView, resources.metalRoughSampler,
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
writer.write_image(3, resources.normalImage.imageView, resources.normalSampler,
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
|
|
|
writer.update_set(device, matData.materialSet);
|
|
|
|
return matData;
|
|
}
|