mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 06:55:02 +01:00
282 lines
13 KiB
C++
282 lines
13 KiB
C++
#include "gbufferblitpass.h"
|
|
|
|
#include <chrono>
|
|
#include <utilities/Timer.h>
|
|
#include <nvrhi/utils.h>
|
|
|
|
#include "contactshadows.h"
|
|
#include "csm.h"
|
|
#include "environment.h"
|
|
#include "gbuffer.h"
|
|
#include "nvrendererbackend.h"
|
|
#include "sky.h"
|
|
#include "ssao.h"
|
|
|
|
GbufferBlitPass::GbufferBlitPass(NvRenderer* renderer, NvGbuffer* gbuffer,
|
|
NvGbuffer* gbuffer_shadow, NvSsao* ssao,
|
|
MaEnvironment* environment,
|
|
MaShadowMap* shadow_map,
|
|
MaContactShadows* contact_shadows, Sky* sky)
|
|
: FullScreenPass(renderer->GetBackend()),
|
|
MaResourceRegistry(renderer),
|
|
m_gbuffer(gbuffer),
|
|
m_gbuffer_shadow(gbuffer_shadow),
|
|
m_ssao(ssao),
|
|
m_environment(environment),
|
|
m_shadow_map(shadow_map),
|
|
m_contact_shadows(contact_shadows),
|
|
m_sky(sky) {}
|
|
|
|
void GbufferBlitPass::Init() {
|
|
InitResourceRegistry();
|
|
m_draw_constants = m_backend->GetDevice()->createBuffer(
|
|
nvrhi::utils::CreateVolatileConstantBufferDesc(
|
|
sizeof(DrawConstants), "GBuffer Lighting Constants", 16)
|
|
.setInitialState(nvrhi::ResourceStates::ConstantBuffer)
|
|
.setKeepInitialState(true));
|
|
RegisterResource(true, "gbuffer_lighting_constants", m_draw_constants,
|
|
nvrhi::ResourceType::VolatileConstantBuffer);
|
|
const nvrhi::SamplerHandle sampler_shadow_comp =
|
|
m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc()
|
|
.setReductionType(nvrhi::SamplerReductionType::Comparison)
|
|
.setComparisonFunc(nvrhi::ComparisonFunc::Greater)
|
|
.setAllAddressModes(nvrhi::SamplerAddressMode::ClampToEdge)
|
|
.setAllFilters(true));
|
|
const nvrhi::SamplerHandle sampler_linear =
|
|
m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc().setAllFilters(true));
|
|
const nvrhi::SamplerHandle sampler_linear_clamp =
|
|
m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc()
|
|
.setAllAddressModes(nvrhi::SamplerAddressMode::ClampToEdge)
|
|
.setAllFilters(true));
|
|
const nvrhi::SamplerHandle sampler_linear_clamp_v_repeat_h =
|
|
m_backend->GetDevice()->createSampler(
|
|
nvrhi::SamplerDesc()
|
|
.setAllAddressModes(nvrhi::SamplerAddressMode::ClampToEdge)
|
|
.setAddressU(nvrhi::SamplerAddressMode::Repeat)
|
|
.setAllFilters(true));
|
|
RegisterResource(true, "shadow_sampler_comp", sampler_shadow_comp,
|
|
nvrhi::ResourceType::Sampler);
|
|
RegisterResource(true, "sampler_linear_wrap", sampler_linear,
|
|
nvrhi::ResourceType::Sampler);
|
|
RegisterResource(true, "sampler_linear_clamp", sampler_linear_clamp,
|
|
nvrhi::ResourceType::Sampler);
|
|
RegisterResource(true, "sampler_linear_clamp_v_repeat_h", sampler_linear_clamp_v_repeat_h,
|
|
nvrhi::ResourceType::Sampler);
|
|
m_scene_depth = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc(m_gbuffer->m_gbuffer_depth->getDesc())
|
|
.setFormat(nvrhi::Format::R32_FLOAT)
|
|
.setDebugName("Scene Depth")
|
|
.setInitialState(nvrhi::ResourceStates::ShaderResource)
|
|
.setUseClearValue(false)
|
|
.setIsRenderTarget(false));
|
|
RegisterResource(true, "gbuffer_depth", m_scene_depth,
|
|
nvrhi::ResourceType::Texture_SRV);
|
|
m_output = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setWidth(m_gbuffer->m_framebuffer->getFramebufferInfo().width)
|
|
.setHeight(m_gbuffer->m_framebuffer->getFramebufferInfo().height)
|
|
.setFormat(nvrhi::Format::RGBA16_FLOAT)
|
|
.setIsUAV(true)
|
|
.setIsRenderTarget(true)
|
|
.setInitialState(nvrhi::ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
RegisterResource(true, "scene_lit_texture", m_output,
|
|
nvrhi::ResourceType::Texture_SRV);
|
|
m_output_copy = m_backend->GetDevice()->createTexture(
|
|
nvrhi::TextureDesc()
|
|
.setWidth(m_gbuffer->m_framebuffer->getFramebufferInfo().width)
|
|
.setHeight(m_gbuffer->m_framebuffer->getFramebufferInfo().height)
|
|
.setFormat(nvrhi::Format::RGBA16_FLOAT)
|
|
.setInitialState(nvrhi::ResourceStates::ShaderResource)
|
|
.setKeepInitialState(true));
|
|
RegisterResource(true, "scene_lit_texture_copy", m_output_copy,
|
|
nvrhi::ResourceType::Texture_SRV);
|
|
m_binding_layout = m_backend->GetDevice()->createBindingLayout(
|
|
nvrhi::BindingLayoutDesc()
|
|
.addItem(nvrhi::BindingLayoutItem::VolatileConstantBuffer(2))
|
|
.addItem(nvrhi::BindingLayoutItem::ConstantBuffer(11))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(0))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(1))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(2))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(3))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(4))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(5))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(8))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(9))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(10))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(11))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(12))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(14))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(15))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_SRV(16))
|
|
.addItem(nvrhi::BindingLayoutItem::StructuredBuffer_SRV(17))
|
|
.addItem(nvrhi::BindingLayoutItem::StructuredBuffer_SRV(18))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(8))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(11))
|
|
.addItem(nvrhi::BindingLayoutItem::Sampler(13))
|
|
.addItem(nvrhi::BindingLayoutItem::Texture_UAV(0))
|
|
.setVisibility(nvrhi::ShaderType::Compute));
|
|
for (int i = 0; i < std::size(m_binding_set); ++i) {
|
|
m_binding_set[i] = m_backend->GetDevice()->createBindingSet(
|
|
nvrhi::BindingSetDesc()
|
|
.addItem(nvrhi::BindingSetItem::ConstantBuffer(2, m_draw_constants))
|
|
.addItem(nvrhi::BindingSetItem::ConstantBuffer(
|
|
11, m_shadow_map->m_projection_buffer))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
0, m_gbuffer->m_gbuffer_diffuse))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
1, m_gbuffer->m_gbuffer_emission))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
2, m_gbuffer->m_gbuffer_params))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
3, m_gbuffer->m_gbuffer_normal))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
4, m_gbuffer->m_gbuffer_depth))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(5, m_ssao->m_outputAO))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
8, m_environment->m_dynamic_envmap_diffuse[0]))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
9, m_environment->m_dynamic_envmap_specular[0]))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
10, m_environment->m_brdf_lut))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
11, m_gbuffer_shadow->m_gbuffer_depth))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
12, m_contact_shadows->m_output_texture))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
14, m_sky->m_aerial_lut->m_lut))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
15, m_environment->m_clouds_texture))
|
|
.addItem(nvrhi::BindingSetItem::Texture_SRV(
|
|
16, static_cast<nvrhi::ITexture*>(
|
|
GetResource("forwardplus_index_grid_opaque", nvrhi::ResourceType::Texture_SRV)
|
|
.m_resource)))
|
|
.addItem(nvrhi::BindingSetItem::StructuredBuffer_SRV(
|
|
17, static_cast<nvrhi::IBuffer*>(
|
|
GetResource("forwardplus_index_buffer_opaque", nvrhi::ResourceType::StructuredBuffer_SRV)
|
|
.m_resource)))
|
|
.addItem(nvrhi::BindingSetItem::StructuredBuffer_SRV(
|
|
18, static_cast<nvrhi::IBuffer*>(
|
|
GetResource("forwardplus_light_buffer", nvrhi::ResourceType::StructuredBuffer_SRV)
|
|
.m_resource)))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(8, sampler_linear))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(11, sampler_shadow_comp))
|
|
.addItem(nvrhi::BindingSetItem::Sampler(13, sampler_linear_clamp_v_repeat_h))
|
|
.addItem(nvrhi::BindingSetItem::Texture_UAV(0, m_output)),
|
|
m_binding_layout);
|
|
}
|
|
m_pixel_shader =
|
|
m_backend->CreateShader("gbuffer_lighting", nvrhi::ShaderType::Compute);
|
|
m_pso = m_backend->GetDevice()->createComputePipeline(
|
|
nvrhi::ComputePipelineDesc()
|
|
.setComputeShader(m_pixel_shader)
|
|
.addBindingLayout(m_binding_layout));
|
|
// m_framebuffer = m_backend->GetDevice()->createFramebuffer(
|
|
// nvrhi::FramebufferDesc().addColorAttachment(m_output));
|
|
// FullScreenPass::Init();
|
|
}
|
|
|
|
void GbufferBlitPass::CreatePipelineDesc(
|
|
nvrhi::GraphicsPipelineDesc& pipeline_desc) {
|
|
FullScreenPass::CreatePipelineDesc(pipeline_desc);
|
|
pipeline_desc.addBindingLayout(m_binding_layout);
|
|
pipeline_desc.setPixelShader(m_pixel_shader);
|
|
}
|
|
|
|
void GbufferBlitPass::UpdateConstants(nvrhi::ICommandList* command_list,
|
|
glm::dmat4& view,
|
|
const glm::dmat4& projection) {
|
|
DrawConstants constants{};
|
|
constants.m_inverse_model_view = glm::inverse(glm::dmat4(glm::dmat3(view)));
|
|
constants.m_inverse_projection = glm::inverse(projection);
|
|
|
|
const auto& daylight = Global.DayLight;
|
|
|
|
m_sky->CalcLighting(constants.m_light_dir, constants.m_light_color);
|
|
constants.m_altitude = Global.pCamera.Pos.y;
|
|
constants.m_time = Timer::GetTime();
|
|
constants.m_vertical_fov =
|
|
glm::radians(Global.FieldOfView / Global.ZoomFactor);
|
|
|
|
{
|
|
float percipitation_intensity = glm::saturate(Global.Overcast - 1.);
|
|
constants.m_rain_params.x =
|
|
percipitation_intensity; // % amount of droplets
|
|
constants.m_rain_params.y =
|
|
glm::mix(15., 1., percipitation_intensity); // Regeneration time
|
|
static glm::vec4 wiper_timer_out;
|
|
static glm::vec4 wiper_timer_return;
|
|
if (TDynamicObject const* owner = Global.pCamera.m_owner;
|
|
owner && !!owner->MoverParameters->CabActive) {
|
|
for (int i = 0; i < 4; ++i) {
|
|
if (i < owner->dWiperPos.size()) {
|
|
int index = owner->MoverParameters->CabActive > 0
|
|
? i
|
|
: static_cast<int>(owner->dWiperPos.size() - 1) - i;
|
|
constants.m_wiper_pos[i] = owner->dWiperPos[index];
|
|
if (owner->dWiperPos[index] > 0. && owner->wiperDirection[index]) {
|
|
constants.m_wiper_pos[i] += 1.;
|
|
}
|
|
if (owner->dWiperPos[index] < .025) {
|
|
wiper_timer_out[i] = constants.m_time;
|
|
}
|
|
if (owner->dWiperPos[index] > .975) {
|
|
wiper_timer_return[i] = constants.m_time;
|
|
}
|
|
constants.m_wiper_timer_out[i] = wiper_timer_out[i];
|
|
constants.m_wiper_timer_return[i] = wiper_timer_return[i];
|
|
} else {
|
|
constants.m_wiper_pos[i] = 0.;
|
|
wiper_timer_out[i] = constants.m_wiper_timer_out[i] = -1000.;
|
|
wiper_timer_return[i] = constants.m_wiper_timer_return[i] = -1000.;
|
|
}
|
|
}
|
|
} else {
|
|
constants.m_wiper_pos = glm::vec4{0.};
|
|
wiper_timer_out = constants.m_wiper_timer_out = glm::vec4{-1000.};
|
|
wiper_timer_return = constants.m_wiper_timer_return = glm::vec4{-1000.};
|
|
}
|
|
}
|
|
|
|
command_list->writeBuffer(m_draw_constants, &constants, sizeof(constants));
|
|
}
|
|
|
|
void GbufferBlitPass::UpdateSceneColorForRefraction(
|
|
nvrhi::ICommandList* command_list) const {
|
|
command_list->copyTexture(
|
|
m_output_copy, nvrhi::TextureSlice().resolve(m_output_copy->getDesc()),
|
|
m_output, nvrhi::TextureSlice().resolve(m_output->getDesc()));
|
|
command_list->setTextureState(m_output, nvrhi::AllSubresources,
|
|
nvrhi::ResourceStates::RenderTarget);
|
|
command_list->commitBarriers();
|
|
}
|
|
|
|
void GbufferBlitPass::Render(nvrhi::ICommandList* command_list,
|
|
glm::dmat4& view, const glm::dmat4& projection) {
|
|
UpdateConstants(command_list, view, projection);
|
|
Render(command_list);
|
|
command_list->copyTexture(
|
|
m_scene_depth, nvrhi::TextureSlice().resolve(m_scene_depth->getDesc()),
|
|
m_gbuffer->m_gbuffer_depth,
|
|
nvrhi::TextureSlice().resolve(m_scene_depth->getDesc()));
|
|
}
|
|
|
|
void GbufferBlitPass::Render(nvrhi::ICommandList* command_list) {
|
|
nvrhi::ComputeState graphics_state;
|
|
auto desc = m_output->getDesc();
|
|
// InitState(graphics_state);
|
|
graphics_state.setPipeline(m_pso);
|
|
graphics_state.addBindingSet(
|
|
m_binding_set[m_environment->GetCurrentSetIndex()]);
|
|
command_list->setComputeState(graphics_state);
|
|
#define DISPATCH_SIZE(size, groupsize) ((size + groupsize - 1) / groupsize)
|
|
command_list->dispatch(DISPATCH_SIZE(desc.width, 8),
|
|
DISPATCH_SIZE(desc.height, 8), 1);
|
|
// Draw(command_list);
|
|
}
|
|
|
|
nvrhi::IFramebuffer* GbufferBlitPass::GetFramebuffer() { return m_framebuffer; }
|