3#include <Tempest/Color>
4#include <Tempest/Fence>
6#include <Tempest/StorageImage>
15using namespace Tempest;
30static float smoothstep(
float edge0,
float edge1,
float x) {
31 float t = std::min(std::max((x - edge0) / (edge1 - edge0), 0.f), 1.f);
32 return t * t * (3.f - 2.f * t);
35static float linearstep(
float edge0,
float edge1,
float x) {
36 float t = std::min(std::max((x - edge0) / (edge1 - edge0), 0.f), 1.f);
47 : swapchain(swapchain) {
50 static const TextureFormat sfrm[] = {
51 TextureFormat::Depth16,
52 TextureFormat::Depth24x8,
53 TextureFormat::Depth32F,
57 if(device.properties().hasDepthFormat(i) && device.properties().hasSamplerFormat(i)) {
63 static const TextureFormat zfrm[] = {
64 TextureFormat::Depth32F,
65 TextureFormat::Depth24x8,
66 TextureFormat::Depth16,
69 if(device.properties().hasDepthFormat(i) && device.properties().hasSamplerFormat(i)){
76 if(!device.properties().hasStorageFormat(sky.lutRGBAFormat))
77 sky.lutRGBAFormat = Tempest::TextureFormat::RGBA8;
78 if(!device.properties().hasStorageFormat(sky.lutRGBFormat))
79 sky.lutRGBFormat = Tempest::TextureFormat::RGBA8;
81 Log::i(
"GPU = ",device.properties().name);
82 Log::i(
"Depth format = ", Tempest::formatName(zBufferFormat),
" Shadow format = ", Tempest::formatName(shadowFormat));
95 sky.cloudsLut = device.image2d (sky.lutRGBAFormat, 2, 1);
96 sky.transLut = device.attachment(sky.lutRGBFormat, 256, 64);
97 sky.multiScatLut = device.attachment(sky.lutRGBFormat, 32, 32);
98 sky.viewLut = device.attachment(Tempest::TextureFormat::RGBA32F, 128, 64);
99 sky.viewCldLut = device.attachment(Tempest::TextureFormat::RGBA32F, 512, 256);
100 sky.irradianceLut = device.image2d(TextureFormat::RGBA32F, 3,2);
114 const auto res = internalResolution();
115 const uint32_t w = uint32_t(res.w);
116 const uint32_t h = uint32_t(res.h);
118 sceneLinear = device.attachment(TextureFormat::R11G11B10UF,w,h);
120 if(settings.aaEnabled) {
121 cmaa2.workingEdges = device.image2d(TextureFormat::R8, (w + 1) / 2, h);
122 cmaa2.shapeCandidates = device.ssbo(Tempest::Uninitialized, w * h / 4 *
sizeof(uint32_t));
123 cmaa2.deferredBlendLocationList = device.ssbo(Tempest::Uninitialized, (w * h + 3) / 6 *
sizeof(uint32_t));
124 cmaa2.deferredBlendItemList = device.ssbo(Tempest::Uninitialized, w * h *
sizeof(uint32_t));
125 cmaa2.deferredBlendItemListHeads = device.image2d(TextureFormat::R32U, (w + 1) / 2, (h + 1) / 2);
126 cmaa2.controlBuffer = device.ssbo(
nullptr, 5 *
sizeof(uint32_t));
127 cmaa2.indirectBuffer = device.ssbo(
nullptr,
sizeof(DispatchIndirectCommand) +
sizeof(DrawIndirectCommand));
130 zbuffer = device.zbuffer(zBufferFormat,w,h);
131 if(w!=swapchain.w() || h!=swapchain.h())
132 zbufferUi = device.zbuffer(zBufferFormat, swapchain.w(), swapchain.h());
else
133 zbufferUi = ZBuffer();
140 while(hw>64 || hh>64) {
141 hw = std::max(1u, (hw+1)/2u);
142 hh = std::max(1u, (hh+1)/2u);
145 hiz.atomicImg = device.properties().hasAtomicFormat(TextureFormat::R32U);
146 hiz.hiZ = device.image2d(TextureFormat::R16, hw, hh,
true);
148 hiz.counter = device.image2d(TextureFormat::R32U, std::max(hw/4, 1u), std::max(hh/4, 1u),
false);
150 hiz.counterBuf = device.ssbo(Tempest::Uninitialized, std::max(hw/4, 1u)*std::max(hh/4, 1u)*
sizeof(uint32_t));
153 sceneOpaque = device.attachment(TextureFormat::R11G11B10UF,w,h);
154 sceneDepth = device.attachment(TextureFormat::R32F, w,h);
156 gbufDiffuse = device.attachment(TextureFormat::RGBA8,w,h);
157 gbufNormal = device.attachment(TextureFormat::R32U, w,h);
159 ssao.ssaoBuf = device.image2d(ssao.aoFormat, w, h);
160 ssao.ssaoBlur = device.image2d(ssao.aoFormat, w, h);
162 epipolar =
decltype(epipolar)();
163 vsm =
decltype(vsm)();
164 rtsm =
decltype(rtsm)();
167 swr.outputImage = StorageImage();
170 swrt.outputImage = StorageImage();
176void Renderer::setupSettings() {
187 if(settings.sunSize<=1)
188 settings.sunSize = 200;
189 if(settings.moonSize<=1)
190 settings.moonSize = 400;
192 auto prevVidResIndex = settings.vidResIndex;
194 settings.aaEnabled = (
Gothic::options().aaPreset>0) && (settings.vidResIndex==0);
197 if(settings.rtsmEnabled)
199 else if(settings.vsmEnabled)
202 settings.shadowResolution>0)
204 else if(settings.shadowResolution>0)
210 if(settings.vsmEnabled)
211 lights.directLightPso = &shaders.
lightsVsm;
213 lights.directLightPso = &shaders.
lightsRq;
215 lights.directLightPso = &shaders.
lights;
217 if(prevVidResIndex!=settings.vidResIndex) {
226void Renderer::toggleGi() {
231 auto prop = device.properties();
232 if(prop.tex2d.maxSize<4096 || !prop.hasStorageFormat(R11G11B10UF) || !prop.hasStorageFormat(R16))
235 settings.giEnabled = !settings.giEnabled;
236 gi.fisrtFrame =
true;
240 wview->resetRendering();
242 if(settings.giEnabled) {
250void Renderer::toggleVsm() {
254 settings.vsmEnabled = !settings.vsmEnabled;
262 wview->resetRendering();
266void Renderer::toggleRtsm() {
270 settings.rtsmEnabled = !settings.rtsmEnabled;
278 wview->resetRendering();
283 gi.fisrtFrame =
true;
284 sky.lutIsInitialized =
false;
292void Renderer::updateCamera(
const Camera& camera) {
299 shadowMatrix[i] = camera.
viewShadow(wview->mainLight().dir(),i);
300 shadowMatrixVsm = camera.
viewShadowVsm(wview->mainLight().dir());
303 auto zNear = camera.
zNear();
304 auto zFar = camera.
zFar();
305 clipInfo.x = zNear*zFar;
306 clipInfo.y = zNear-zFar;
310bool Renderer::requiresTlas()
const {
314 if(settings.giEnabled)
316 if(!(settings.rtsmEnabled || settings.vsmEnabled))
321StorageImage& Renderer::usesImage3d(Tempest::StorageImage& ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h, uint32_t d,
bool mips) {
322 if(ret.format()==frm && uint32_t(ret.w())==w && uint32_t(ret.h())==h && uint32_t(ret.d())==d &&
bool(ret.mipCount()>1)==mips)
329StorageImage& Renderer::usesImage2d(Tempest::StorageImage& ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h,
bool mips) {
330 if(ret.format()==frm && uint32_t(ret.w())==w && uint32_t(ret.h())==h && ret.d()==1 &&
bool(ret.mipCount()>1)==mips)
337StorageImage& Renderer::usesImage2d(Tempest::StorageImage& ret, Tempest::TextureFormat frm, Tempest::Size size,
bool mips) {
338 if(ret.format()==frm && ret.size()==size && ret.d()==1 && (ret.mipCount()>1)==mips)
345ZBuffer& Renderer::usesZBuffer(Tempest::ZBuffer& ret, Tempest::TextureFormat frm, uint32_t w, uint32_t h) {
346 if(textureCast<Texture2d&>(ret).format()==frm && uint32_t(ret.w())==w && uint32_t(ret.h())==h)
353StorageBuffer& Renderer::usesSsbo(Tempest::StorageBuffer& ret,
size_t size) {
354 if(ret.byteSize()==size)
361StorageBuffer& Renderer::usesScratch(Tempest::StorageBuffer& ret,
size_t size) {
362 if(ret.byteSize()>=size)
369void Renderer::prepareUniforms() {
376 if(!shadowMap[i].isEmpty()) {
377 sh[i] = &textureCast<const Texture2d&>(shadowMap[i]);
379 wview->setShadowMaps(sh);
380 wview->setVirtualShadowMap(settings.vsmEnabled, vsm.pageData, vsm.pageTbl, vsm.pageHiZ, vsm.pageList);
382 wview->setHiZ(textureCast<const Texture2d&>(hiz.hiZ));
383 wview->setGbuffer(textureCast<const Texture2d&>(gbufDiffuse), textureCast<const Texture2d&>(gbufNormal));
384 wview->setSceneImages(textureCast<const Texture2d&>(sceneOpaque), textureCast<const Texture2d&>(sceneDepth), zbuffer);
387void Renderer::resetShadowmap() {
394 if(settings.vsmEnabled && !(settings.giEnabled && i==1) && !(sky.quality==PathTrace && i==1) && !(settings.rtsmEnabled && i==1))
396 if(settings.rtsmEnabled && !(settings.giEnabled && i==1) && !(sky.quality!=None && i==1))
398 shadowMap[i] = device.zbuffer(shadowFormat, settings.shadowResolution, settings.shadowResolution);
402void Renderer::resetSkyFog() {
405 const auto res = internalResolution();
406 const uint32_t w = uint32_t(res.w);
407 const uint32_t h = uint32_t(res.h);
410 auto q = Quality::VolumetricLQ;
411 if(!settings.zFogRadial) {
412 q = Quality::VolumetricLQ;
414 q = Quality::VolumetricHQ;
421 if(sky.quality==q && (sky.occlusionLut.isEmpty() || sky.occlusionLut.size()==res)) {
432 sky.lutIsInitialized =
false;
434 switch(sky.quality) {
437 sky.fogLut3D = device.image3d(sky.lutRGBAFormat, 160, 90, 64);
438 sky.occlusionLut = StorageImage();
442 sky.fogLut3D = device.image3d(sky.lutRGBFormat, 128,64,32);
443 sky.fogLut3DMs = device.image3d(sky.lutRGBAFormat, 128,64,32);
444 sky.occlusionLut = device.image2d(TextureFormat::R32U, w, h);
447 sky.fogLut3D = device.image3d(sky.lutRGBFormat, 128,64,32);
448 sky.fogLut3DMs = device.image3d(sky.lutRGBAFormat, 128,64,32);
449 sky.occlusionLut = device.image2d(TextureFormat::R32U, w, h);
456void Renderer::prepareSky(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
459 cmd.setDebugMarker(
"Sky LUT");
460 if(!sky.lutIsInitialized) {
461 sky.lutIsInitialized =
true;
463 cmd.setFramebuffer({});
464 cmd.setBinding(0, sky.cloudsLut);
465 cmd.setBinding(5, *wview.
sky().
cloudsDay() .
lay[0], Sampler::trillinear());
466 cmd.setBinding(6, *wview.
sky().
cloudsDay() .
lay[1], Sampler::trillinear());
470 cmd.dispatchThreads(
size_t(sky.cloudsLut.w()),
size_t(sky.cloudsLut.h()));
472 auto sz = Vec2(
float(sky.transLut.w()),
float(sky.transLut.h()));
473 cmd.setFramebuffer({{sky.transLut, Tempest::Discard, Tempest::Preserve}});
474 cmd.setBinding(5, *wview.
sky().
cloudsDay() .
lay[0], Sampler::trillinear());
475 cmd.setBinding(6, *wview.
sky().
cloudsDay() .
lay[1], Sampler::trillinear());
478 cmd.setPushData(&sz,
sizeof(sz));
480 cmd.draw(
nullptr, 0, 3);
482 sz = Vec2(
float(sky.multiScatLut.w()),
float(sky.multiScatLut.h()));
483 cmd.setFramebuffer({{sky.multiScatLut, Tempest::Discard, Tempest::Preserve}});
484 cmd.setBinding(0, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
485 cmd.setPushData(&sz,
sizeof(sz));
487 cmd.draw(
nullptr, 0, 3);
490 auto sz = Vec2(
float(sky.viewLut.w()),
float(sky.viewLut.h()));
491 cmd.setFramebuffer({{sky.viewLut, Tempest::Discard, Tempest::Preserve}});
493 cmd.setBinding(1, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
494 cmd.setBinding(2, sky.multiScatLut, Sampler::bilinear(ClampMode::ClampToEdge));
495 cmd.setBinding(3, sky.cloudsLut, Sampler::bilinear(ClampMode::ClampToEdge));
496 cmd.setPushData(&sz,
sizeof(sz));
498 cmd.draw(
nullptr, 0, 3);
500 sz = Vec2(
float(sky.viewCldLut.w()),
float(sky.viewCldLut.h()));
501 cmd.setFramebuffer({{sky.viewCldLut, Tempest::Discard, Tempest::Preserve}});
503 cmd.setBinding(1, sky.viewLut);
504 cmd.setBinding(2, *wview.
sky().
cloudsDay() .
lay[0], Sampler::trillinear());
505 cmd.setBinding(3, *wview.
sky().
cloudsDay() .
lay[1], Sampler::trillinear());
508 cmd.setPushData(&sz,
sizeof(sz));
510 cmd.draw(
nullptr, 0, 3);
513void Renderer::draw(Encoder<CommandBuffer>& cmd, uint8_t cmdId,
size_t imgId,
514 VectorImage::Mesh& uiLayer, VectorImage::Mesh& numOverlay,
516 auto& result = swapchain[imgId];
519 draw(result, cmd, cmdId);
521 cmd.setFramebuffer({{result, Vec4(), Tempest::Preserve}});
523 cmd.setFramebuffer({{result, Tempest::Preserve, Tempest::Preserve}});
524 cmd.setDebugMarker(
"UI");
528 auto& zb = (zbufferUi.isEmpty() ? zbuffer : zbufferUi);
529 cmd.setFramebuffer({{result, Tempest::Preserve, Tempest::Preserve}},{zb, 1.f, Tempest::Preserve});
530 cmd.setDebugMarker(
"Inventory");
533 cmd.setFramebuffer({{result, Tempest::Preserve, Tempest::Preserve}});
534 cmd.setDebugMarker(
"Inventory-counters");
535 numOverlay.draw(cmd);
540 static bool dbg =
false;
544 std::vector<const Texture2d*> tex;
552 tex.push_back(&textureCast<const Texture2d&>(swrt.outputImage));
554 static int size = 400;
557 p.setBrush(Brush(*t,Painter::NoBlend,ClampMode::ClampToBorder));
558 auto sz = Size(p.brush().w(),p.brush().h());
561 while(sz.w<size && sz.h<size) {
565 while(sz.w>size*2 || sz.h>size*2) {
569 p.drawRect(left,50,sz.w,sz.h,
570 0,0,p.brush().w(),p.brush().h());
575void Renderer::draw(Tempest::Attachment& result, Encoder<CommandBuffer>& cmd, uint8_t fId) {
578 if(wview==
nullptr || camera==
nullptr) {
579 cmd.setFramebuffer({{result, Vec4(), Tempest::Preserve}});
587 updateCamera(*camera);
589 static bool updFr =
true;
608 prepareSky(cmd,*wview);
610 drawHiZ (cmd, *wview);
614 drawGBuffer(cmd,fId,*wview);
616 drawShadowMap(cmd,fId,*wview);
617 prepareEpipolar(cmd, *wview);
619 drawVsm(cmd, *wview);
620 drawSwr(cmd, *wview);
621 drawRtsm(cmd, *wview);
622 drawRtsmOmni(cmd, *wview);
624 drawSwRT(cmd, *wview);
626 prepareIrradiance(cmd,*wview);
627 prepareExposure(cmd,*wview);
628 prepareSSAO(cmd,*wview);
629 prepareFog (cmd,*wview);
630 prepareGi (cmd,*wview);
632 cmd.setFramebuffer({{sceneLinear, Tempest::Discard, Tempest::Preserve}}, {zbuffer, Tempest::Readonly});
633 drawShadowResolve(cmd,*wview);
634 drawAmbient(cmd,*wview);
635 drawLights(cmd,*wview);
640 drawGWater(cmd, *wview);
642 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}}, {zbuffer, Tempest::Preserve, Tempest::Preserve});
643 cmd.setDebugMarker(
"Sun&Moon");
644 drawSunMoon(cmd, *wview);
645 cmd.setDebugMarker(
"Translucent");
648 drawProbesDbg(cmd, *wview);
649 drawProbesHitDbg(cmd);
650 drawVsmDbg(cmd, *wview);
651 drawSwrDbg(cmd, *wview);
652 drawRtsmDbg(cmd, *wview);
654 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}});
655 drawReflections(cmd, *wview);
657 cmd.setDebugMarker(
"Underwater");
658 drawUnderwater(cmd, *wview);
660 cmd.setDebugMarker(
"Fog");
661 drawFog(cmd, *wview);
664 if(settings.aaEnabled) {
665 cmd.setDebugMarker(
"CMAA2 & Tonemapping");
666 drawCMAA2(result, cmd, *wview);
668 cmd.setDebugMarker(
"Tonemapping");
669 drawTonemapping(result, cmd, *wview);
675void Renderer::drawTonemapping(Attachment& result, Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
677 float brightness = 0;
679 float gamma = 1.f/2.2f;
684 p.brightness = (settings.zVidBrightness - 0.5f)*0.1f;
685 p.contrast = std::max(1.5f - settings.zVidContrast, 0.01f);
686 p.gamma = p.gamma/std::max(2.0f*settings.zVidGamma, 0.01f);
688 static float mul = 0.f;
692 auto& pso = (settings.vidResIndex==0) ? shaders.
tonemapping : shaders.tonemappingUpscale;
693 cmd.setFramebuffer({ {result, Tempest::Discard, Tempest::Preserve} });
695 cmd.setBinding(1, sceneLinear, Sampler::nearest(ClampMode::ClampToEdge));
697 cmd.setPipeline(pso);
698 cmd.draw(
nullptr, 0, 3);
701void Renderer::drawCMAA2(Tempest::Attachment& result, Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
703 const IVec3 inputGroupSize = pso.workGroupSize();
704 const IVec3 outputGroupSize = inputGroupSize - IVec3(2, 2, 0);
705 const uint32_t groupCountX = uint32_t((sceneLinear.w() + outputGroupSize.x * 2 - 1) / (outputGroupSize.x * 2));
706 const uint32_t groupCountY = uint32_t((sceneLinear.h() + outputGroupSize.y * 2 - 1) / (outputGroupSize.y * 2));
708 cmd.setFramebuffer({});
709 cmd.setBinding(0, sceneLinear, Sampler::bilinear(ClampMode::ClampToEdge));
710 cmd.setBinding(1, cmaa2.workingEdges);
711 cmd.setBinding(2, cmaa2.shapeCandidates);
712 cmd.setBinding(3, cmaa2.deferredBlendLocationList);
713 cmd.setBinding(4, cmaa2.deferredBlendItemList);
714 cmd.setBinding(5, cmaa2.deferredBlendItemListHeads);
715 cmd.setBinding(6, cmaa2.controlBuffer);
716 cmd.setBinding(7, cmaa2.indirectBuffer);
719 cmd.setPipeline(pso);
720 cmd.dispatch(groupCountX, groupCountY, 1);
724 cmd.dispatchIndirect(cmaa2.indirectBuffer, 0);
728 float brightness = 0;
730 float gamma = 1.f/2.2f;
735 p.brightness = (settings.zVidBrightness - 0.5f)*0.1f;
736 p.contrast = std::max(1.5f - settings.zVidContrast, 0.01f);
737 p.gamma = p.gamma/std::max(2.0f*settings.zVidGamma, 0.01f);
739 static float mul = 0.f;
743 auto& psoTone = (settings.vidResIndex==0) ? shaders.
tonemapping : shaders.tonemappingUpscale;
744 cmd.setFramebuffer({{result, Tempest::Discard, Tempest::Preserve}});
746 cmd.setBinding(1, sceneLinear, Sampler::nearest());
747 cmd.setPushData(&p,
sizeof(p));
748 cmd.setPipeline(psoTone);
749 cmd.draw(
nullptr, 0, 3);
751 cmd.setBinding(0, sceneLinear);
752 cmd.setBinding(1, cmaa2.workingEdges);
753 cmd.setBinding(2, cmaa2.shapeCandidates);
754 cmd.setBinding(3, cmaa2.deferredBlendLocationList);
755 cmd.setBinding(4, cmaa2.deferredBlendItemList);
756 cmd.setBinding(5, cmaa2.deferredBlendItemListHeads);
757 cmd.setBinding(6, cmaa2.controlBuffer);
758 cmd.setPushData(&p,
sizeof(p));
760 cmd.drawIndirect(cmaa2.indirectBuffer, 3*
sizeof(uint32_t));
763void Renderer::drawFog(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
766 switch(sky.quality) {
769 cmd.setBinding(0, sky.fogLut3D, Sampler::bilinear(ClampMode::ClampToEdge));
770 cmd.setBinding(1, sky.fogLut3D, Sampler::bilinear(ClampMode::ClampToEdge));
771 cmd.setBinding(2, zbuffer, Sampler::nearest());
773 cmd.setPipeline(shaders.
fog);
777 cmd.setBinding(0, sky.fogLut3D, Sampler::bilinear(ClampMode::ClampToEdge));
778 cmd.setBinding(1, sky.fogLut3DMs, Sampler::bilinear(ClampMode::ClampToEdge));
779 cmd.setBinding(2, zbuffer, Sampler::nearest());
781 cmd.setBinding(4, sky.occlusionLut);
782 cmd.setPipeline(shaders.
fog3dHQ);
788 cmd.setBinding(1, zbuffer, Sampler::nearest());
789 cmd.setBinding(2, vsm.fogDbg, Sampler::bilinear(ClampMode::ClampToEdge));
790 cmd.setBinding(3, epipolar.epipoles);
791 cmd.setBinding(4, sky.fogLut3DMs, Sampler::bilinear(ClampMode::ClampToEdge));
792 cmd.setPipeline(shaders.
vsmFog);
798 cmd.draw(
nullptr, 0, 3);
801void Renderer::drawSunMoon(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
802 drawSunMoon(cmd, wview,
false);
803 drawSunMoon(cmd, wview,
true);
806void Renderer::drawSunMoon(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview,
bool isSun) {
809 auto m = scene.viewProject();
814 d = Vec3::normalize({-1,1,0});
819 m.project(dx.x, dx.y, dx.z, w);
827 Tempest::Vec3 sunDir;
828 float GSunIntensity = 0;
829 Tempest::Matrix4x4 viewProjectInv;
832 push.pos = Vec2(dx.x,dx.y)/dx.z;
833 push.size.x = 2.f/float(zbuffer.w());
834 push.size.y = 2.f/float(zbuffer.h());
839 const float scale = internalResolutionScale();
840 const float sunSize = settings.sunSize * scale;
841 const float moonSize = settings.moonSize * scale;
842 const float intencity = isSun ? 0.07f : 0.4f;
844 push.size *= isSun ? sunSize : (moonSize*0.25f);
845 push.GSunIntensity = isSun ? (GSunIntensity*intencity) : (GMoonIntensity*intencity);
846 push.isSun = isSun ? 1 : 0;
848 push.viewProjectInv = scene.viewProjectLwcInv();
852 float day = sun.dir().y;
854 push.GSunIntensity *= stp*stp*4.f;
861 cmd.setBinding(1, isSun ? wview.
sky().
sunImage() : wview.sky().moonImage());
862 cmd.setBinding(2, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
863 cmd.setPushData(push);
864 cmd.setPipeline(shaders.
sun);
865 cmd.draw(
nullptr, 0, 6);
868void Renderer::drawSwRT(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
869 if(!settings.swrtEnabled)
874 const auto originLwc = scene.originLwc;
876 if(swrt.outputImage.size()!=zbuffer.size()) {
880 swrt.outputImage = device.image2d(TextureFormat::RGBA8, zbuffer.size());
883 cmd.setFramebuffer({});
884 cmd.setDebugMarker(
"Raytracing");
887 cmd.setPushData(&originLwc,
sizeof(originLwc));
888 cmd.setBinding(0, swrt.outputImage);
890 cmd.setBinding(2, gbufDiffuse);
891 cmd.setBinding(3, gbufNormal);
892 cmd.setBinding(4, zbuffer);
893 cmd.setBinding(5, bvh);
895 cmd.dispatchThreads(swrt.outputImage.size());
898void Renderer::stashSceneAux(Encoder<CommandBuffer>& cmd) {
900 if(!device.properties().hasSamplerFormat(zBufferFormat))
902 cmd.setFramebuffer({{sceneOpaque, Tempest::Discard, Tempest::Preserve}, {sceneDepth, Tempest::Discard, Tempest::Preserve}});
903 cmd.setDebugMarker(
"Stash scene");
904 cmd.setBinding(0, sceneLinear,Sampler::nearest());
905 cmd.setBinding(1, zbuffer, Sampler::nearest());
906 cmd.setPipeline(shaders.
stash);
907 cmd.draw(
nullptr, 0, 3);
910void Renderer::drawVsmDbg(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
911 static bool enable =
false;
912 if(!enable || !settings.vsmEnabled)
915 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}});
916 cmd.setDebugMarker(
"VSM-dbg");
918 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
919 cmd.setBinding(2, gbufNormal, Sampler::nearest());
920 cmd.setBinding(3, zbuffer, Sampler::nearest());
921 cmd.setBinding(4, vsm.pageTbl);
922 cmd.setBinding(5, vsm.pageList);
923 cmd.setBinding(6, vsm.pageData);
925 cmd.setPushData(&settings.vsmMipBias,
sizeof(settings.vsmMipBias));
926 cmd.setPipeline(shaders.
vsmDbg);
927 cmd.draw(
nullptr, 0, 3);
930void Renderer::drawSwrDbg(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
931 static bool enable =
true;
932 if(!enable || !settings.swrEnabled)
935 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}});
936 cmd.setDebugMarker(
"SWR-dbg");
937 cmd.setBinding(0, swr.outputImage);
939 cmd.setBinding(2, gbufDiffuse, Sampler::nearest());
940 cmd.setBinding(3, gbufNormal, Sampler::nearest());
941 cmd.setBinding(4, zbuffer, Sampler::nearest());
943 cmd.draw(
nullptr, 0, 3);
946void Renderer::drawRtsmDbg(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
const WorldView& wview) {
947 static bool enable =
false;
948 if(!enable || !settings.rtsmEnabled)
951 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve}});
952 cmd.setDebugMarker(
"RTSM-dbg");
954 cmd.setBinding(0, rtsm.dbg32);
956 cmd.setBinding(0, rtsm.primBins);
957 cmd.setBinding(1, rtsm.posList);
958 cmd.setBinding(2, rtsm.pages);
960 cmd.setPipeline(shaders.
rtsmDbg);
961 cmd.draw(
nullptr, 0, 3);
964void Renderer::resetGiData() {
965 if(!settings.giEnabled)
967 if(!gi.hashTable.isEmpty())
973 gi.hashTable = device.ssbo(
nullptr, 2'097'152*
sizeof(uint32_t));
974 gi.voteTable = device.ssbo(
nullptr, gi.hashTable.byteSize());
975 gi.probes = device.ssbo(
nullptr,
maxProbes*32 + 64);
976 gi.freeList = device.ssbo(
nullptr,
maxProbes*
sizeof(uint32_t) +
sizeof(int32_t));
977 gi.probesGBuffDiff = device.image2d(TextureFormat::RGBA8, gi.atlasDim*16, gi.atlasDim*16);
978 gi.probesGBuffNorm = device.image2d(TextureFormat::RGBA8, gi.atlasDim*16, gi.atlasDim*16);
979 gi.probesGBuffRayT = device.image2d(TextureFormat::R16, gi.atlasDim*16, gi.atlasDim*16);
980 gi.probesLighting = device.image2d(TextureFormat::R11G11B10UF, gi.atlasDim*3, gi.atlasDim*2);
981 gi.probesLightingPrev = device.image2d(TextureFormat::R11G11B10UF, uint32_t(gi.probesLighting.w()), uint32_t(gi.probesLighting.h()));
982 gi.fisrtFrame =
true;
985void Renderer::drawHiZ(Encoder<CommandBuffer>& cmd,
WorldView& view) {
986 cmd.setDebugMarker(
"HiZ-occluders");
987 cmd.setFramebuffer({}, {zbuffer, 1.f, Tempest::Preserve});
991void Renderer::buildHiZ(Tempest::Encoder<Tempest::CommandBuffer>& cmd) {
992 assert(hiz.hiZ.w()<=128 && hiz.hiZ.h()<=128);
994 cmd.setDebugMarker(
"HiZ-mip");
995 cmd.setFramebuffer({});
996 cmd.setBinding(0, zbuffer, Sampler::nearest(ClampMode::ClampToEdge));
997 cmd.setBinding(1, hiz.hiZ);
998 cmd.setPipeline(shaders.
hiZPot);
999 cmd.dispatch(
size_t(hiz.hiZ.w()),
size_t(hiz.hiZ.h()));
1001 const uint32_t maxBind = 8, mip = hiz.hiZ.mipCount();
1002 const uint32_t w = uint32_t(hiz.hiZ.w()), h = uint32_t(hiz.hiZ.h());
1004 cmd.setBinding(0, hiz.counter, Sampler::nearest(), 0);
1006 cmd.setBinding(0, hiz.counterBuf);
1008 for(uint32_t i=0; i<maxBind; ++i)
1009 cmd.setBinding(1+i, hiz.hiZ, Sampler::nearest(), std::min(i, mip-1));
1010 cmd.setPushData(&mip,
sizeof(mip));
1011 cmd.setPipeline(shaders.
hiZMip);
1012 cmd.dispatchThreads(w,h);
1015void Renderer::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1016 if(!settings.vsmEnabled)
1019 static bool omniLights =
true;
1020 const bool directLight = !settings.rtsmEnabled;
1021 const bool doVirtualFog = directLight && sky.quality!=VolumetricLQ && sky.quality!=PathTrace;
1027 auto&
vsmDbg = usesImage2d(vsm.vsmDbg, TextureFormat::R32U, zbuffer.size());
1028 auto&
pageTbl = usesImage3d(vsm.pageTbl, TextureFormat::R32U, 32, 32, 16);
1029 auto&
pageHiZ = usesImage3d(vsm.pageHiZ, TextureFormat::R32U, 32, 32, 16);
1030 auto&
pageData = usesZBuffer(vsm.pageData, shadowFormat, 8192, 8192);
1032 auto pageCount = uint32_t(vsm.pageData.w()/VSM_PAGE_SIZE) * uint32_t(vsm.pageData.h()/VSM_PAGE_SIZE);
1033 auto&
pageList = usesSsbo(vsm.pageList, shaders.
vsmClear.sizeofBuffer(0, pageCount));
1036 const uint32_t lightsTotal = omniLights ? uint32_t(wview.
lights().
size()) : 0;
1037 const size_t numOmniPages = lightsTotal*6;
1043 cmd.setFramebuffer({});
1044 cmd.setDebugMarker(
"VSM-pages");
1055 cmd.dispatchThreads(numOmniPages);
1057 struct Push {
float znear; uint32_t lightsTotal; } push = {};
1058 push.znear = scene.znear;
1059 push.lightsTotal = lightsTotal;
1060 cmd.setBinding(0, sceneUbo);
1061 cmd.setBinding(1, lightsSsbo);
1063 cmd.setBinding(3, *scene.hiZ);
1064 cmd.setPushData(push);
1070 cmd.setBinding(0, sceneUbo);
1071 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1072 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1073 cmd.setBinding(3, zbuffer, Sampler::nearest());
1076 cmd.setPushData(settings.vsmMipBias);
1078 cmd.dispatchThreads(zbuffer.size());
1082 struct Push { Vec3 originLwc;
float znear;
float vsmMipBias; } push = {};
1083 push.originLwc = scene.originLwc;
1084 push.znear = scene.znear;
1085 push.vsmMipBias = settings.vsmMipBias;
1086 cmd.setBinding(0, sceneUbo);
1087 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1088 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1089 cmd.setBinding(3, zbuffer, Sampler::nearest());
1090 cmd.setBinding(4, lightsSsbo);
1093 cmd.setBinding(7,
vsmDbg);
1094 cmd.setPushData(&push,
sizeof(push));
1096 cmd.dispatchThreads(zbuffer.size());
1099 cmd.setPushData(&lightsTotal,
sizeof(lightsTotal));
1106 cmd.setDebugMarker(
"VSM-pages-epipolar");
1107 cmd.setBinding(0, epipolar.epTrace);
1108 cmd.setBinding(1, sceneUbo);
1109 cmd.setBinding(2, epipolar.epipoles);
1113 cmd.dispatchThreads(epipolar.epTrace.size());
1116 cmd.setDebugMarker(
"VSM-pages-alloc");
1129 cmd.setBinding(4, scene.vsmDbg);
1133 cmd.dispatch(
size_t(
pageTbl.d() + 1));
else
1134 cmd.dispatch(
size_t(
pageTbl.d()));
1143 cmd.setDebugMarker(
"VSM-visibility");
1146 cmd.setDebugMarker(
"VSM-rendering");
1147 cmd.setFramebuffer({}, {
pageData, 0.f, Tempest::Preserve});
1151void Renderer::drawRtsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1152 if(!settings.rtsmEnabled)
1155 const int RTSM_BIN_SIZE = 32;
1156 const int RTSM_SMALL_TILE = 32;
1157 const int RTSM_LARGE_TILE = 128;
1161 const auto& clusters = wview.
clusters();
1167 const auto largeTiles =
tileCount(scene.zbuffer->size(), RTSM_LARGE_TILE);
1168 const auto smallTiles =
tileCount(scene.zbuffer->size(), RTSM_SMALL_TILE);
1169 const auto binTiles =
tileCount(scene.zbuffer->size(), RTSM_BIN_SIZE);
1170 const auto maxMeshlets = drawCmd.maxMeshlets();
1173 auto&
posList = usesScratch(rtsm.posList, 64*1024*1024);
1174 auto&
outputImage = usesImage2d(rtsm.outputImage, TextureFormat::R8, zbuffer.size());
1175 auto&
pages = usesImage3d(rtsm.pages, TextureFormat::R32U, 32, 32, 16);
1176 auto&
meshTiles = usesImage2d(rtsm.meshTiles, TextureFormat::RG32U, smallTiles);
1177 auto&
primTiles = usesImage2d(rtsm.primTiles, TextureFormat::RG32U, binTiles);
1178 auto&
visList = usesSsbo (rtsm.visList, shaders.
rtsmClear.sizeofBuffer(1, maxMeshlets));
1180 auto&
dbg32 = usesImage2d(rtsm.dbg32, TextureFormat::R32U,
tileCount(zbuffer.size(), 32));
1181 auto&
dbg16 = usesImage2d(rtsm.dbg16, TextureFormat::R32U,
tileCount(zbuffer.size(), 16));
1183 cmd.setDebugMarker(
"RTSM-rendering");
1184 cmd.setFramebuffer({});
1188 cmd.setBinding(0,
pages);
1193 cmd.dispatchThreads(
size_t(
pages.w()),
size_t(
pages.h()),
size_t(
pages.d()));
1198 struct Push { uint32_t meshletCount; } push = {};
1199 push.meshletCount = uint32_t(clusters.size());
1200 cmd.setPushData(push);
1202 if(sky.quality==VolumetricHQ) {
1203 cmd.setBinding(0, epipolar.epTrace);
1204 cmd.setBinding(1, sceneUbo);
1205 cmd.setBinding(2, epipolar.epipoles);
1206 cmd.setBinding(3,
pages);
1208 cmd.dispatchThreads(epipolar.epTrace.size());
1212 cmd.setBinding(1, sceneUbo);
1213 cmd.setBinding(2, gbufDiffuse);
1214 cmd.setBinding(3, gbufNormal);
1215 cmd.setBinding(4, zbuffer);
1216 cmd.setBinding(5, clusters.ssbo());
1218 cmd.setBinding(7,
pages);
1221 cmd.dispatchThreads(scene.zbuffer->size());
1223 cmd.setBinding(0,
pages);
1224 cmd.setPipeline(shaders.
rtsmHiZ);
1229 cmd.dispatchThreads(push.meshletCount);
1234 struct Push { Vec3 originLwc; } push = {};
1235 push.originLwc = scene.originLwc;
1237 cmd.setPushData(push);
1239 cmd.setBinding(1, sceneUbo);
1242 cmd.setBinding(5, clusters.ssbo());
1243 cmd.setBinding(6, instanceSsbo);
1244 cmd.setBinding(7, buckets.ssbo());
1245 cmd.setBinding(8, buckets.ibo());
1246 cmd.setBinding(9, buckets.vbo());
1247 cmd.setBinding(10, buckets.morphId());
1248 cmd.setBinding(11, buckets.morph());
1251 cmd.dispatchIndirect(
visList,0);
1257 cmd.setBinding(1, sceneUbo);
1258 cmd.setBinding(2, gbufNormal);
1259 cmd.setBinding(3, zbuffer);
1263 cmd.setBinding(9,
dbg32);
1267 cmd.dispatch(largeTiles);
1271 cmd.dispatch(smallTiles);
1277 cmd.setBinding(1, sceneUbo);
1278 cmd.setBinding(2, gbufNormal);
1279 cmd.setBinding(3, zbuffer);
1283 cmd.setBinding(7, buckets.textures());
1284 cmd.setBinding(8, Sampler::trillinear());
1285 cmd.setBinding(9,
dbg16);
1292void Renderer::drawRtsmOmni(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1293 if(!settings.rtsmEnabled)
1296 static bool omniLights =
true;
1301 const uint32_t RTSM_LIGHT_TILE = 64;
1306 const auto& clusters = wview.
clusters();
1311 const auto maxMeshlets = drawCmd.maxMeshlets();
1312 const auto lightsTotal = uint32_t(wview.
lights().
size());
1315 auto&
posList = usesScratch(rtsm.posList, 64*1024*1024);
1316 auto&
outputImageClr = usesImage2d(rtsm.outputImageClr, TextureFormat::R11G11B10UF, zbuffer.size());
1317 auto&
lightTiles = usesImage2d(rtsm.lightTiles, TextureFormat::RG32U,
tileCount(scene.zbuffer->size(), RTSM_LIGHT_TILE));
1318 auto&
lightBins = usesImage2d(rtsm.lightBins, TextureFormat::RG32U, lightsTotal, 1u);
1319 auto&
primTilesOmni = usesImage2d(rtsm.primTilesOmni, TextureFormat::R32U,
tileCount(zbuffer.size(), RTSM_LIGHT_TILE));
1320 auto&
drawTasks = usesSsbo (rtsm.drawTasks, 4*
sizeof(uint32_t));
1324 auto&
dbg64 = usesImage2d(rtsm.dbg64, TextureFormat::R32U,
tileCount(zbuffer.size(), 64));
1325 auto&
dbg16 = usesImage2d(rtsm.dbg16, TextureFormat::R32U,
tileCount(zbuffer.size(), 16));
1327 cmd.setDebugMarker(
"RTSM-rendering-omni");
1328 cmd.setFramebuffer({});
1331 struct Push { uint32_t meshletCount; } push = {};
1332 push.meshletCount = uint32_t(clusters.size());
1334 cmd.setPushData(push);
1339 cmd.dispatchThreads(1);
1344 struct Push {
float znear; uint32_t lightsTotal; } push = {};
1345 push.znear = scene.znear;
1346 push.lightsTotal = lightsTotal;
1348 cmd.setPushData(push);
1349 cmd.setBinding(0, sceneUbo);
1350 cmd.setBinding(1, lightsSsbo);
1353 cmd.setBinding(4, hiz.hiZ);
1354 cmd.setBinding(5, clusters.ssbo());
1358 cmd.dispatchThreads(lightsTotal);
1363 struct Push { Vec3 originLwc;
float znear; } push = {};
1364 push.originLwc = scene.originLwc;
1365 push.znear = scene.znear;
1367 cmd.setPushData(push);
1369 cmd.setBinding(1, sceneUbo);
1370 cmd.setBinding(2, gbufNormal);
1371 cmd.setBinding(3, zbuffer);
1373 cmd.setBinding(5, lightsSsbo);
1376 cmd.setBinding(9, rtsm.dbg64);
1382 cmd.dispatchThreads(zbuffer.size());
1388 cmd.dispatchThreads(lightsTotal);
1393 struct Push {
float znear; uint32_t meshletCount; } push = {};
1394 push.znear = scene.znear;
1395 push.meshletCount = uint32_t(clusters.size());
1397 cmd.setPushData(push);
1399 cmd.setBinding(1, sceneUbo);
1400 cmd.setBinding(2, rtsm.visList);
1401 cmd.setBinding(3, lightsSsbo);
1403 cmd.setBinding(5, clusters.ssbo());
1406 cmd.dispatchThreads(push.meshletCount);
1411 struct Push { Vec3 originLwc; } push = {};
1412 push.originLwc = scene.originLwc;
1414 cmd.setPushData(push);
1416 cmd.setBinding(1, sceneUbo);
1419 cmd.setBinding(5, clusters.ssbo());
1420 cmd.setBinding(6, instanceSsbo);
1421 cmd.setBinding(7, buckets.ssbo());
1422 cmd.setBinding(8, buckets.ibo());
1423 cmd.setBinding(9, buckets.vbo());
1424 cmd.setBinding(10, buckets.morphId());
1425 cmd.setBinding(11, buckets.morph());
1428 cmd.dispatchIndirect(
visList, 0);
1433 struct Push { Vec3 originLwc;
float znear; } push = {};
1434 push.originLwc = scene.originLwc;
1435 push.znear = scene.znear;
1437 cmd.setBinding(0, sceneUbo);
1438 cmd.setBinding(1, lightsSsbo);
1441 cmd.setBinding(4, clusters.ssbo());
1453 struct Push { Vec3 originLwc;
float znear; } push = {};
1454 push.originLwc = scene.originLwc;
1455 push.znear = scene.znear;
1456 cmd.setPushData(push);
1458 cmd.setBinding(1, sceneUbo);
1459 cmd.setBinding(2, gbufNormal);
1460 cmd.setBinding(3, zbuffer);
1462 cmd.setBinding(5, lightsSsbo);
1466 cmd.setBinding(9,
dbg64);
1477 struct Push { Vec3 originLwc; } push = {};
1478 push.originLwc = scene.originLwc;
1480 cmd.setPushData(push);
1482 cmd.setBinding(1, sceneUbo);
1483 cmd.setBinding(2, gbufNormal);
1484 cmd.setBinding(3, zbuffer);
1486 cmd.setBinding(5, lightsSsbo);
1488 cmd.setBinding(7, buckets.textures());
1489 cmd.setBinding(8, Sampler::trillinear());
1490 cmd.setBinding(9,
dbg16);
1499 struct Push { Vec3 originLwc; } push = {};
1500 push.originLwc = scene.originLwc;
1501 cmd.setPushData(push);
1503 cmd.setBinding(1, sceneUbo);
1504 cmd.setBinding(2, gbufNormal);
1505 cmd.setBinding(3, zbuffer);
1507 cmd.setBinding(5, lightsSsbo);
1510 cmd.setBinding(9,
dbg16);
1517void Renderer::drawSwr(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1518 if(!settings.swrEnabled)
1522 const auto& clusters = wview.
clusters();
1526 auto&
outputImage = usesImage2d(swr.outputImage, TextureFormat::R32U, zbuffer.size());
1528 cmd.setFramebuffer({});
1529 cmd.setDebugMarker(
"SW-rendering");
1531 struct Push { uint32_t firstMeshlet; uint32_t meshletCount;
float znear; } push = {};
1532 push.firstMeshlet = 0;
1533 push.meshletCount = uint32_t(clusters.size());
1534 push.znear = scene.znear;
1538 cmd.setBinding(2, *scene.gbufNormals);
1539 cmd.setBinding(3, *scene.zbuffer);
1540 cmd.setBinding(4, clusters.ssbo());
1541 cmd.setBinding(5, buckets.ibo());
1542 cmd.setBinding(6, buckets.vbo());
1543 cmd.setBinding(7, buckets.textures());
1544 cmd.setBinding(8, Sampler::bilinear());
1549 cmd.setPushData(&push,
sizeof(push));
1550 cmd.setPipeline(*pso);
1552 cmd.dispatch(clusters.size());
1556 IVec2 tileSize = IVec2(128);
1557 int tileX = (
outputImage.w()+tileSize.x-1)/tileSize.x;
1558 int tileY = (
outputImage.h()+tileSize.y-1)/tileSize.y;
1559 cmd.setPushData(&push,
sizeof(push));
1560 cmd.setPipeline(*pso);
1561 cmd.dispatch(
size_t(tileX),
size_t(tileY));
1565 cmd.setBinding(9, *scene.lights);
1566 cmd.setBinding(10, instanceSsbo);
1567 cmd.setPushData(&push,
sizeof(push));
1568 cmd.setPipeline(*pso);
1575void Renderer::drawGBuffer(Encoder<CommandBuffer>& cmd, uint8_t fId,
WorldView& view) {
1576 cmd.setDebugMarker(
"GBuffer");
1577 cmd.setFramebuffer({{gbufDiffuse, Tempest::Vec4(), Tempest::Preserve},
1578 {gbufNormal, Tempest::Vec4(), Tempest::Preserve}},
1579 {zbuffer, Tempest::Preserve, Tempest::Preserve});
1583void Renderer::drawGWater(Encoder<CommandBuffer>& cmd,
WorldView& view) {
1584 static bool water =
true;
1588 cmd.setFramebuffer({{sceneLinear, Tempest::Preserve, Tempest::Preserve},
1589 {gbufDiffuse, Vec4(0,0,0,0), Tempest::Preserve},
1590 {gbufNormal, Vec4(0,0,0,0), Tempest::Preserve}},
1591 {zbuffer, Tempest::Preserve, Tempest::Preserve});
1594 cmd.setDebugMarker(
"GWater");
1598void Renderer::drawReflections(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
1601 cmd.setDebugMarker(
"Reflections");
1603 cmd.setBinding(1, sceneOpaque, Sampler::bilinear(ClampMode::ClampToEdge));
1604 cmd.setBinding(2, gbufDiffuse, Sampler::nearest (ClampMode::ClampToEdge));
1605 cmd.setBinding(3, gbufNormal, Sampler::nearest (ClampMode::ClampToEdge));
1606 cmd.setBinding(4, zbuffer, Sampler::nearest (ClampMode::ClampToEdge));
1607 cmd.setBinding(5, sceneDepth, Sampler::nearest (ClampMode::ClampToEdge));
1608 cmd.setBinding(6, sky.viewCldLut);
1609 cmd.setPipeline(pso);
1611 cmd.dispatchMeshThreads(gbufDiffuse.size());
1613 cmd.draw(
nullptr, 0, 3);
1617void Renderer::drawUnderwater(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
1619 cmd.setBinding(1, zbuffer);
1622 cmd.draw(
nullptr, 0, 3);
1624 cmd.draw(
nullptr, 0, 3);
1627void Renderer::drawShadowMap(Encoder<CommandBuffer>& cmd, uint8_t fId,
WorldView& view) {
1629 if(shadowMap[i].isEmpty())
1631 cmd.setDebugMarker(
string_frm(
"ShadowMap #",i));
1632 cmd.setFramebuffer({}, {shadowMap[i], 0.f, Tempest::Preserve});
1638void Renderer::drawShadowResolve(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
1639 static bool light =
true;
1644 cmd.setDebugMarker(settings.vsmEnabled ?
"DirectSunLight-VSM" :
"DirectSunLight");
1647 cmd.setPushData(&originLwc,
sizeof(originLwc));
1649 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1650 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1651 cmd.setBinding(3, zbuffer, Sampler::nearest());
1653 cmd.setBinding(4, vsm.pageTbl);
1654 cmd.setBinding(5, vsm.pageList);
1655 cmd.setBinding(6, vsm.pageData);
1656 cmd.setBinding(8, scene.vsmDbg);
1660 if(shadowMap[r].isEmpty())
1664 cmd.setBinding(6, scene.rtScene.tlas);
1665 cmd.setBinding(7, Sampler::bilinear());
1666 cmd.setBinding(8, scene.rtScene.tex);
1667 cmd.setBinding(9, scene.rtScene.vbo);
1668 cmd.setBinding(10,scene.rtScene.ibo);
1669 cmd.setBinding(11,scene.rtScene.rtDesc);
1672 cmd.setBinding(4, rtsm.outputImage);
1677 if(shadowMap[r].isEmpty())
1683 cmd.setPipeline(*shadow.directLightPso);
1684 if(settings.vsmEnabled) {
1685 cmd.setPushData(settings.vsmMipBias);
1686 cmd.setPipeline(*shadow.directLightPso);
1688 cmd.draw(
nullptr, 0, 3);
1691void Renderer::drawLights(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
1692 static bool light =
true;
1696 if(settings.rtsmEnabled && !rtsm.outputImageClr.isEmpty())
1700 cmd.setDebugMarker(
"Point lights");
1703 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1704 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1705 cmd.setBinding(3, zbuffer, Sampler::nearest());
1707 if(lights.directLightPso==&shaders.
lightsVsm) {
1708 cmd.setBinding(5, vsm.pageTblOmni);
1709 cmd.setBinding(6, vsm.pageData);
1711 if(lights.directLightPso==&shaders.
lightsRq) {
1712 cmd.setBinding(6, scene.rtScene.tlas);
1713 cmd.setBinding(7, Sampler::bilinear());
1714 cmd.setBinding(8, scene.rtScene.tex);
1715 cmd.setBinding(9, scene.rtScene.vbo);
1716 cmd.setBinding(10,scene.rtScene.ibo);
1717 cmd.setBinding(11,scene.rtScene.rtDesc);
1722 cmd.setPushData(&originLwc,
sizeof(originLwc));
1723 cmd.setPipeline(*lights.directLightPso);
1724 cmd.draw(
nullptr,ibo, 0,ibo.size(), 0,wview.
lights().
size());
1727void Renderer::drawSky(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
1730 cmd.setDebugMarker(
"Sky");
1731 if(sky.quality==PathTrace) {
1733 cmd.setBinding(1, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
1734 cmd.setBinding(2, sky.multiScatLut, Sampler::bilinear(ClampMode::ClampToEdge));
1735 cmd.setBinding(3, sky.cloudsLut, Sampler::bilinear(ClampMode::ClampToEdge));
1736 cmd.setBinding(4, zbuffer, Sampler::nearest());
1739 cmd.draw(
nullptr, 0, 3);
1743 auto& skyShader = sky.quality==VolumetricLQ ? shaders.
sky : shaders.
skySep;
1745 cmd.setBinding(1, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
1746 cmd.setBinding(2, sky.multiScatLut, Sampler::bilinear(ClampMode::ClampToEdge));
1747 cmd.setBinding(3, sky.viewLut, Sampler::bilinear(ClampMode::ClampToEdge));
1748 cmd.setBinding(4, sky.fogLut3D);
1749 if(sky.quality!=VolumetricLQ)
1750 cmd.setBinding(5, sky.fogLut3DMs, Sampler::bilinear(ClampMode::ClampToEdge));
1751 cmd.setBinding(6, *wview.
sky().
cloudsDay() .
lay[0], Sampler::trillinear());
1752 cmd.setBinding(7, *wview.
sky().
cloudsDay() .
lay[1], Sampler::trillinear());
1755 cmd.setPipeline(skyShader);
1756 cmd.draw(
nullptr, 0, 3);
1759void Renderer::prepareSSAO(Encoder<CommandBuffer>& cmd,
WorldView& wview) {
1760 if(!settings.zCloudShadowScale)
1768 push.projInv = proj;
1769 push.projInv.inverse();
1771 cmd.setFramebuffer({});
1772 cmd.setDebugMarker(
"SSAO");
1774 cmd.setBinding(0, ssao.ssaoBuf);
1776 cmd.setBinding(2, gbufDiffuse, Sampler::nearest(ClampMode::ClampToEdge));
1777 cmd.setBinding(3, gbufNormal, Sampler::nearest(ClampMode::ClampToEdge));
1778 cmd.setBinding(4, zbuffer, Sampler::nearest(ClampMode::ClampToEdge));
1779 cmd.setPushData(&push,
sizeof(push));
1780 cmd.setPipeline(shaders.
ssao);
1781 cmd.dispatchThreads(ssao.ssaoBuf.size());
1783 cmd.setBinding(0, ssao.ssaoBlur);
1785 cmd.setBinding(2, ssao.ssaoBuf);
1786 cmd.setBinding(3, zbuffer, Sampler::nearest(ClampMode::ClampToEdge));
1788 cmd.dispatchThreads(ssao.ssaoBuf.size());
1791void Renderer::prepareFog(Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1795 cmd.setDebugMarker(
"Fog-LUTs");
1796 if(sky.quality!=PathTrace) {
1798 cmd.setFramebuffer({});
1800 cmd.setBinding(1, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
1801 cmd.setBinding(2, sky.multiScatLut, Sampler::bilinear(ClampMode::ClampToEdge));
1802 cmd.setBinding(3, sky.cloudsLut, Sampler::bilinear(ClampMode::ClampToEdge));
1803 cmd.setBinding(4, sky.fogLut3D);
1804 if(sky.quality==VolumetricHQ || sky.quality==Epipolar)
1805 cmd.setBinding(5, sky.fogLut3DMs, Sampler::bilinear(ClampMode::ClampToEdge));
1806 cmd.setPipeline(shader);
1807 cmd.dispatchThreads(uint32_t(sky.fogLut3D.w()), uint32_t(sky.fogLut3D.h()));
1810 if(settings.vsmEnabled && (sky.quality==VolumetricHQ || sky.quality==Epipolar)) {
1811 cmd.setFramebuffer({});
1812 cmd.setDebugMarker(
"VSM-epipolar-fog");
1813 cmd.setBinding(0, epipolar.epTrace);
1815 cmd.setBinding(2, epipolar.epipoles);
1816 cmd.setBinding(3, vsm.pageTbl);
1817 cmd.setBinding(4, vsm.pageData);
1819 cmd.dispatchThreads(epipolar.epTrace.size());
1822 switch(sky.quality) {
1826 case VolumetricHQ: {
1827 if(settings.vsmEnabled && !settings.rtsmEnabled) {
1828 cmd.setFramebuffer({});
1829 cmd.setBinding(0, sky.occlusionLut);
1830 cmd.setBinding(1, epipolar.epTrace);
1832 cmd.setBinding(3, epipolar.epipoles);
1833 cmd.setBinding(4, zbuffer);
1835 cmd.dispatchThreads(zbuffer.size());
1837 cmd.setFramebuffer({});
1838 cmd.setBinding(2, zbuffer, Sampler::nearest());
1840 cmd.setBinding(4, sky.occlusionLut);
1843 cmd.dispatchThreads(sky.occlusionLut.size());
1849 if(vsm.fogDbg.isEmpty())
1850 vsm.fogDbg = device.image2d(sky.lutRGBFormat, 1024, 2*1024);
1851 cmd.setFramebuffer({});
1852 cmd.setDebugMarker(
"VSM-trace");
1853 cmd.setBinding(0, vsm.fogDbg);
1854 cmd.setBinding(1, epipolar.epTrace);
1856 cmd.setBinding(3, epipolar.epipoles);
1857 cmd.setBinding(4, zbuffer);
1858 cmd.setBinding(5, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
1859 cmd.setBinding(6, sky.cloudsLut, Sampler::bilinear(ClampMode::ClampToEdge));
1860 cmd.setBinding(7, sky.fogLut3DMs, Sampler::bilinear(ClampMode::ClampToEdge));
1862 cmd.dispatchThreads(epipolar.epTrace.size());
1871void Renderer::prepareEpipolar(Tempest::Encoder<Tempest::CommandBuffer>& cmd,
WorldView& wview) {
1872 const bool doVolumetricFog = sky.quality!=VolumetricLQ && sky.quality!=PathTrace;
1873 if(!doVolumetricFog || (!settings.vsmEnabled && !settings.rtsmEnabled))
1878 auto&
epTrace = usesImage2d(epipolar.epTrace, TextureFormat::R16, 1024, 2*1024);
1879 auto&
epipoles = usesSsbo (epipolar.epipoles, shaders.
fogEpipolarVsm.sizeofBuffer(3,
size_t(epipolar.epTrace.h())));
1881 cmd.setDebugMarker(
"Fog-epipolar");
1882 cmd.setFramebuffer({});
1883 cmd.setBinding(0, sky.occlusionLut);
1887 cmd.setBinding(4, zbuffer);
1888 if(settings.vsmEnabled)
1890 else if(settings.rtsmEnabled)
1892 cmd.dispatch(uint32_t(
epTrace.h()));
1895void Renderer::prepareIrradiance(Encoder<CommandBuffer>& cmd,
WorldView& wview) {
1898 cmd.setDebugMarker(
"Irradiance");
1899 cmd.setFramebuffer({});
1900 cmd.setBinding(0, sky.irradianceLut);
1902 cmd.setBinding(2, sky.viewCldLut);
1907void Renderer::prepareGi(Encoder<CommandBuffer>& cmd,
WorldView& wview) {
1908 if(!settings.giEnabled || !settings.zCloudShadowScale) {
1912 const size_t maxHash = gi.hashTable.byteSize()/
sizeof(uint32_t);
1916 cmd.setFramebuffer({});
1918 cmd.setDebugMarker(
"GI-Init");
1919 cmd.setBinding(0, gi.voteTable);
1920 cmd.setBinding(1, gi.hashTable);
1921 cmd.setBinding(2, gi.probes);
1922 cmd.setBinding(3, gi.freeList);
1926 cmd.dispatchThreads(maxHash);
1928 cmd.setBinding(0, gi.probesLighting);
1930 cmd.setPipeline(shaders.
copyImg);
1931 cmd.dispatchThreads(gi.probesLighting.size());
1932 gi.fisrtFrame =
false;
1935 static bool alloc =
true;
1936 cmd.setDebugMarker(
"GI-Alloc");
1937 cmd.setBinding(0, gi.voteTable);
1938 cmd.setBinding(1, gi.hashTable);
1939 cmd.setBinding(2, gi.probes);
1940 cmd.setBinding(3, gi.freeList);
1942 cmd.dispatchThreads(maxHash);
1946 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1947 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1948 cmd.setBinding(3, zbuffer, Sampler::nearest());
1949 cmd.setBinding(4, gi.voteTable);
1950 cmd.setBinding(5, gi.hashTable);
1951 cmd.setBinding(6, gi.probes);
1952 cmd.setBinding(7, gi.freeList);
1954 cmd.dispatchThreads(sceneDepth.size());
1956 cmd.setBinding(0, gi.voteTable);
1957 cmd.setBinding(1, gi.hashTable);
1958 cmd.setBinding(2, gi.probes);
1959 cmd.setBinding(3, gi.freeList);
1961 cmd.dispatchThreads(gi.maxProbes);
1964 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
1965 cmd.setBinding(2, gbufNormal, Sampler::nearest());
1966 cmd.setBinding(3, zbuffer, Sampler::nearest());
1967 cmd.setBinding(4, gi.voteTable);
1968 cmd.setBinding(5, gi.hashTable);
1969 cmd.setBinding(6, gi.probes);
1970 cmd.setBinding(7, gi.freeList);
1972 cmd.dispatchThreads(sceneDepth.size());
1975 cmd.setDebugMarker(
"GI-Trace");
1977 cmd.setBinding(1, gi.probesGBuffDiff);
1978 cmd.setBinding(2, gi.probesGBuffNorm);
1979 cmd.setBinding(3, gi.probesGBuffRayT);
1980 cmd.setBinding(4, gi.hashTable);
1981 cmd.setBinding(5, gi.probes);
1982 cmd.setBinding(6, scene.rtScene.tlas);
1983 cmd.setBinding(7, Sampler::bilinear());
1984 cmd.setBinding(8, scene.rtScene.tex);
1985 cmd.setBinding(9, scene.rtScene.vbo);
1986 cmd.setBinding(10,scene.rtScene.ibo);
1987 cmd.setBinding(11,scene.rtScene.rtDesc);
1991 cmd.setDebugMarker(
"GI-HashMap");
1992 cmd.setBinding(0, gi.voteTable);
1993 cmd.setBinding(1, gi.hashTable);
1994 cmd.setBinding(2, gi.probes);
1995 cmd.setBinding(3, gi.freeList);
1997 cmd.dispatchThreads(maxHash);
1999 cmd.dispatchThreads(gi.maxProbes);
2001 cmd.setDebugMarker(
"GI-Lighting");
2002 cmd.setBinding(0, gi.probesLightingPrev);
2003 cmd.setBinding(1, gi.probesLighting);
2004 cmd.setPipeline(shaders.
copyImg);
2005 cmd.dispatchThreads(gi.probesLighting.size());
2008 cmd.setBinding(1, gi.probesLighting);
2009 cmd.setBinding(2, gi.probesGBuffDiff, Sampler::nearest());
2010 cmd.setBinding(3, gi.probesGBuffNorm, Sampler::nearest());
2011 cmd.setBinding(4, gi.probesGBuffRayT, Sampler::nearest());
2012 cmd.setBinding(5, sky.viewCldLut, Sampler::bilinear());
2013 cmd.setBinding(6, shadowMap[1], Sampler::bilinear());
2014 cmd.setBinding(7, gi.probesLightingPrev, Sampler::nearest());
2015 cmd.setBinding(8, gi.hashTable);
2016 cmd.setBinding(9, gi.probes);
2021void Renderer::prepareExposure(Encoder<CommandBuffer>& cmd,
WorldView& wview) {
2027 float sunOcclusion = 1.0;
2030 push.sunOcclusion =
smoothstep(0.0f, 0.01f, sunDir.y);
2032 static float override = 0;
2033 static float add = 1.f;
2035 push.baseL =
override;
2038 cmd.setDebugMarker(
"Exposure");
2039 cmd.setFramebuffer({});
2041 cmd.setBinding(1, sky.viewCldLut);
2042 cmd.setBinding(2, sky.transLut, Sampler::bilinear(ClampMode::ClampToEdge));
2043 cmd.setBinding(3, sky.cloudsLut, Sampler::bilinear(ClampMode::ClampToEdge));
2044 cmd.setBinding(4, sky.irradianceLut);
2045 cmd.setPushData(&push,
sizeof(push));
2050void Renderer::drawProbesDbg(Encoder<CommandBuffer>& cmd,
const WorldView& wview) {
2051 if(!settings.giEnabled)
2054 static bool enable =
false;
2058 cmd.setDebugMarker(
"GI-dbg");
2060 cmd.setBinding(1, gi.probesLighting);
2061 cmd.setBinding(2, gi.probes);
2062 cmd.setBinding(3, gi.hashTable);
2064 cmd.draw(
nullptr, 0, 36, 0, gi.maxProbes);
2067void Renderer::drawProbesHitDbg(Encoder<CommandBuffer>& cmd) {
2068 if(!settings.giEnabled)
2071 static bool enable =
false;
2075 cmd.setDebugMarker(
"GI-dbg");
2076 cmd.setBinding(1, gi.probesLighting);
2077 cmd.setBinding(2, gi.probesGBuffDiff);
2078 cmd.setBinding(3, gi.probesGBuffRayT);
2079 cmd.setBinding(4, gi.probes);
2081 cmd.draw(
nullptr, 0, 36, 0, gi.maxProbes*256);
2085void Renderer::drawAmbient(Encoder<CommandBuffer>& cmd,
const WorldView& view) {
2086 static bool enable =
true;
2090 if(settings.giEnabled && settings.zCloudShadowScale) {
2091 cmd.setDebugMarker(
"AmbientLight");
2093 cmd.setBinding(1, gi.probesLighting);
2094 cmd.setBinding(2, gbufDiffuse, Sampler::nearest());
2095 cmd.setBinding(3, gbufNormal, Sampler::nearest());
2096 cmd.setBinding(4, zbuffer, Sampler::nearest());
2097 cmd.setBinding(5, ssao.ssaoBlur, Sampler::nearest());
2098 cmd.setBinding(6, gi.hashTable);
2099 cmd.setBinding(7, gi.probes);
2101 cmd.draw(
nullptr, 0, 3);
2105 cmd.setDebugMarker(
"AmbientLight");
2107 cmd.setBinding(1, gbufDiffuse, Sampler::nearest());
2108 cmd.setBinding(2, gbufNormal, Sampler::nearest());
2109 cmd.setBinding(3, sky.irradianceLut);
2110 if(settings.zCloudShadowScale) {
2111 cmd.setBinding(4, ssao.ssaoBlur, Sampler::nearest(ClampMode::ClampToEdge));
2116 cmd.draw(
nullptr, 0, 3);
2123 uint32_t w = uint32_t(zbuffer.w());
2124 uint32_t h = uint32_t(zbuffer.h());
2125 auto img = device.attachment(Tempest::TextureFormat::RGBA8,w,h);
2129 auto enc = cmd.startEncoding(device);
2130 draw(img,enc,frameId);
2133 auto sync = device.submit(cmd);
2138 auto d16 = device.attachment(TextureFormat::R16, swapchain.w(),swapchain.h());
2139 auto normals = device.attachment(TextureFormat::RGBA16, swapchain.w(),swapchain.h());
2142 auto enc = cmd.startEncoding(device);
2143 enc.setFramebuffer({{normals,Tempest::Discard,Tempest::Preserve}});
2144 enc.setBinding(0, gbufNormal, Sampler::nearest());
2145 enc.setPipeline(shaders.
copy);
2146 enc.draw(
nullptr, 0, 3);
2148 enc.setFramebuffer({{d16,Tempest::Discard,Tempest::Preserve}});
2149 enc.setBinding(0,zbuffer,Sampler::nearest());
2150 enc.setPipeline(shaders.
copy);
2151 enc.draw(
nullptr, 0, 3);
2153 sync = device.submit(cmd);
2156 auto pm = device.readPixels(textureCast<const Texture2d&>(normals));
2157 pm.save(
"gbufNormal.png");
2159 pm = device.readPixels(textureCast<const Texture2d&>(d16));
2160 pm.save(
"zbuffer.hdr");
2165float Renderer::internalResolutionScale()
const {
2166 if(settings.vidResIndex==0)
2168 if(settings.vidResIndex==1)
2173Size Renderer::internalResolution()
const {
2174 if(settings.vidResIndex==0)
2175 return Size(
int(swapchain.w()),
int(swapchain.h()));
2176 if(settings.vidResIndex==1)
2177 return Size(
int(3*swapchain.w()/4),
int(3*swapchain.h()/4));
2178 return Size(
int(swapchain.w()/2),
int(swapchain.h()/2));
Tempest::Matrix4x4 projective() const
static constexpr const float minShadowY
Tempest::Matrix4x4 viewProjLwc() const
Tempest::Matrix4x4 viewShadowVsm(const Tempest::Vec3 &ldir) const
Tempest::Matrix4x4 viewShadow(const Tempest::Vec3 &ldir, size_t layer) const
Tempest::Matrix4x4 viewProj() const
void make(const Tempest::Matrix4x4 &m, int32_t w, int32_t h)
Tempest::Signal< void()> onSettingsChanged
static auto options() -> const Options &
static int settingsGetI(std::string_view sec, std::string_view name)
WorldView * worldView() const
Tempest::Signal< void()> toggleGi
static float settingsGetF(std::string_view sec, std::string_view name)
Tempest::Signal< void()> toggleVsm
Tempest::Signal< void()> toggleRtsm
const Tempest::StorageBuffer & bvh() const
auto & lightsSsbo() const
Tempest::Vec3 dir() const
Tempest::StorageImage dbg32
Tempest::StorageBuffer visList
Tempest::Attachment screenshoot(uint8_t frameId)
Tempest::StorageBuffer drawTasks
Tempest::StorageBuffer pageTblOmni
Tempest::ZBuffer pageData
Tempest::StorageImage outputImageClr
Tempest::StorageBuffer pageList
Tempest::StorageBuffer pageListTmp
Tempest::StorageImage pageTbl
void dbgDraw(Tempest::Painter &painter)
Tempest::StorageImage lightTiles
Tempest::StorageImage vsmDbg
Tempest::StorageImage dbg16
Tempest::StorageImage pages
Tempest::StorageImage primTilesOmni
Tempest::StorageImage dbg64
Tempest::StorageBuffer posList
Tempest::StorageImage outputImage
Tempest::StorageBuffer epipoles
Tempest::StorageImage primTiles
Tempest::StorageBuffer visibleLights
Tempest::StorageImage pageHiZ
Tempest::StorageImage epTrace
Tempest::StorageImage meshTiles
Renderer(Tempest::Swapchain &swapchain)
void draw(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t cmdId, size_t imgId, Tempest::VectorImage::Mesh &uiLayer, Tempest::VectorImage::Mesh &numOverlay, InventoryMenu &inventory, VideoWidget &video)
Tempest::StorageImage lightBins
static const Tempest::IndexBuffer< uint16_t > & cubeIbo()
static const Tempest::Sampler & shadowSampler()
static Tempest::Device & device()
static const Tempest::Texture2d & fallbackBlack()
static void recycle(Tempest::DescriptorArray &&arr)
Tempest::StorageImage vsmDbg
Tempest::StorageBuffer uboGlobal[V_Count]
Tempest::ComputePipeline rtsmPrimOmni
Tempest::ComputePipeline rtsmHiZ
Tempest::ComputePipeline fogViewLut3d
Tempest::RenderPipeline fog3dHQ
Tempest::ComputePipeline rtsmMeshletCull
Tempest::ComputePipeline vsmListPages
Tempest::RenderPipeline skyPathTrace
Tempest::ComputePipeline probeAlocation
Tempest::ComputePipeline rtsmLightsOmni
Tempest::ComputePipeline rtsmMeshletOmni
Tempest::ComputePipeline vsmCullLights
Tempest::ComputePipeline fogViewLutSep
Tempest::ComputePipeline rtsmBackfaceOmni
Tempest::ComputePipeline probeInit
Tempest::RenderPipeline directLightSh
Tempest::ComputePipeline fogOcclusion
Tempest::ComputePipeline swRendering
Tempest::RenderPipeline stash
Tempest::RenderPipeline probeHitDbg
Tempest::RenderPipeline waterReflection
Tempest::ComputePipeline hiZMip
Tempest::RenderPipeline rtsmDbg
Tempest::ComputePipeline probePrune
static bool isRtsmSupported()
Tempest::RenderPipeline probeAmbient
Tempest::ComputePipeline rtsmCulling
Tempest::ComputePipeline rtsmCompactOmni
Tempest::RenderPipeline vsmDirectLight
Tempest::RenderPipeline skyViewLut
Tempest::ComputePipeline vsmPostprocessOmni
Tempest::RenderPipeline directLightRq
Tempest::RenderPipeline ambientLight
Tempest::ComputePipeline rtsmRaster
Tempest::RenderPipeline vsmDbg
Tempest::RenderPipeline sun
Tempest::RenderPipeline lightsVsm
Tempest::ComputePipeline rtsmPosition
Tempest::ComputePipeline vsmMarkOmniPages
Tempest::ComputePipeline swRaytracing
Tempest::RenderPipeline skyTransmittance
Tempest::ComputePipeline hiZPot
Tempest::ComputePipeline probeMakeHash
Tempest::RenderPipeline swRenderingDbg
Tempest::ComputePipeline ssao
Tempest::ComputePipeline rtsmCullLights
Tempest::ComputePipeline rtsmRasterOmni
Tempest::RenderPipeline lightsRq
Tempest::ComputePipeline ssaoBlur
Tempest::ComputePipeline rtsmTaskOmni
Tempest::ComputePipeline vsmFogShadow
Tempest::ComputePipeline probeClear
Tempest::RenderPipeline vsmFog
Tempest::ComputePipeline rtsmRenderingOmni
Tempest::ComputePipeline vsmAllocPages
static bool isVsmSupported()
Tempest::ComputePipeline rtsmCompactLights
Tempest::ComputePipeline rtsmPrimCull
Tempest::RenderPipeline skyViewCldLut
Tempest::ComputePipeline cmaa2ProcessCandidates
Tempest::RenderPipeline directLight
Tempest::RenderPipeline fog
Tempest::ComputePipeline probeVote
Tempest::ComputePipeline vsmClear
Tempest::ComputePipeline rtsmClearOmni
Tempest::ComputePipeline vsmFogPages
Tempest::ComputePipeline vsmMergePages
Tempest::RenderPipeline ambientLightSsao
Tempest::ComputePipeline fogEpipolarVsm
Tempest::RenderPipeline underwaterT
Tempest::RenderPipeline copy
Tempest::RenderPipeline sky
Tempest::RenderPipeline cmaa2DeferredColorApply2x2
Tempest::ComputePipeline cloudsLut
Tempest::ComputePipeline rtsmCullingOmni
Tempest::ComputePipeline probeTrace
Tempest::RenderPipeline skyMultiScattering
Tempest::ComputePipeline rtsmPositionOmni
Tempest::RenderPipeline lights
Tempest::ComputePipeline rtsmBboxesOmni
Tempest::ComputePipeline cmaa2EdgeColor2x2Presets[uint32_t(AaPreset::PRESETS_COUNT)]
Tempest::ComputePipeline vsmFogTrace
Tempest::RenderPipeline skySep
Tempest::ComputePipeline fogEpipolarOcclusion
Tempest::ComputePipeline irradiance
Tempest::ComputePipeline copyImg
Tempest::RenderPipeline rtsmDirectLight
Tempest::ComputePipeline vsmClearOmni
Tempest::ComputePipeline rtsmFogPages
Tempest::ComputePipeline probeLighting
Tempest::RenderPipeline waterReflectionSSR
Tempest::ComputePipeline rtsmPages
Tempest::RenderPipeline underwaterS
Tempest::ComputePipeline vsmMarkPages
Tempest::ComputePipeline vsmClumpPages
Tempest::RenderPipeline probeDbg
Tempest::ComputePipeline rtsmClear
Tempest::ComputePipeline probeClearHash
Tempest::ComputePipeline skyExposure
Tempest::RenderPipeline tonemapping
const State & cloudsNight() const
const State & cloudsDay() const
const Tempest::Texture2d & sunImage() const
float sunIntensity() const
float moonIntensity() const
const LightSource & sunLight() const
void prepareGlobals(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t fId)
const DrawBuckets & drawBuckets() const
void drawShadow(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t frameId, uint8_t layer)
void drawGBuffer(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t frameId)
void drawTranslucent(Tempest::Encoder< Tempest::CommandBuffer > &cmd, uint8_t frameId)
const SceneGlobals & sceneGlobals() const
auto instanceSsbo() const -> const Tempest::StorageBuffer &
const DrawClusters & clusters() const
const Landscape & landscape() const
void visibilityPass(Tempest::Encoder< Tempest::CommandBuffer > &cmd, int pass)
void drawHiZ(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void drawVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void visibilityVsm(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
const DrawCommands & drawCommands() const
void updateFrustrum(const Frustrum fr[])
void preFrameUpdate(const Camera &camera, uint64_t tickCount, uint8_t fId)
void drawWater(Tempest::Encoder< Tempest::CommandBuffer > &cmd)
void setVirtualShadowMap(bool enabled, const Tempest::ZBuffer &pageData, const Tempest::StorageImage &pageTbl, const Tempest::StorageImage &pageHiZ, const Tempest::StorageBuffer &pageList)
const LightSource & mainLight() const
const LightGroup & lights() const
static uint32_t nextPot(uint32_t x)
static const bool skyPathTrace
static Size tileCount(Size sz, int s)
static float linearstep(float edge0, float edge1, float x)
static float smoothstep(float edge0, float edge1, float x)
static uint32_t nextPot(uint32_t x)
const Tempest::Texture2d * lay[2]