载入中...
搜索中...
未找到
GraphicsDeferredLighting.cpp
浏览该文件的文档.
1// Hybrid clustered deferred lighting (Phase C): fullscreen pass that samples
2// the Phase B GBuffer and evaluates core PBR with ClusteredLight + CSM.
4#include "graphics/Shadow.h"
5#include "graphics/shaders/deferred_lighting_frag_spv.inc"
6#include "graphics/shaders/deferred_lighting_vert_spv.inc"
9
10#include <algorithm>
11#include <cstring>
12
13namespace eve::graphics::vulkan {
14namespace {
15
16std::vector<uint32_t> embeddedSpirv(const uint32_t* words, size_t count) {
17 return std::vector<uint32_t>(words, words + count);
18}
19
20} // namespace
21
22void Graphics::destroyDeferredLightingResources() {
23 destroyPipeline(device, deferredLightingPipeline);
24 destroyPipelineLayout(device, deferredLightingPipelineLayout);
25 deferredLightingSetLayout = vk::DescriptorSetLayout{};
26 deferredLightingSetLayoutUnique.reset();
27 deferredLightingSet = vk::DescriptorSet{};
28 deferredLightingUbo.release();
29 if (deferredLightingSampler) {
30 device->destroySampler(deferredLightingSampler);
31 deferredLightingSampler = nullptr;
32 }
33}
34
35void Graphics::createDeferredLightingPipeline() {
36 if (deferredLightingPipeline || !sceneColorRenderPass) return;
37
38 vkb::DescriptorSetLayoutBuilder layoutBuilder;
39 deferredLightingSetLayoutUnique =
40 layoutBuilder.buffer(0, vk::DescriptorType::eUniformBuffer, vk::ShaderStageFlagBits::eFragment, 1)
41 .image(1, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
42 .image(2, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
43 .image(3, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
44 .image(4, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
45 .image(5, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
46 .image(6, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
47 .buffer(7, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eFragment, 1)
48 .buffer(8, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eFragment, 1)
49 .buffer(9, vk::DescriptorType::eStorageBuffer, vk::ShaderStageFlagBits::eFragment, 1)
50 .buffer(10, vk::DescriptorType::eUniformBuffer, vk::ShaderStageFlagBits::eFragment, 1)
51 .image(11, vk::DescriptorType::eCombinedImageSampler, vk::ShaderStageFlagBits::eFragment, 1)
52 .createUnique(device.instance);
53 deferredLightingSetLayout = *deferredLightingSetLayoutUnique;
54 deferredLightingPipelineLayout = createPipelineLayout(device, deferredLightingSetLayout);
55
56 auto vert = embeddedSpirv(deferred_lighting_vert_spv, deferred_lighting_vert_spv_count);
57 auto frag = embeddedSpirv(deferred_lighting_frag_spv, deferred_lighting_frag_spv_count);
58 vk::ShaderModule vertModule = vkb::PipelineBuilder::createShaderModule(device.instance, vert);
59 vk::ShaderModule fragModule = vkb::PipelineBuilder::createShaderModule(device.instance, frag);
60 deferredLightingPipeline = device.createPipeline()
61 .useClassicPipeline(vertModule, fragModule)
62 .setPipelineLayout(deferredLightingPipelineLayout)
63 .setDynamicStatesViewportScissor()
64 .setRasterizer(vk::PolygonMode::eFill, false, false, 1.0f,
65 vk::CullModeFlagBits::eNone, vk::FrontFace::eClockwise)
66 .setMultisampler(false, sceneColorSamples)
67 // Always pass; fragment writes gl_FragDepth from GBuffer hwDepth so
68 // transparent Forward+ can depth-test against deferred opaques.
69 .setDepthStencil(true, true, vk::CompareOp::eAlways)
70 .setColorAttachmentCount(1)
71 .build(sceneColorRenderPass);
72 device->destroyShaderModule(vertModule);
73 device->destroyShaderModule(fragModule);
74
75 if (!deferredLightingUbo.buffer) {
76 deferredLightingUbo.allocate(frameToken(), device, vk::BufferUsageFlagBits::eUniformBuffer,
77 sizeof(DeferredLightingUBO), kHostVisibleCoherent);
78 }
79 if (!deferredLightingSampler) {
80 vkb::SamplerBuilder sb;
81 deferredLightingSampler = sb.nearestClamp().build(device);
82 }
83 if (!deferredLightingSet && descriptorPool) {
84 vk::DescriptorSetAllocateInfo alloc{};
85 alloc.descriptorPool = descriptorPool;
86 alloc.descriptorSetCount = 1;
87 alloc.pSetLayouts = &deferredLightingSetLayout;
88 deferredLightingSet = device->allocateDescriptorSets(alloc).front();
89 }
90}
91
93 if (!sceneColorPassOpen || !sceneColorRenderPass) return;
94 auto* gslot = currentGBufferSlot();
95 if (!gslot || !gslot->normalGpu.sampler) return;
96 createDeferredLightingPipeline();
97 if (!deferredLightingPipeline || !deferredLightingSet) return;
98
99 if (!shadowPipeline) createShadowResources();
100 vk::ImageView shadowView = currentShadowArrayView();
101 if (!shadowView || !shadowSampler) return;
102
103 // Ensure clustered storage exists even with an empty/inactive upload so
104 // the SSBO bindings stay valid. Hybrid always samples the cluster tables.
105 if (!mesh3dClustered.active) {
106 std::vector<ClusteredLightGpu> dirs;
107 if (glm::length(glm::vec3(mesh3dFrameUbo.lightDir)) > 1e-4f) {
109 d.posRadius = glm::vec4(glm::normalize(glm::vec3(mesh3dFrameUbo.lightDir)), 0.f);
110 d.color = glm::vec4(glm::vec3(mesh3dFrameUbo.lightColor), 1.f);
111 dirs.push_back(d);
112 }
114 {}, dirs, mesh3dFrameUbo.view, mesh3dFrameUbo.clipInfo.x, mesh3dFrameUbo.clipInfo.y,
115 std::max(1, sceneColorWidth), std::max(1, sceneColorHeight), /*fovYRad*/ 1.f, mesh3dFrameUbo.ambient);
116 empty.active = true;
118 } else {
119 uploadClusteredLighting(mesh3dClustered);
120 }
121 auto& storage = currentClusteredStorage();
122 if (!storage.lightsBuf.buffer || !storage.tableBuf.buffer || !storage.indicesBuf.buffer) return;
123
125 ubo.invViewProj = glm::inverse(mesh3dFrameUbo.mvp);
126 ubo.view = mesh3dFrameUbo.view;
127 ubo.lightDir = mesh3dFrameUbo.lightDir;
128 // Mesh3DUBO packs lightCount in lightDir.w; deferred_lighting.frag uses w as
129 // the primary-enable flag. Re-encode enable from the direction vector.
130 ubo.lightDir.w = glm::length(glm::vec3(mesh3dFrameUbo.lightDir)) > 1e-4f ? 1.f : 0.f;
131 ubo.lightColor = mesh3dFrameUbo.lightColor;
132 ubo.cameraPos = glm::vec4(glm::vec3(mesh3dFrameUbo.cameraPos), 0.f);
133 ubo.ambient = mesh3dFrameUbo.ambient;
134 if (mesh3dClustered.active) {
135 ubo.gridInfo = mesh3dClustered.gridInfo;
136 ubo.clipInfo = mesh3dClustered.clipInfo;
137 ubo.ambient = mesh3dClustered.ambient;
138 ubo.lightDir = mesh3dClustered.primaryDir;
139 ubo.lightColor = glm::vec4(glm::vec3(mesh3dClustered.primaryColor), 0.f);
140 ubo.view = mesh3dClustered.view;
141 }
142 ubo.clipInfo.z = float(std::max(1, sceneColorWidth));
143 ubo.clipInfo.w = float(std::max(1, sceneColorHeight));
144 deferredLightingUbo.updateLocal(frameToken(), &ubo, sizeof(ubo));
145
146 // Shadow UBO: stage the latest CSM upload into the clustered shadow ring.
147 ensureMesh3dStrides();
148 auto& cfslots = currentMesh3dClusteredFrameSlots();
149 ensureMesh3dClusteredRing(cfslots);
150 const uint32_t shadowOffset = 0;
151 std::memcpy(static_cast<uint8_t*>(cfslots.shadowRing.map()) + shadowOffset, &mesh3dShadows.ubo, sizeof(ShadowUBO));
152
153 auto writeImage = [&](uint32_t binding, vk::ImageView view, vk::Sampler sampler,
154 vk::ImageLayout layout = vk::ImageLayout::eShaderReadOnlyOptimal) {
155 vk::DescriptorImageInfo img{};
156 img.sampler = sampler;
157 img.imageView = view;
158 img.imageLayout = layout;
159 vk::WriteDescriptorSet w{};
160 w.dstSet = deferredLightingSet;
161 w.dstBinding = binding;
162 w.descriptorCount = 1;
163 w.descriptorType = vk::DescriptorType::eCombinedImageSampler;
164 w.pImageInfo = &img;
165 device->updateDescriptorSets(w, {});
166 };
167 auto writeBuffer = [&](uint32_t binding, vk::Buffer buffer, vk::DeviceSize size, vk::DescriptorType type) {
168 vk::DescriptorBufferInfo buf{};
169 buf.buffer = buffer;
170 buf.offset = 0;
171 buf.range = size;
172 vk::WriteDescriptorSet w{};
173 w.dstSet = deferredLightingSet;
174 w.dstBinding = binding;
175 w.descriptorCount = 1;
176 w.descriptorType = type;
177 w.pBufferInfo = &buf;
178 device->updateDescriptorSets(w, {});
179 };
180
181 writeBuffer(0, deferredLightingUbo.buffer, sizeof(DeferredLightingUBO), vk::DescriptorType::eUniformBuffer);
182 writeImage(1, gslot->normal.imageView(), deferredLightingSampler);
183 writeImage(2, gslot->depthColor.imageView(), deferredLightingSampler);
184 writeImage(3, gslot->albedo.imageView(), deferredLightingSampler);
185 writeImage(4, gslot->pbrParams.imageView(), deferredLightingSampler);
186 writeImage(5, gslot->emissive.imageView(), deferredLightingSampler);
187 writeImage(6, gslot->depth.imageView(), deferredLightingSampler);
188 writeBuffer(7, storage.lightsBuf.buffer, VK_WHOLE_SIZE, vk::DescriptorType::eStorageBuffer);
189 writeBuffer(8, storage.tableBuf.buffer, VK_WHOLE_SIZE, vk::DescriptorType::eStorageBuffer);
190 writeBuffer(9, storage.indicesBuf.buffer, VK_WHOLE_SIZE, vk::DescriptorType::eStorageBuffer);
191 {
192 vk::DescriptorBufferInfo buf{};
193 buf.buffer = cfslots.shadowRing.buffer;
194 buf.offset = shadowOffset;
195 buf.range = sizeof(ShadowUBO);
196 vk::WriteDescriptorSet w{};
197 w.dstSet = deferredLightingSet;
198 w.dstBinding = 10;
199 w.descriptorCount = 1;
200 w.descriptorType = vk::DescriptorType::eUniformBuffer;
201 w.pBufferInfo = &buf;
202 device->updateDescriptorSets(w, {});
203 }
204 writeImage(11, shadowView, vk::Sampler(shadowSampler), currentShadowMap().image.currentLayout());
205
206 auto& cb = currentPresentCb();
207 cb.bindPipeline(vk::PipelineBindPoint::eGraphics, deferredLightingPipeline);
208 cb.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, deferredLightingPipelineLayout, 0, 1, &deferredLightingSet,
209 0, nullptr);
210 setViewportAndScissor(cb, uint32_t(sceneColorWidth), uint32_t(sceneColorHeight));
211 cb.draw(3, 1, 0, 0);
212}
213
214} // namespace eve::graphics::vulkan
float w
Definition AnimClip.cpp:738
std::string layout
vk::ShaderModule vert
vk::ShaderModule frag
vk::UniqueSampler sampler
vk::UniqueImage image
std::unique_ptr< gpgpu::GpuBuffer > buffer
Definition OnnxGpgpu.cpp:26
eve::action::ActionVfxBinding binding
float d
glm::mat4 view
std::uint32_t count
float size
Definition TreeMesh.cpp:156
void drawDeferredLighting() override
Draws deferred lighting.
void setMesh3DClusteredLighting(const ClusteredLightingUpload &upload) override
Sets the mesh 3 d clustered lighting.
ClusteredLightingUpload buildClusteredLighting(const std::vector< ClusteredLightGpu > &points, const std::vector< ClusteredLightGpu > &dirs, const glm::mat4 &view, float nearZ, float farZ, int screenW, int screenH, float fovYRad, const glm::vec4 &ambient)
Build clustered tables for point lights in view space.
CPU-built clustered lighting upload for one frame/camera. Point lights are clustered; directional lig...
GPU light packing for mesh3d / PBR (std140-friendly).
Definition Light.h:161
Per-frame / per-draw CSM + local-spot constants (std140).
Definition Shadow.h:36
DeferredLightingUBO public API.
Definition Graphics.h:222