History

Revert "Revert "Mirrors + Portals""

Dale Glass committed 2 years ago

Commit e7591d61 parent b33d35c81 files · +1047 −263Browse files

Showing the changes to libraries/render-utils/src/RenderCommonTask.cpp (1 of 81 files). Show all

Unified · Split

libraries/render-utils/src/RenderCommonTask.cpp+157−2
@@ -13,7 +13,10 @@ · 12 unmodified lines
1313
1414 #include "render-utils/ShaderConstants.h"
1515 #include "DeferredLightingEffect.h"
16+#include "FadeEffect.h"
1617 #include "RenderUtilsLogging.h"
18+#include "RenderViewTask.h"
19+#include "StencilMaskPass.h"
1720
1821 namespace ru {
1922 using render_utils::slot::texture::Texture;
@@ -25,9 +28,11 @@ namespace gr { · 5 unmodified lines
2528 using graphics::slot::buffer::Buffer;
2629 }
2730
31+using RenderArgsPointer = std::shared_ptr<RenderArgs>;
2832
2933 using namespace render;
3034 extern void initForwardPipelines(ShapePlumber& plumber);
35+extern void initMirrorPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter, bool forward);
3136
3237 void BeginGPURangeTimer::run(const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) {
3338 timer = _gpuTimer;
@@ -45,10 +50,14 @@ void EndGPURangeTimer::run(const render::RenderContextPointer& renderContext, co · 11 unmodified lines
4550 config->setGPUBatchRunTime(timer->getGPUAverage(), timer->getBatchAverage());
4651 }
4752
53+render::ShapePlumberPointer DrawLayered3D::_shapePlumber = std::make_shared<ShapePlumber>();
54+
4855 DrawLayered3D::DrawLayered3D(bool opaque) :
49− _shapePlumber(std::make_shared<ShapePlumber>()),
5056 _opaquePass(opaque) {
51− initForwardPipelines(*_shapePlumber);
57+ static std::once_flag once;
58+ std::call_once(once, [] {
59+ initForwardPipelines(*_shapePlumber);
60+ });
5261 }
5362
5463 void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& inputs) {
@@ -262,3 +271,149 @@ void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, · 207 unmodified lines
262271 }
263272 }
264273
274+class SetupMirrorTask {
275+public:
276+ using Input = RenderMirrorTask::Inputs;
277+ using Outputs = render::VaryingSet4<render::ItemBound, gpu::FramebufferPointer, RenderArgsPointer, glm::vec2>;
278+ using JobModel = render::Job::ModelIO<SetupMirrorTask, Input, Outputs>;
279+
280+ SetupMirrorTask(size_t mirrorIndex, size_t depth) : _mirrorIndex(mirrorIndex), _depth(depth) {}
281+
282+ void run(const render::RenderContextPointer& renderContext, const Input& inputs, Outputs& outputs) {
283+ auto args = renderContext->args;
284+ auto items = inputs.get0();
285+
286+ if (items.empty() || _mirrorIndex > items.size() - 1) {
287+ renderContext->taskFlow.abortTask();
288+ return;
289+ }
290+
291+ auto inputFramebuffer = inputs.get1();
292+ if (!_mirrorFramebuffer || _mirrorFramebuffer->getWidth() != inputFramebuffer->getWidth() || _mirrorFramebuffer->getHeight() != inputFramebuffer->getHeight()) {
293+ _mirrorFramebuffer.reset(gpu::Framebuffer::create("mirror" + _mirrorIndex, gpu::Element::COLOR_SRGBA_32, inputFramebuffer->getWidth(), inputFramebuffer->getHeight()));
294+ }
295+
296+ render::ItemBound mirror = items[_mirrorIndex];
297+
298+ _cachedArgsPointer->_renderMode = args->_renderMode;
299+ _cachedArgsPointer->_blitFramebuffer = args->_blitFramebuffer;
300+ _cachedArgsPointer->_ignoreItem = args->_ignoreItem;
301+ _cachedArgsPointer->_mirrorDepth = args->_mirrorDepth;
302+ _cachedArgsPointer->_numMirrorFlips = args->_numMirrorFlips;
303+
304+ ViewFrustum srcViewFrustum = args->getViewFrustum();
305+ ItemID portalExitID = args->_scene->getItem(mirror.id).computeMirrorView(srcViewFrustum);
306+
307+ args->_blitFramebuffer = _mirrorFramebuffer;
308+ args->_ignoreItem = portalExitID != Item::INVALID_ITEM_ID ? portalExitID : mirror.id;
309+ args->_mirrorDepth = _depth;
310+ args->_numMirrorFlips += portalExitID != Item::INVALID_ITEM_ID ? 0 : 1;
311+
312+ gpu::doInBatch("SetupMirrorTask::run", args->_context, [&](gpu::Batch& batch) {
313+ bool shouldMirror = args->_numMirrorFlips % 2 == (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE);
314+ batch.setContextMirrorViewCorrection(shouldMirror);
315+ });
316+
317+ // Without calculating the bound planes, the mirror will use the same culling frustum as the main camera,
318+ // which is not what we want here.
319+ srcViewFrustum.calculate();
320+ args->pushViewFrustum(srcViewFrustum);
321+
322+ outputs.edit0() = mirror;
323+ outputs.edit1() = inputFramebuffer;
324+ outputs.edit2() = _cachedArgsPointer;
325+ outputs.edit3() = inputs.get2();
326+ }
327+
328+protected:
329+ gpu::FramebufferPointer _mirrorFramebuffer { nullptr };
330+ RenderArgsPointer _cachedArgsPointer { std::make_shared<RenderArgs>() };
331+ size_t _mirrorIndex;
332+ size_t _depth;
333+
334+};
335+
336+class DrawMirrorTask {
337+public:
338+ using Inputs = SetupMirrorTask::Outputs;
339+ using JobModel = render::Job::ModelI<DrawMirrorTask, Inputs>;
340+
341+ DrawMirrorTask() {
342+ static std::once_flag once;
343+ std::call_once(once, [this] {
344+ auto state = std::make_shared<gpu::State>();
345+ state->setCullMode(gpu::State::CULL_BACK);
346+ state->setDepthTest(true, true, gpu::LESS_EQUAL);
347+ PrepareStencil::testMaskDrawShape(*state);
348+
349+ auto fadeEffect = DependencyManager::get<FadeEffect>();
350+ initMirrorPipelines(*_forwardPipelines, state, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter(), true);
351+ initMirrorPipelines(*_deferredPipelines, state, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter(), false);
352+ });
353+ }
354+
355+ void run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
356+ auto args = renderContext->args;
357+ auto mirror = inputs.get0();
358+ auto framebuffer = inputs.get1();
359+ auto cachedArgs = inputs.get2();
360+ auto jitter = inputs.get3();
361+
362+ if (cachedArgs) {
363+ args->_renderMode = cachedArgs->_renderMode;
364+ }
365+ args->popViewFrustum();
366+
367+ gpu::doInBatch("DrawMirrorTask::run", args->_context, [&](gpu::Batch& batch) {
368+ args->_batch = &batch;
369+
370+ if (cachedArgs) {
371+ bool shouldMirror = cachedArgs->_numMirrorFlips % 2 == (args->_renderMode != RenderArgs::MIRROR_RENDER_MODE);
372+ batch.setContextMirrorViewCorrection(shouldMirror);
373+ }
374+
375+ batch.setFramebuffer(framebuffer);
376+ batch.setViewportTransform(args->_viewport);
377+ batch.setStateScissorRect(args->_viewport);
378+
379+ glm::mat4 projMat;
380+ Transform viewMat;
381+ args->getViewFrustum().evalProjectionMatrix(projMat);
382+ args->getViewFrustum().evalViewTransform(viewMat);
383+
384+ batch.setProjectionTransform(projMat);
385+ batch.setProjectionJitter(jitter.x, jitter.y);
386+ batch.setViewTransform(viewMat);
387+
388+ batch.setResourceTexture(gr::Texture::MaterialMirror, args->_blitFramebuffer->getRenderBuffer(0));
389+
390+ renderShapes(renderContext, args->_renderMethod == render::Args::RenderMethod::FORWARD ? _forwardPipelines : _deferredPipelines, { mirror });
391+
392+ args->_batch = nullptr;
393+ });
394+
395+ if (cachedArgs) {
396+ // Restore the blit framebuffer after we've sampled from it
397+ args->_blitFramebuffer = cachedArgs->_blitFramebuffer;
398+ args->_ignoreItem = cachedArgs->_ignoreItem;
399+ args->_mirrorDepth = cachedArgs->_mirrorDepth;
400+ args->_numMirrorFlips = cachedArgs->_numMirrorFlips;
401+ }
402+ }
403+
404+private:
405+ static ShapePlumberPointer _forwardPipelines;
406+ static ShapePlumberPointer _deferredPipelines;
407+};
408+
409+ShapePlumberPointer DrawMirrorTask::_forwardPipelines = std::make_shared<ShapePlumber>();
410+ShapePlumberPointer DrawMirrorTask::_deferredPipelines = std::make_shared<ShapePlumber>();
411+
412+ void RenderMirrorTask::build(JobModel& task, const render::Varying& inputs, render::Varying& output, size_t mirrorIndex, render::CullFunctor cullFunctor, size_t depth) {
413+ size_t nextDepth = depth + 1;
414+ const auto setupOutput = task.addJob<SetupMirrorTask>("SetupMirror" + std::to_string(mirrorIndex) + "Depth" + std::to_string(depth), inputs, mirrorIndex, nextDepth);
415+
416+ task.addJob<RenderViewTask>("RenderMirrorView" + std::to_string(mirrorIndex) + "Depth" + std::to_string(depth), cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1, nextDepth);
417+
418+ task.addJob<DrawMirrorTask>("DrawMirrorTask" + std::to_string(mirrorIndex) + "Depth" + std::to_string(depth), setupOutput);
419+ }