Showing the changes to libraries/render-utils/src/RenderCommonTask.cpp (1 of 81 files). Show all
Unified · Split
| @@ -13,7 +13,10 @@ · 12 unmodified lines | ||
| 13 | 13 | |
| 14 | 14 | #include "render-utils/ShaderConstants.h" |
| 15 | 15 | #include "DeferredLightingEffect.h" |
| 16 | +#include "FadeEffect.h" | |
| 16 | 17 | #include "RenderUtilsLogging.h" |
| 18 | +#include "RenderViewTask.h" | |
| 19 | +#include "StencilMaskPass.h" | |
| 17 | 20 | |
| 18 | 21 | namespace ru { |
| 19 | 22 | using render_utils::slot::texture::Texture; |
| @@ -25,9 +28,11 @@ namespace gr { · 5 unmodified lines | ||
| 25 | 28 | using graphics::slot::buffer::Buffer; |
| 26 | 29 | } |
| 27 | 30 | |
| 31 | +using RenderArgsPointer = std::shared_ptr<RenderArgs>; | |
| 28 | 32 | |
| 29 | 33 | using namespace render; |
| 30 | 34 | 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); | |
| 31 | 36 | |
| 32 | 37 | void BeginGPURangeTimer::run(const render::RenderContextPointer& renderContext, gpu::RangeTimerPointer& timer) { |
| 33 | 38 | timer = _gpuTimer; |
| @@ -45,10 +50,14 @@ void EndGPURangeTimer::run(const render::RenderContextPointer& renderContext, co · 11 unmodified lines | ||
| 45 | 50 | config->setGPUBatchRunTime(timer->getGPUAverage(), timer->getBatchAverage()); |
| 46 | 51 | } |
| 47 | 52 | |
| 53 | +render::ShapePlumberPointer DrawLayered3D::_shapePlumber = std::make_shared<ShapePlumber>(); | |
| 54 | + | |
| 48 | 55 | DrawLayered3D::DrawLayered3D(bool opaque) : |
| 49 | − _shapePlumber(std::make_shared<ShapePlumber>()), | |
| 50 | 56 | _opaquePass(opaque) { |
| 51 | − initForwardPipelines(*_shapePlumber); | |
| 57 | + static std::once_flag once; | |
| 58 | + std::call_once(once, [] { | |
| 59 | + initForwardPipelines(*_shapePlumber); | |
| 60 | + }); | |
| 52 | 61 | } |
| 53 | 62 | |
| 54 | 63 | void DrawLayered3D::run(const RenderContextPointer& renderContext, const Inputs& inputs) { |
| @@ -262,3 +271,149 @@ void ResolveFramebuffer::run(const render::RenderContextPointer& renderContext, · 207 unmodified lines | ||
| 262 | 271 | } |
| 263 | 272 | } |
| 264 | 273 | |
| 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 | + } | |