diff options
Diffstat (limited to 'source/blender/draw/engines')
36 files changed, 585 insertions, 945 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_gbuffer.hh b/source/blender/draw/engines/eevee/eevee_gbuffer.hh index 237a2ecaf31..dc217590038 100644 --- a/source/blender/draw/engines/eevee/eevee_gbuffer.hh +++ b/source/blender/draw/engines/eevee/eevee_gbuffer.hh @@ -33,110 +33,132 @@ enum eClosureBits { CLOSURE_SSS = 1 << 1, CLOSURE_REFLECTION = 1 << 2, CLOSURE_REFRACTION = 1 << 3, - CLOSURE_VOLUME = 1 << 4, - CLOSURE_EMISSION = 1 << 5, - CLOSURE_TRANSPARENCY = 1 << 6, + CLOSURE_AMBIENT_OCCLUSION = 1 << 5, + /* Non-stencil bits. */ + CLOSURE_TRANSPARENCY = 1 << 8, + CLOSURE_EMISSION = 1 << 9, + CLOSURE_HOLDOUT = 1 << 10, + CLOSURE_VOLUME = 1 << 11, }; +ENUM_OPERATORS(eClosureBits, CLOSURE_VOLUME); + +static inline eClosureBits extract_closure_mask(const GPUMaterial *gpumat) +{ + eClosureBits closure_bits = eClosureBits(0); + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE)) { + closure_bits |= CLOSURE_DIFFUSE; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { + closure_bits |= CLOSURE_TRANSPARENCY; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_EMISSION)) { + closure_bits |= CLOSURE_EMISSION; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY)) { + closure_bits |= CLOSURE_REFLECTION; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_SUBSURFACE)) { + closure_bits |= CLOSURE_SSS; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT)) { + closure_bits |= CLOSURE_REFRACTION; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_HOLDOUT)) { + closure_bits |= CLOSURE_HOLDOUT; + } + if (GPU_material_flag_get(gpumat, GPU_MATFLAG_AO)) { + closure_bits |= CLOSURE_AMBIENT_OCCLUSION; + } + return closure_bits; +} + struct GBuffer { + Instance &inst; + TextureFromPool transmit_color_tx = {"GbufferTransmitColor"}; TextureFromPool transmit_normal_tx = {"GbufferTransmitNormal"}; TextureFromPool transmit_data_tx = {"GbufferTransmitData"}; + TextureFromPool reflect_color_tx = {"GbufferReflectionColor"}; TextureFromPool reflect_normal_tx = {"GbufferReflectionNormal"}; - TextureFromPool volume_tx = {"GbufferVolume"}; - TextureFromPool emission_tx = {"GbufferEmission"}; - TextureFromPool transparency_tx = {"GbufferTransparency"}; - - Framebuffer gbuffer_fb = {"Gbuffer"}; - Framebuffer volume_fb = {"VolumeHeterogeneous"}; - - TextureFromPool holdout_tx = {"HoldoutRadiance"}; - TextureFromPool diffuse_tx = {"DiffuseRadiance"}; - Framebuffer radiance_fb = {"Radiance"}; - Framebuffer radiance_clear_fb = {"RadianceClear"}; - - Framebuffer holdout_fb = {"Holdout"}; - - TextureFromPool depth_behind_tx = {"DepthBehind"}; - - Framebuffer depth_behind_fb = {"DepthCopy"}; + TextureFromPool radiance_diffuse_tx = {"DiffuseRadiance"}; /** Raytracing. */ TextureFromPool ray_data_tx = {"RayData"}; TextureFromPool ray_radiance_tx = {"RayRadiance"}; TextureFromPool ray_variance_tx = {"RayVariance"}; - Framebuffer ray_data_fb = {"RayData"}; - Framebuffer ray_denoise_fb = {"RayDenoise"}; - /* Owner of this GBuffer. Used to query temp textures. */ - void *owner; + TextureFromPool rpass_emission_tx = {"PassEmission"}; + TextureFromPool rpass_diffuse_light_tx = {"PassDiffuseColor"}; + TextureFromPool rpass_specular_light_tx = {"PassSpecularColor"}; + TextureFromPool rpass_volume_light_tx = {"PassVolumeLight"}; + + /* Maximum texture size. Since we use imageLoad/Store instead of framebuffer, we only need to + * allocate the biggest texture. */ + int2 extent = int2(-1); - /* Pointer to the view's buffers. */ - GPUTexture *depth_tx = nullptr; - GPUTexture *combined_tx = nullptr; - int layer = -1; + GBuffer(Instance &inst_) : inst(inst_){}; - void sync(GPUTexture *depth_tx_, GPUTexture *combined_tx_, void *owner_, int layer_ = -1) + void begin_sync() { - owner = owner_; - depth_tx = depth_tx_; - combined_tx = combined_tx_; - layer = layer_; + extent = int2(-1); + transmit_color_tx.sync(); transmit_normal_tx.sync(); transmit_data_tx.sync(); reflect_color_tx.sync(); reflect_normal_tx.sync(); - volume_tx.sync(); - emission_tx.sync(); - transparency_tx.sync(); - holdout_tx.sync(); - diffuse_tx.sync(); - depth_behind_tx.sync(); + radiance_diffuse_tx.sync(); ray_data_tx.sync(); ray_radiance_tx.sync(); ray_variance_tx.sync(); + rpass_emission_tx.sync(); + rpass_diffuse_light_tx.sync(); + rpass_specular_light_tx.sync(); + rpass_volume_light_tx.sync(); } - void prepare(eClosureBits closures_used) + void view_sync(int2 view_extent) { - int2 extent = {GPU_texture_width(depth_tx), GPU_texture_height(depth_tx)}; + extent = math::max(extent, view_extent); + } + + void acquire(eClosureBits closures_used) + { + DrawEngineType *owner = (DrawEngineType *)&inst; - /* TODO Reuse for different config. */ if (closures_used & (CLOSURE_DIFFUSE | CLOSURE_SSS | CLOSURE_REFRACTION)) { transmit_color_tx.acquire(extent, GPU_R11F_G11F_B10F, owner); } + else { + transmit_color_tx.acquire(int2(1), GPU_R11F_G11F_B10F, owner); + } + if (closures_used & (CLOSURE_SSS | CLOSURE_REFRACTION)) { transmit_normal_tx.acquire(extent, GPU_RGBA16F, owner); transmit_data_tx.acquire(extent, GPU_R11F_G11F_B10F, owner); } else if (closures_used & CLOSURE_DIFFUSE) { transmit_normal_tx.acquire(extent, GPU_RG16F, owner); - } - if (closures_used & CLOSURE_SSS) { - diffuse_tx.acquire(extent, GPU_RGBA16F, owner); + transmit_data_tx.acquire(int2(1), GPU_R11F_G11F_B10F, owner); } if (closures_used & CLOSURE_REFLECTION) { reflect_color_tx.acquire(extent, GPU_R11F_G11F_B10F, owner); reflect_normal_tx.acquire(extent, GPU_RGBA16F, owner); } - - if (closures_used & CLOSURE_VOLUME) { - /* TODO(fclem): This is killing performance. - * Idea: use interleaved data pattern to fill only a 32bpp buffer. */ - volume_tx.acquire(extent, GPU_RGBA32UI, owner); + else { + reflect_color_tx.acquire(int2(1), GPU_R11F_G11F_B10F, owner); + reflect_normal_tx.acquire(int2(1), GPU_RGBA16F, owner); } - if (closures_used & CLOSURE_EMISSION) { - emission_tx.acquire(extent, GPU_R11F_G11F_B10F, owner); + if (closures_used & CLOSURE_SSS) { + radiance_diffuse_tx.acquire(extent, GPU_RGBA16F, owner); } - - if (closures_used & CLOSURE_TRANSPARENCY) { - /* TODO(fclem): Speedup by using Dithered holdout and GPU_RGB10_A2. */ - transparency_tx.acquire(extent, GPU_RGBA16, owner); + else { + radiance_diffuse_tx.acquire(int2(1), GPU_RGBA16F, owner); } if (closures_used & (CLOSURE_DIFFUSE | CLOSURE_REFLECTION | CLOSURE_REFRACTION)) { @@ -145,97 +167,30 @@ struct GBuffer { ray_variance_tx.acquire(extent, GPU_R8, owner); } - holdout_tx.acquire(extent, GPU_R11F_G11F_B10F, owner); - depth_behind_tx.acquire(extent, GPU_DEPTH24_STENCIL8, owner); - - /* Layer attachement also works with cubemap. */ - gbuffer_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx, layer), - GPU_ATTACHMENT_TEXTURE(transmit_color_tx), - GPU_ATTACHMENT_TEXTURE(transmit_normal_tx), - GPU_ATTACHMENT_TEXTURE(transmit_data_tx), - GPU_ATTACHMENT_TEXTURE(reflect_color_tx), - GPU_ATTACHMENT_TEXTURE(reflect_normal_tx), - GPU_ATTACHMENT_TEXTURE(volume_tx), - GPU_ATTACHMENT_TEXTURE(emission_tx), - GPU_ATTACHMENT_TEXTURE(transparency_tx)); - } - - void bind(void) - { - GPU_framebuffer_bind(gbuffer_fb); - GPU_framebuffer_clear_stencil(gbuffer_fb, 0x0); - } - - void bind_radiance(void) - { - /* Layer attachement also works with cubemap. */ - radiance_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx, layer), - GPU_ATTACHMENT_TEXTURE(combined_tx), - GPU_ATTACHMENT_TEXTURE(diffuse_tx)); - GPU_framebuffer_bind(radiance_fb); - } - - void bind_volume(void) - { - /* Layer attachement also works with cubemap. */ - volume_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx, layer), - GPU_ATTACHMENT_TEXTURE(volume_tx), - GPU_ATTACHMENT_TEXTURE(transparency_tx)); - GPU_framebuffer_bind(volume_fb); - } - - void bind_tracing(void) - { - /* Layer attachement also works with cubemap. */ - /* Attach depth_stencil buffer to only trace the surfaces that need it. */ - ray_data_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx, layer), - GPU_ATTACHMENT_TEXTURE(ray_data_tx), - GPU_ATTACHMENT_TEXTURE(ray_radiance_tx)); - GPU_framebuffer_bind(ray_data_fb); - - float color[4] = {0.0f}; - GPU_framebuffer_clear_color(ray_data_fb, color); - } - - void bind_holdout(void) - { - holdout_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(holdout_tx)); - GPU_framebuffer_bind(holdout_fb); - } - - void copy_depth_behind(void) - { - depth_behind_fb.ensure(GPU_ATTACHMENT_TEXTURE(depth_behind_tx)); - GPU_framebuffer_bind(depth_behind_fb); - - GPU_framebuffer_blit(gbuffer_fb, 0, depth_behind_fb, 0, GPU_DEPTH_BIT); - } - - void clear_radiance(void) - { - radiance_clear_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(diffuse_tx)); - GPU_framebuffer_bind(radiance_clear_fb); - - float color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_clear_color(radiance_clear_fb, color); + if (true) { + /* Dummies for everything for now. */ + rpass_emission_tx.acquire(int2(1), GPU_RGBA16F, owner); + rpass_diffuse_light_tx.acquire(int2(1), GPU_RGBA16F, owner); + rpass_specular_light_tx.acquire(int2(1), GPU_RGBA16F, owner); + rpass_volume_light_tx.acquire(int2(1), GPU_RGBA16F, owner); + } } - void render_end(void) + void release(void) { transmit_color_tx.release(); transmit_normal_tx.release(); transmit_data_tx.release(); reflect_color_tx.release(); reflect_normal_tx.release(); - volume_tx.release(); - emission_tx.release(); - transparency_tx.release(); - holdout_tx.release(); - diffuse_tx.release(); - depth_behind_tx.release(); + radiance_diffuse_tx.release(); ray_data_tx.release(); ray_radiance_tx.release(); ray_variance_tx.release(); + rpass_emission_tx.release(); + rpass_diffuse_light_tx.release(); + rpass_specular_light_tx.release(); + rpass_volume_light_tx.release(); } }; diff --git a/source/blender/draw/engines/eevee/eevee_hizbuffer.cc b/source/blender/draw/engines/eevee/eevee_hizbuffer.cc index aa9a1a7a4ad..2d364945a02 100644 --- a/source/blender/draw/engines/eevee/eevee_hizbuffer.cc +++ b/source/blender/draw/engines/eevee/eevee_hizbuffer.cc @@ -56,20 +56,20 @@ void HiZBuffer::end_sync() DRW_shgroup_call_compute_ref(grp, dispatch_size_); DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH); } -} -void HiZBuffer::prepare(GPUTexture *depth_src_tx) -{ - /* TODO(fclem) Remove. */ - begin_sync(); - view_sync({GPU_texture_width(depth_src_tx), GPU_texture_height(depth_src_tx)}); - end_sync(); + is_dirty_ = true; } void HiZBuffer::update(GPUTexture *depth_src_tx) { + if (!is_dirty_) { + return; + } int2 extent_src = {GPU_texture_width(depth_src_tx), GPU_texture_height(depth_src_tx)}; + BLI_assert(extent_src.x <= extent_.x); + BLI_assert(extent_src.y <= extent_.y); + dispatch_size_.x = divide_ceil_u(extent_src.x, kernel_size_); dispatch_size_.y = divide_ceil_u(extent_src.y, kernel_size_); dispatch_size_.z = 1; diff --git a/source/blender/draw/engines/eevee/eevee_hizbuffer.hh b/source/blender/draw/engines/eevee/eevee_hizbuffer.hh index 5b29cc089c0..1d84349ba43 100644 --- a/source/blender/draw/engines/eevee/eevee_hizbuffer.hh +++ b/source/blender/draw/engines/eevee/eevee_hizbuffer.hh @@ -42,6 +42,8 @@ class HiZBuffer { DRWPass *hiz_update_ps_; /** References only. */ GPUTexture *input_depth_tx_ = nullptr; + /** Dirty flag to check if the update is necessary. */ + bool is_dirty_ = true; public: HiZBuffer(Instance &inst) : inst_(inst){}; @@ -50,13 +52,16 @@ class HiZBuffer { void view_sync(int2 extent); void end_sync(); - void prepare(GPUTexture *depth_src_tx); - void update(GPUTexture *depth_src); - GPUTexture *texture_get(void) const + GPUTexture **texture_ref_get(void) + { + return &hiz_tx_; + } + + void set_dirty() { - return hiz_tx_; + is_dirty_ = true; } private: diff --git a/source/blender/draw/engines/eevee/eevee_instance.cc b/source/blender/draw/engines/eevee/eevee_instance.cc index 59270029a98..e733cf6ee06 100644 --- a/source/blender/draw/engines/eevee/eevee_instance.cc +++ b/source/blender/draw/engines/eevee/eevee_instance.cc @@ -109,6 +109,11 @@ void Instance::update_eval_members(void) void Instance::begin_sync() { + /* Must be sync before views. */ + gbuffer.begin_sync(); + hiz_front.begin_sync(); + hiz_back.begin_sync(); + camera.sync(); render_passes.sync(); shading_passes.sync(); @@ -225,6 +230,8 @@ void Instance::end_sync(void) render_passes.end_sync(); lightprobes.end_sync(); subsurface.end_sync(); + hiz_front.end_sync(); + hiz_back.end_sync(); } void Instance::render_sync(void) diff --git a/source/blender/draw/engines/eevee/eevee_instance.hh b/source/blender/draw/engines/eevee/eevee_instance.hh index 531f492be8f..cef355b6b0f 100644 --- a/source/blender/draw/engines/eevee/eevee_instance.hh +++ b/source/blender/draw/engines/eevee/eevee_instance.hh @@ -58,7 +58,9 @@ class Instance { LightModule lights; LightProbeModule lightprobes; RaytracingModule raytracing; + GBuffer gbuffer; HiZBufferModule hiz; + HiZBuffer hiz_front, hiz_back; /* TODO(fclem) Move it to scene layer data. */ ShadowModule shadows; SubsurfaceModule subsurface; @@ -103,7 +105,10 @@ class Instance { lights(*this), lightprobes(*this), raytracing(*this), + gbuffer(*this), hiz(*this), + hiz_front(*this), + hiz_back(*this), shadows(*this), subsurface(*this), sync(*this), diff --git a/source/blender/draw/engines/eevee/eevee_light.cc b/source/blender/draw/engines/eevee/eevee_light.cc index a75417ac0b7..fa7b5812d17 100644 --- a/source/blender/draw/engines/eevee/eevee_light.cc +++ b/source/blender/draw/engines/eevee/eevee_light.cc @@ -393,7 +393,7 @@ void LightModule::debug_end_sync(void) DRW_shgroup_storage_block_ref(grp, "lights_cull_buf", &culling_data); DRW_shgroup_storage_block_ref(grp, "lights_zbin_buf", &culling_zbin_buf); DRW_shgroup_storage_block_ref(grp, "lights_tile_buf", &culling_tile_buf); - DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_); + DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get()); DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); } @@ -444,13 +444,11 @@ void LightModule::set_view(const DRWView *view, DRW_draw_pass(culling_ps_); } -void LightModule::debug_draw(GPUFrameBuffer *view_fb, HiZBuffer &hiz) +void LightModule::debug_draw(GPUFrameBuffer *view_fb) { if (debug_draw_ps_ == nullptr) { return; } - input_depth_tx_ = hiz.texture_get(); - GPU_framebuffer_bind(view_fb); DRW_draw_pass(debug_draw_ps_); } diff --git a/source/blender/draw/engines/eevee/eevee_light.hh b/source/blender/draw/engines/eevee/eevee_light.hh index 63d723d5df0..3f7817036d2 100644 --- a/source/blender/draw/engines/eevee/eevee_light.hh +++ b/source/blender/draw/engines/eevee/eevee_light.hh @@ -122,7 +122,7 @@ class LightModule { void shgroup_resources(DRWShadingGroup *grp); void debug_end_sync(void); - void debug_draw(GPUFrameBuffer *view_fb, HiZBuffer &hiz); + void debug_draw(GPUFrameBuffer *view_fb); }; /** \} */ diff --git a/source/blender/draw/engines/eevee/eevee_lightprobe.cc b/source/blender/draw/engines/eevee/eevee_lightprobe.cc index 346fabc3fb1..4b4ab02e217 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobe.cc +++ b/source/blender/draw/engines/eevee/eevee_lightprobe.cc @@ -211,7 +211,7 @@ void LightProbeModule::cubemap_render(void) { DRW_stats_group_start("Cubemap Render"); for (auto i : IndexRange(ARRAY_SIZE(probe_views_))) { - probe_views_[i].render(); + probe_views_[i].render(cube_depth_tx_); } DRW_stats_group_end(); diff --git a/source/blender/draw/engines/eevee/eevee_material.cc b/source/blender/draw/engines/eevee/eevee_material.cc index 56841b67a4d..8406ee8fec6 100644 --- a/source/blender/draw/engines/eevee/eevee_material.cc +++ b/source/blender/draw/engines/eevee/eevee_material.cc @@ -245,10 +245,10 @@ MaterialPass MaterialModule::material_pass_get(::Material *blender_mat, Material &MaterialModule::material_sync(::Material *blender_mat, eMaterialGeometry geometry_type) { eMaterialPipeline surface_pipe = (blender_mat->blend_method == MA_BM_BLEND) ? MAT_PIPE_FORWARD : - MAT_PIPE_FORWARD; + MAT_PIPE_DEFERRED; eMaterialPipeline prepass_pipe = (blender_mat->blend_method == MA_BM_BLEND) ? MAT_PIPE_FORWARD_PREPASS : - MAT_PIPE_FORWARD_PREPASS; + MAT_PIPE_DEFERRED_PREPASS; MaterialKey material_key(blender_mat, geometry_type, surface_pipe); diff --git a/source/blender/draw/engines/eevee/eevee_raytracing.cc b/source/blender/draw/engines/eevee/eevee_raytracing.cc index 4280e6d9d3f..9bc37958215 100644 --- a/source/blender/draw/engines/eevee/eevee_raytracing.cc +++ b/source/blender/draw/engines/eevee/eevee_raytracing.cc @@ -27,27 +27,27 @@ void RaytracingModule::sync(void) { SceneEEVEE &sce_eevee = inst_.scene->eevee; - reflection_data_.thickness = sce_eevee.ssr_thickness; - reflection_data_.brightness_clamp = (sce_eevee.ssr_firefly_fac < 1e-8f) ? - FLT_MAX : - sce_eevee.ssr_firefly_fac; - reflection_data_.max_roughness = sce_eevee.ssr_max_roughness + 0.01f; - reflection_data_.quality = 1.0f - 0.95f * sce_eevee.ssr_quality; - reflection_data_.bias = 0.8f + sce_eevee.ssr_quality * 0.15f; - reflection_data_.pool_offset = inst_.sampling.sample_get() / 5; - - refraction_data_ = static_cast<RaytraceData>(reflection_data_); - // refraction_data_.thickness = 1e16; + reflection_data.thickness = sce_eevee.ssr_thickness; + reflection_data.brightness_clamp = (sce_eevee.ssr_firefly_fac < 1e-8f) ? + FLT_MAX : + sce_eevee.ssr_firefly_fac; + reflection_data.max_roughness = sce_eevee.ssr_max_roughness + 0.01f; + reflection_data.quality = 1.0f - 0.95f * sce_eevee.ssr_quality; + reflection_data.bias = 0.8f + sce_eevee.ssr_quality * 0.15f; + reflection_data.pool_offset = inst_.sampling.sample_get() / 5; + + refraction_data = static_cast<RaytraceData>(reflection_data); + // refraction_data.thickness = 1e16; /* TODO(fclem): Clamp option for refraction. */ /* TODO(fclem): bias option for refraction. */ /* TODO(fclem): bias option for refraction. */ - diffuse_data_ = static_cast<RaytraceData>(reflection_data_); - diffuse_data_.max_roughness = 1.01f; + diffuse_data = static_cast<RaytraceData>(reflection_data); + diffuse_data.max_roughness = 1.01f; - reflection_data_.push_update(); - refraction_data_.push_update(); - diffuse_data_.push_update(); + reflection_data.push_update(); + refraction_data.push_update(); + diffuse_data.push_update(); // enabled_ = (sce_eevee.flag & SCE_EEVEE_RAYTRACING_ENABLED) != 0; } @@ -84,7 +84,7 @@ void RaytraceBuffer::sync(int2 extent) GPUShader *sh = inst_.shaders.static_shader_get(do_rt ? RAYTRACE_REFLECTION : RAYTRACE_REFLECTION_FALLBACK); grps[0] = DRW_shgroup_create(sh, trace_reflection_ps_); - DRW_shgroup_uniform_block(grps[0], "raytrace_buf", inst_.raytracing.reflection_ubo_get()); + DRW_shgroup_uniform_block(grps[0], "raytrace_buf", inst_.raytracing.reflection_data); DRW_shgroup_stencil_set(grps[0], 0x0, 0x0, CLOSURE_REFLECTION); } { @@ -92,7 +92,7 @@ void RaytraceBuffer::sync(int2 extent) GPUShader *sh = inst_.shaders.static_shader_get(do_rt ? RAYTRACE_REFRACTION : RAYTRACE_REFRACTION_FALLBACK); grps[1] = DRW_shgroup_create(sh, trace_refraction_ps_); - DRW_shgroup_uniform_block(grps[1], "raytrace_buf", inst_.raytracing.refraction_ubo_get()); + DRW_shgroup_uniform_block(grps[1], "raytrace_buf", inst_.raytracing.refraction_data); DRW_shgroup_stencil_set(grps[1], 0x0, 0x0, CLOSURE_REFRACTION); } { @@ -100,7 +100,7 @@ void RaytraceBuffer::sync(int2 extent) GPUShader *sh = inst_.shaders.static_shader_get(do_rt ? RAYTRACE_DIFFUSE : RAYTRACE_DIFFUSE_FALLBACK); grps[2] = DRW_shgroup_create(sh, trace_diffuse_ps_); - DRW_shgroup_uniform_block(grps[2], "raytrace_buf", inst_.raytracing.diffuse_ubo_get()); + DRW_shgroup_uniform_block(grps[2], "raytrace_buf", inst_.raytracing.diffuse_data); DRW_shgroup_stencil_set(grps[2], 0x0, 0x0, CLOSURE_DIFFUSE); } @@ -144,7 +144,7 @@ void RaytraceBuffer::sync(int2 extent) for (DRWShadingGroup *grp : grps) { /* Does not matter which raytrace_block we use. */ - DRW_shgroup_uniform_block(grp, "raytrace_buf", inst_.raytracing.diffuse_ubo_get()); + DRW_shgroup_uniform_block(grp, "raytrace_buf", inst_.raytracing.diffuse_data); DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get()); DRW_shgroup_uniform_block(grp, "rtbuf_buf", data_); DRW_shgroup_uniform_texture_ref_ex(grp, "ray_data_tx", &input_ray_data_tx_, no_interp); @@ -198,13 +198,12 @@ void RaytraceBuffer::sync(int2 extent) } } -void RaytraceBuffer::trace(eClosureBits closure_type, - GBuffer &gbuffer, - HiZBuffer &hiz, - HiZBuffer &hiz_front) +void RaytraceBuffer::trace(eClosureBits UNUSED(closure_type), + GBuffer &UNUSED(gbuffer), + HiZBuffer &UNUSED(hiz), + HiZBuffer &UNUSED(hiz_front)) { - gbuffer.bind_tracing(); - +#if 0 input_hiz_tx_ = hiz.texture_get(); input_hiz_front_tx_ = hiz_front.texture_get(); if (closure_type == CLOSURE_REFLECTION) { @@ -237,10 +236,12 @@ void RaytraceBuffer::trace(eClosureBits closure_type, input_ray_data_tx_ = gbuffer.ray_data_tx; input_ray_color_tx_ = gbuffer.ray_radiance_tx; +#endif } -void RaytraceBuffer::denoise(eClosureBits closure_type) +void RaytraceBuffer::denoise(eClosureBits UNUSED(closure_type)) { +#if 0 switch (closure_type) { default: case CLOSURE_REFLECTION: @@ -265,10 +266,12 @@ void RaytraceBuffer::denoise(eClosureBits closure_type) DRW_draw_pass(denoise_diffuse_ps_); break; } +#endif } -void RaytraceBuffer::resolve(eClosureBits closure_type, GBuffer &gbuffer) +void RaytraceBuffer::resolve(eClosureBits UNUSED(closure_type), GBuffer &UNUSED(gbuffer)) { +#if 0 gbuffer.bind_radiance(); switch (closure_type) { default: @@ -282,6 +285,7 @@ void RaytraceBuffer::resolve(eClosureBits closure_type, GBuffer &gbuffer) DRW_draw_pass(resolve_diffuse_ps_); break; } +#endif } /** \} */ diff --git a/source/blender/draw/engines/eevee/eevee_raytracing.hh b/source/blender/draw/engines/eevee/eevee_raytracing.hh index c44c2b56099..71452e23478 100644 --- a/source/blender/draw/engines/eevee/eevee_raytracing.hh +++ b/source/blender/draw/engines/eevee/eevee_raytracing.hh @@ -18,13 +18,14 @@ class Instance; * \{ */ class RaytracingModule { + public: + RaytraceDataBuf reflection_data; + RaytraceDataBuf refraction_data; + RaytraceDataBuf diffuse_data; + private: Instance &inst_; - RaytraceDataBuf reflection_data_; - RaytraceDataBuf refraction_data_; - RaytraceDataBuf diffuse_data_; - bool enabled_ = false; public: @@ -32,19 +33,6 @@ class RaytracingModule { void sync(void); - const GPUUniformBuf *reflection_ubo_get(void) const - { - return reflection_data_; - } - const GPUUniformBuf *refraction_ubo_get(void) const - { - return refraction_data_; - } - const GPUUniformBuf *diffuse_ubo_get(void) const - { - return diffuse_data_; - } - bool enabled(void) const { return enabled_; diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.hh b/source/blender/draw/engines/eevee/eevee_renderpasses.hh index e25f7cf79d1..7da77ac90f0 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.hh +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.hh @@ -29,6 +29,10 @@ enum eRenderPassBit { RENDERPASS_DEPTH = (1 << 1), RENDERPASS_NORMAL = (1 << 2), RENDERPASS_VECTOR = (1 << 3), + RENDERPASS_EMISSION = (1 << 4), + RENDERPASS_DIFFUSE_COLOR = (1 << 5), + RENDERPASS_SPECULAR_COLOR = (1 << 6), + RENDERPASS_VOLUME_LIGHT = (1 << 7), /** Used for iterator. */ RENDERPASS_MAX, RENDERPASS_ALL = ((RENDERPASS_MAX - 1) << 1) - 1, @@ -43,6 +47,10 @@ static inline eRenderPassBit to_render_passes_bits(int i_rpasses) SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_Z, RENDERPASS_DEPTH); SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_NORMAL, RENDERPASS_NORMAL); SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_VECTOR, RENDERPASS_VECTOR); + SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_EMIT, RENDERPASS_EMISSION); + SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_DIFFUSE_COLOR, RENDERPASS_DIFFUSE_COLOR); + SET_FLAG_FROM_TEST(rpasses, i_rpasses & SCE_PASS_GLOSSY_COLOR, RENDERPASS_SPECULAR_COLOR); + /* RENDERPASS_VOLUME_LIGHT? */ return rpasses; } @@ -57,6 +65,14 @@ static inline const char *to_render_passes_name(eRenderPassBit rpass) return RE_PASSNAME_NORMAL; case RENDERPASS_VECTOR: return RE_PASSNAME_VECTOR; + case RENDERPASS_EMISSION: + return RE_PASSNAME_EMIT; + case RENDERPASS_DIFFUSE_COLOR: + return RE_PASSNAME_DIFFUSE_COLOR; + case RENDERPASS_SPECULAR_COLOR: + return RE_PASSNAME_GLOSSY_COLOR; + case RENDERPASS_VOLUME_LIGHT: + return RE_PASSNAME_VOLUME_LIGHT; default: BLI_assert(0); return ""; @@ -67,6 +83,10 @@ static inline eFilmDataType to_render_passes_data_type(eRenderPassBit rpass, const bool use_log_encoding) { switch (rpass) { + case RENDERPASS_EMISSION: + case RENDERPASS_DIFFUSE_COLOR: + case RENDERPASS_SPECULAR_COLOR: + case RENDERPASS_VOLUME_LIGHT: case RENDERPASS_COMBINED: return (use_log_encoding) ? FILM_DATA_COLOR_LOG : FILM_DATA_COLOR; case RENDERPASS_DEPTH: @@ -97,12 +117,26 @@ class RenderPasses { Film *depth = nullptr; Film *normal = nullptr; Film *vector = nullptr; + Film *emission = nullptr; + Film *diffuse_color = nullptr; + Film *diffuse_light = nullptr; + Film *specular_color = nullptr; + Film *specular_light = nullptr; + Film *volume_light = nullptr; Vector<Film *> aovs; + /** View texture to render to. */ + TextureFromPool emission_tx = {"PassEmission"}; + TextureFromPool diffuse_color_tx = {"PassDiffuseColor"}; + TextureFromPool specular_color_tx = {"PassSpecularColor"}; + TextureFromPool volume_light_tx = {"PassVolumeLight"}; private: Instance &inst_; eRenderPassBit enabled_passes_ = RENDERPASS_NONE; + /* Maximum texture size. Since we use imageLoad/Store instead of framebuffer, we only need to + * allocate the biggest texture. */ + int2 tmp_extent_ = int2(-1); public: RenderPasses(Instance &inst) : inst_(inst){}; @@ -113,6 +147,9 @@ class RenderPasses { delete depth; delete normal; delete vector; + for (Film *&film : aovs) { + delete film; + } } void init(const int extent[2], const rcti *output_rect); @@ -122,6 +159,16 @@ class RenderPasses { for (RenderPassItem rpi : *this) { rpi.film->sync(); } + emission_tx.sync(); + diffuse_color_tx.sync(); + specular_color_tx.sync(); + volume_light_tx.sync(); + tmp_extent_ = int2(-1); + } + + void view_sync(int2 view_extent) + { + tmp_extent_ = math::max(tmp_extent_, view_extent); } void end_sync(void) @@ -131,6 +178,25 @@ class RenderPasses { } } + void acquire() + { + auto acquire_tmp_pass_buffer = [&](TextureFromPool &texture, bool enabled_pass) { + texture.acquire(enabled_pass ? tmp_extent_ : int2(1), GPU_RGBA16F, (void *)&inst_); + }; + acquire_tmp_pass_buffer(emission_tx, enabled_passes_ & RENDERPASS_EMISSION); + acquire_tmp_pass_buffer(diffuse_color_tx, enabled_passes_ & RENDERPASS_DIFFUSE_COLOR); + acquire_tmp_pass_buffer(specular_color_tx, enabled_passes_ & RENDERPASS_SPECULAR_COLOR); + acquire_tmp_pass_buffer(volume_light_tx, enabled_passes_ & RENDERPASS_VOLUME_LIGHT); + } + + void release() + { + emission_tx.release(); + diffuse_color_tx.release(); + specular_color_tx.release(); + volume_light_tx.release(); + } + void resolve_viewport(DefaultFramebufferList *dfbl) { for (RenderPassItem rpi : *this) { @@ -168,6 +234,14 @@ class RenderPasses { return normal; case RENDERPASS_VECTOR: return vector; + case RENDERPASS_EMISSION: + return emission; + case RENDERPASS_DIFFUSE_COLOR: + return vector; + case RENDERPASS_SPECULAR_COLOR: + return vector; + case RENDERPASS_VOLUME_LIGHT: + return vector; default: BLI_assert(0); return combined; diff --git a/source/blender/draw/engines/eevee/eevee_shader.cc b/source/blender/draw/engines/eevee/eevee_shader.cc index 53d6417e2b2..3a1c1109095 100644 --- a/source/blender/draw/engines/eevee/eevee_shader.cc +++ b/source/blender/draw/engines/eevee/eevee_shader.cc @@ -95,14 +95,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ case FILM_RESOLVE_DEPTH: return "eevee_film_resolve_depth"; - case DEFERRED_EVAL_DIRECT: - return "eevee_deferred_direct"; - case DEFERRED_EVAL_HOLDOUT: - return "eevee_deferred_holdout"; - case DEFERRED_EVAL_TRANSPARENT: - return "eevee_deferred_transparent"; - case DEFERRED_EVAL_VOLUME: - return "eevee_deferred_volume"; + case DEFERRED_EVAL: + return "eevee_deferred_eval"; case DEFERRED_VOLUME: return "eevee_volume_deferred"; diff --git a/source/blender/draw/engines/eevee/eevee_shader.hh b/source/blender/draw/engines/eevee/eevee_shader.hh index 7f306e2d6e0..33a27e04df7 100644 --- a/source/blender/draw/engines/eevee/eevee_shader.hh +++ b/source/blender/draw/engines/eevee/eevee_shader.hh @@ -30,10 +30,7 @@ enum eShaderType { CULLING_SORT, CULLING_TILE, - DEFERRED_EVAL_DIRECT, - DEFERRED_EVAL_HOLDOUT, - DEFERRED_EVAL_TRANSPARENT, - DEFERRED_EVAL_VOLUME, + DEFERRED_EVAL, DEFERRED_VOLUME, diff --git a/source/blender/draw/engines/eevee/eevee_shading.cc b/source/blender/draw/engines/eevee/eevee_shading.cc index 55cc0bbdc96..fc64c76c933 100644 --- a/source/blender/draw/engines/eevee/eevee_shading.cc +++ b/source/blender/draw/engines/eevee/eevee_shading.cc @@ -100,14 +100,14 @@ DRWShadingGroup *ForwardPass::material_opaque_add(::Material *blender_mat, GPUMa grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get()); } if (raytracing.enabled()) { - DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_ubo_get()); - DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_ubo_get()); - DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_ubo_get()); - DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_radiance_tx_, no_interp); + DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data); + DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data); + DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data); + DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_screen_radiance_tx_, no_interp); } if (raytracing.enabled()) { DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get()); - DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_); + DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get()); } return grp; } @@ -142,14 +142,15 @@ DRWShadingGroup *ForwardPass::material_transparent_add(::Material *blender_mat, grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get()); } if (raytracing.enabled()) { - DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_ubo_get()); - DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_ubo_get()); - DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_ubo_get()); - DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_radiance_tx_, no_interp); + DRW_shgroup_uniform_block(grp, "rt_diffuse_buf", raytracing.diffuse_data); + DRW_shgroup_uniform_block(grp, "rt_reflection_buf", raytracing.reflection_data); + DRW_shgroup_uniform_block(grp, "rt_refraction_buf", raytracing.refraction_data); + DRW_shgroup_uniform_texture_ref_ex( + grp, "rt_radiance_tx", &input_screen_radiance_tx_, no_interp); } if (raytracing.enabled()) { DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get()); - DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_); + DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", inst_.hiz_front.texture_ref_get()); } DRWState state_disable = DRW_STATE_WRITE_DEPTH; @@ -181,34 +182,23 @@ DRWShadingGroup *ForwardPass::prepass_transparent_add(::Material *blender_mat, G } void ForwardPass::render(const DRWView *view, - GBuffer &gbuffer, - HiZBuffer &hiz, - GPUFrameBuffer *view_fb) + GPUTexture *depth_tx, + GPUTexture *UNUSED(combined_tx)) { - if (inst_.raytracing.enabled()) { - int2 extent = {GPU_texture_width(gbuffer.depth_tx), GPU_texture_height(gbuffer.depth_tx)}; - /* Reuse texture. */ - gbuffer.ray_radiance_tx.acquire(extent, GPU_RGBA16F, gbuffer.owner); - /* Copy combined buffer so we can sample from it. */ - GPU_texture_copy(gbuffer.ray_radiance_tx, gbuffer.combined_tx); - - input_radiance_tx_ = gbuffer.ray_radiance_tx; - - hiz.prepare(gbuffer.depth_tx); - /* TODO(fclem): Avoid this if possible. */ - hiz.update(gbuffer.depth_tx); - - input_hiz_tx_ = hiz.texture_get(); - } + HiZBuffer &hiz = inst_.hiz_front; DRW_stats_group_start("ForwardOpaque"); - GPU_framebuffer_bind(view_fb); DRW_draw_pass(prepass_ps_); + hiz.set_dirty(); - inst_.shadows.set_view(view, gbuffer.depth_tx); + if (inst_.raytracing.enabled()) { + // rt_buffer.radiance_copy(combined_tx); + hiz.update(depth_tx); + } + + inst_.shadows.set_view(view, depth_tx); - GPU_framebuffer_bind(view_fb); DRW_draw_pass(opaque_ps_); DRW_stats_group_end(); @@ -222,18 +212,146 @@ void ForwardPass::render(const DRWView *view, DRW_stats_group_end(); if (inst_.raytracing.enabled()) { - gbuffer.ray_radiance_tx.release(); + // gbuffer.ray_radiance_tx.release(); } } /** \} */ /* -------------------------------------------------------------------- */ +/** \name DeferredPass + * \{ */ + +void DeferredPass::sync(void) +{ + opaque_layer_.sync(); + refraction_layer_.sync(); + volumetric_layer_.sync(); + + LightModule &lights = inst_.lights; + LightProbeModule &lightprobes = inst_.lightprobes; + GBuffer &gbuf = inst_.gbuffer; + HiZBuffer &hiz = inst_.hiz_front; + + eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT; + + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_BLEND_ADD_FULL; + eval_ps_ = DRW_pass_create("DeferredEval", state); + GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL); + DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_ps_); + lights.shgroup_resources(grp); + DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get()); + DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", hiz.texture_ref_get()); + DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get()); + DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get()); + DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.shading_passes.utility_tx); + DRW_shgroup_uniform_texture_ref(grp, "transmit_color_tx", &gbuf.transmit_color_tx); + DRW_shgroup_uniform_texture_ref(grp, "transmit_normal_tx", &gbuf.transmit_normal_tx); + DRW_shgroup_uniform_texture_ref(grp, "transmit_data_tx", &gbuf.transmit_data_tx); + DRW_shgroup_uniform_texture_ref(grp, "reflect_color_tx", &gbuf.reflect_color_tx); + DRW_shgroup_uniform_texture_ref(grp, "reflect_normal_tx", &gbuf.reflect_normal_tx); + DRW_shgroup_uniform_image_ref(grp, "rpass_diffuse_light", &gbuf.rpass_diffuse_light_tx); + DRW_shgroup_uniform_image_ref(grp, "rpass_specular_light", &gbuf.rpass_specular_light_tx); + // DRW_shgroup_uniform_image_ref(grp, "ray_data", &gbuf.rpass_specular_light_tx); + DRW_shgroup_uniform_image_ref(grp, "sss_radiance", &gbuf.radiance_diffuse_tx); + DRW_shgroup_uniform_texture_ref( + grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get()); + DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_DIFFUSE | CLOSURE_REFLECTION); + /* Sync with the Gbuffer pass. */ + DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH); + DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); + } + { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_BLEND_ADD_FULL; + eval_subsurface_ps_ = DRW_pass_create("SubsurfaceEval", state); + GPUShader *sh = inst_.shaders.static_shader_get(SUBSURFACE_EVAL); + DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_subsurface_ps_); + DRW_shgroup_uniform_block(grp, "sss_buf", inst_.subsurface.ubo_get()); + DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get()); + DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", hiz.texture_ref_get()); + DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &gbuf.radiance_diffuse_tx, no_interp); + DRW_shgroup_uniform_texture_ref(grp, "transmit_color_tx", &gbuf.transmit_color_tx); + DRW_shgroup_uniform_texture_ref(grp, "transmit_normal_tx", &gbuf.transmit_normal_tx); + DRW_shgroup_uniform_texture_ref(grp, "transmit_data_tx", &gbuf.transmit_data_tx); + DRW_shgroup_stencil_set(grp, 0x0, 0xFF, CLOSURE_SSS); + /* Sync with the DeferredEval pass. */ + DRW_shgroup_barrier(grp, GPU_BARRIER_TEXTURE_FETCH); + DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); + } +} + +DRWShadingGroup *DeferredPass::material_add(::Material *material, GPUMaterial *gpumat) +{ + if (material->blend_flag & MA_BL_SS_REFRACTION) { + return refraction_layer_.material_add(material, gpumat); + } + else { + return opaque_layer_.material_add(material, gpumat); + } +} + +DRWShadingGroup *DeferredPass::prepass_add(::Material *material, GPUMaterial *gpumat) +{ + if (material->blend_flag & MA_BL_SS_REFRACTION) { + return refraction_layer_.prepass_add(material, gpumat); + } + else { + return opaque_layer_.prepass_add(material, gpumat); + } +} + +void DeferredPass::volume_add(Object *ob) +{ + volumetric_layer_.volume_add(ob); +} + +void DeferredPass::render(const DRWView *drw_view, + RaytraceBuffer &rt_buffer_opaque_, + RaytraceBuffer &rt_buffer_refract_, + GPUTexture *depth_tx, + GPUTexture *combined_tx) +{ + DRW_stats_group_start("OpaqueLayer"); + opaque_layer_.render(drw_view, &rt_buffer_opaque_, depth_tx, combined_tx); + DRW_stats_group_end(); + + DRW_stats_group_start("RefractionLayer"); + refraction_layer_.render(drw_view, &rt_buffer_refract_, depth_tx, combined_tx); + DRW_stats_group_end(); + + DRW_stats_group_start("VolumetricLayer"); + volumetric_layer_.render(drw_view, nullptr, depth_tx, combined_tx); + DRW_stats_group_end(); + + rt_buffer_opaque_.render_end(drw_view); + rt_buffer_refract_.render_end(drw_view); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name DeferredLayer * \{ */ +void DeferredLayer::deferred_shgroup_resources(DRWShadingGroup *grp) +{ + GBuffer &gbuf = inst_.gbuffer; + /* Gbuffer. */ + DRW_shgroup_uniform_image_ref(grp, "gbuff_transmit_color", &gbuf.transmit_color_tx); + DRW_shgroup_uniform_image_ref(grp, "gbuff_transmit_data", &gbuf.transmit_data_tx); + DRW_shgroup_uniform_image_ref(grp, "gbuff_transmit_normal", &gbuf.transmit_normal_tx); + DRW_shgroup_uniform_image_ref(grp, "gbuff_reflection_color", &gbuf.reflect_color_tx); + DRW_shgroup_uniform_image_ref(grp, "gbuff_reflection_normal", &gbuf.reflect_normal_tx); + /* Renderpasses. */ + DRW_shgroup_uniform_image_ref(grp, "rpass_emission", &gbuf.rpass_emission_tx); + DRW_shgroup_uniform_image_ref(grp, "rpass_volume_light", &gbuf.rpass_volume_light_tx); +} + void DeferredLayer::sync(void) { + closure_bits_ = eClosureBits(0); + { DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; prepass_ps_ = DRW_pass_create("Gbuffer.Prepass", state); @@ -245,7 +363,7 @@ void DeferredLayer::sync(void) } { DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_STENCIL_ALWAYS | - DRW_STATE_WRITE_STENCIL; + DRW_STATE_WRITE_STENCIL | DRW_STATE_BLEND_CUSTOM; gbuffer_ps_ = DRW_pass_create("Gbuffer", state); state |= DRW_STATE_CULL_BACK; @@ -262,15 +380,16 @@ void DeferredLayer::sync(void) DRWShadingGroup *DeferredLayer::material_add(::Material *blender_mat, GPUMaterial *gpumat) { - /* TODO/OPTI(fclem) Set the right mask for each effect based on gpumat flags. */ - uint stencil_mask = CLOSURE_DIFFUSE | CLOSURE_SSS | CLOSURE_REFLECTION | CLOSURE_TRANSPARENCY | - CLOSURE_EMISSION | CLOSURE_REFRACTION; + eClosureBits closure_bits = extract_closure_mask(gpumat); DRWPass *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ? gbuffer_culled_ps_ : gbuffer_ps_; DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, pass); DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get()); DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.shading_passes.utility_tx); - DRW_shgroup_stencil_set(grp, stencil_mask, 0xFF, 0xFF); + deferred_shgroup_resources(grp); + DRW_shgroup_stencil_set(grp, (uint)closure_bits & 0xFF, 0xFF, 0xFF); + + closure_bits_ |= closure_bits; return grp; } @@ -284,6 +403,8 @@ DRWShadingGroup *DeferredLayer::prepass_add(::Material *blender_mat, GPUMaterial void DeferredLayer::volume_add(Object *ob) { + (void)ob; +#if 0 /* TODO */ LightModule &lights = inst_.lights; DeferredPass &deferred_pass = inst_.shading_passes.deferred; @@ -294,294 +415,69 @@ void DeferredLayer::volume_add(Object *ob) DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.shading_passes.utility_tx); DRW_shgroup_stencil_set(grp, CLOSURE_VOLUME | CLOSURE_TRANSPARENCY, 0xFF, 0xFF); DRW_shgroup_call(grp, DRW_cache_cube_get(), ob); +#endif } void DeferredLayer::render(const DRWView *view, - GBuffer &gbuffer, - HiZBuffer &hiz_front, - HiZBuffer &hiz_back, - RaytraceBuffer &rt_buffer, - GPUFrameBuffer *view_fb) + RaytraceBuffer *UNUSED(rt_buffer), + GPUTexture *depth_tx, + GPUTexture *UNUSED(combined_tx)) { DeferredPass &deferred_pass = inst_.shading_passes.deferred; + GBuffer &gbuffer = inst_.gbuffer; + HiZBuffer &hiz_front = inst_.hiz_front; + HiZBuffer &hiz_back = inst_.hiz_back; const bool no_surfaces = DRW_pass_is_empty(gbuffer_ps_); const bool no_volumes = DRW_pass_is_empty(volume_ps_); if (no_surfaces && no_volumes) { return; } - /* TODO(fclem): detect these cases. */ - const bool use_diffuse = true; - const bool use_subsurface = true; - const bool use_transparency = true; - const bool use_holdout = true; - const bool use_refraction = true; - const bool use_glossy = true; - const bool use_ao = false; - - gbuffer.prepare((eClosureBits)0xFFFFFFFFu); - if (use_ao || use_glossy || use_diffuse) { - hiz_front.prepare(gbuffer.depth_tx); - } + const bool use_subsurface = closure_bits_ & CLOSURE_SSS; + const bool use_refraction = closure_bits_ & CLOSURE_REFRACTION; + + gbuffer.acquire(closure_bits_); + if (use_refraction) { - hiz_back.prepare(gbuffer.depth_tx); + // rt_buffer->radiance_copy(view_fb); } - update_pass_inputs(gbuffer, hiz_front, hiz_back); - if (use_refraction) { - /* TODO(fclem) Only update if needed. - * i.e: No need when SSR from previous layer has already updated hiz. */ - hiz_back.update(gbuffer.depth_tx); + hiz_back.update(depth_tx); } - gbuffer.bind(); + GPU_framebuffer_clear_stencil(GPU_framebuffer_active_get(), 0x00u); if (!no_surfaces) { DRW_draw_pass(prepass_ps_); - - /* TODO(fclem): Ambient Occlusion texture node. */ - if (use_ao) { - hiz_front.update(gbuffer.depth_tx); - gbuffer.bind(); - } - - DRW_draw_pass(gbuffer_ps_); - } - - inst_.shadows.set_view(view, gbuffer.depth_tx); - - if (!no_volumes) { - // gbuffer.copy_depth_behind(); - // deferred_pass.input_depth_behind_tx_ = gbuffer.depth_behind_tx; - - gbuffer.bind_volume(); - DRW_draw_pass(volume_ps_); - } - - if (use_holdout) { - gbuffer.bind_holdout(); - DRW_draw_pass(deferred_pass.eval_holdout_ps_); - } - - /* TODO(fclem) We could bypass update if ao already updated it and if there is no volume. */ - hiz_front.update(gbuffer.depth_tx); - - if (!no_surfaces && use_refraction) { - /* Launch and shade refraction rays before transparency changes the combined pass. */ - rt_buffer.trace(CLOSURE_REFRACTION, gbuffer, hiz_back, hiz_front); - } - - GPU_framebuffer_bind(view_fb); - if (use_transparency) { - DRW_draw_pass(deferred_pass.eval_transparency_ps_); + hiz_front.set_dirty(); + hiz_back.set_dirty(); } - gbuffer.clear_radiance(); + hiz_front.update(depth_tx); + inst_.shadows.set_view(view, depth_tx); - if (!no_surfaces && use_refraction) { - rt_buffer.denoise(CLOSURE_REFRACTION); - rt_buffer.resolve(CLOSURE_REFRACTION, gbuffer); + if (!no_surfaces) { + DRW_draw_pass(gbuffer_ps_); } if (!no_volumes) { - /* TODO(fclem) volume fb. */ - GPU_framebuffer_bind(view_fb); - DRW_draw_pass(deferred_pass.eval_volume_homogeneous_ps_); + // DRW_draw_pass(volume_ps_); } if (!no_surfaces) { - gbuffer.bind_radiance(); - DRW_draw_pass(deferred_pass.eval_direct_ps_); + // DRW_draw_pass(deferred_pass.raygen_ps_); - if (use_diffuse) { - rt_buffer.trace(CLOSURE_DIFFUSE, gbuffer, hiz_front, hiz_front); - rt_buffer.denoise(CLOSURE_DIFFUSE); - rt_buffer.resolve(CLOSURE_DIFFUSE, gbuffer); - } + // rt_buffer->trace(closure_bits_, gbuffer, hiz_back, hiz_front, radiance_copy_tx); - if (use_subsurface) { - GPU_framebuffer_bind(view_fb); - DRW_draw_pass(deferred_pass.eval_subsurface_ps_); - } + DRW_draw_pass(deferred_pass.eval_ps_); - if (use_glossy) { - rt_buffer.trace(CLOSURE_REFLECTION, gbuffer, hiz_front, hiz_front); - rt_buffer.denoise(CLOSURE_REFLECTION); - rt_buffer.resolve(CLOSURE_REFLECTION, gbuffer); + if (use_subsurface) { + // DRW_draw_pass(deferred_pass.eval_subsurface_ps_); } } -} - -void DeferredLayer::update_pass_inputs(GBuffer &gbuffer, HiZBuffer &hiz_front, HiZBuffer &hiz_back) -{ - DeferredPass &deferred_pass = inst_.shading_passes.deferred; - deferred_pass.input_combined_tx_ = gbuffer.combined_tx; - deferred_pass.input_emission_data_tx_ = gbuffer.emission_tx; - deferred_pass.input_transmit_color_tx_ = gbuffer.transmit_color_tx; - deferred_pass.input_transmit_normal_tx_ = gbuffer.transmit_normal_tx; - deferred_pass.input_transmit_data_tx_ = gbuffer.transmit_data_tx; - deferred_pass.input_reflect_color_tx_ = gbuffer.reflect_color_tx; - deferred_pass.input_reflect_normal_tx_ = gbuffer.reflect_normal_tx; - deferred_pass.input_diffuse_tx_ = gbuffer.diffuse_tx; - deferred_pass.input_transparency_data_tx_ = gbuffer.transparency_tx; - deferred_pass.input_volume_data_tx_ = gbuffer.volume_tx; - deferred_pass.input_hiz_front_tx_ = hiz_front.texture_get(); - deferred_pass.input_hiz_back_tx_ = hiz_back.texture_get(); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name DeferredLayer - * \{ */ - -void DeferredPass::sync(void) -{ - opaque_layer_.sync(); - refraction_layer_.sync(); - volumetric_layer_.sync(); - - LightModule &lights = inst_.lights; - LightProbeModule &lightprobes = inst_.lightprobes; - - eGPUSamplerState no_interp = GPU_SAMPLER_DEFAULT; - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_BLEND_ADD_FULL; - eval_direct_ps_ = DRW_pass_create("DeferredDirect", state); - GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL_DIRECT); - DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_direct_ps_); - lights.shgroup_resources(grp); - DRW_shgroup_uniform_block(grp, "sampling_buf", inst_.sampling.ubo_get()); - DRW_shgroup_uniform_block(grp, "grids_buf", lightprobes.grid_ubo_get()); - DRW_shgroup_uniform_block(grp, "cubes_buf", lightprobes.cube_ubo_get()); - DRW_shgroup_uniform_block(grp, "probes_buf", lightprobes.info_ubo_get()); - DRW_shgroup_uniform_texture_ref(grp, "lightprobe_grid_tx", lightprobes.grid_tx_ref_get()); - DRW_shgroup_uniform_texture_ref(grp, "lightprobe_cube_tx", lightprobes.cube_tx_ref_get()); - DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.shading_passes.utility_tx); - DRW_shgroup_uniform_texture_ref_ex( - grp, "emission_data_tx", &input_emission_data_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_color_tx", &input_transmit_color_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_normal_tx", &input_transmit_normal_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_data_tx", &input_transmit_data_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "reflect_color_tx", &input_reflect_color_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "reflect_normal_tx", &input_reflect_normal_tx_, no_interp); - DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_front_tx_); - DRW_shgroup_uniform_texture_ref( - grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get()); - DRW_shgroup_stencil_set( - grp, 0x0, 0x0, CLOSURE_DIFFUSE | CLOSURE_REFLECTION | CLOSURE_EMISSION); - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL | DRW_STATE_BLEND_ADD_FULL; - eval_subsurface_ps_ = DRW_pass_create("DeferredSubsurface", state); - GPUShader *sh = inst_.shaders.static_shader_get(SUBSURFACE_EVAL); - DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_subsurface_ps_); - DRW_shgroup_uniform_block(grp, "sss_buf", inst_.subsurface.ubo_get()); - DRW_shgroup_uniform_block(grp, "hiz_buf", inst_.hiz.ubo_get()); - DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_front_tx_); - DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_diffuse_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_color_tx", &input_transmit_color_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_normal_tx", &input_transmit_normal_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transmit_data_tx", &input_transmit_data_tx_, no_interp); - DRW_shgroup_stencil_set(grp, 0x0, 0xFF, CLOSURE_SSS); - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_BLEND_ADD_FULL; - eval_volume_homogeneous_ps_ = DRW_pass_create("DeferredVolume", state); - GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL_VOLUME); - DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_volume_homogeneous_ps_); - lights.shgroup_resources(grp); - DRW_shgroup_uniform_texture(grp, "utility_tx", inst_.shading_passes.utility_tx); - DRW_shgroup_uniform_texture_ref_ex( - grp, "transparency_data_tx", &input_transparency_data_tx_, no_interp); - DRW_shgroup_uniform_texture_ref_ex(grp, "volume_data_tx", &input_volume_data_tx_, no_interp); - DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_front_tx_); - DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_VOLUME); - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL | DRW_STATE_BLEND_MUL; - eval_transparency_ps_ = DRW_pass_create("DeferredTransparency", state); - GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL_TRANSPARENT); - DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_transparency_ps_); - DRW_shgroup_uniform_texture_ref(grp, "transparency_data_tx", &input_transparency_data_tx_); - DRW_shgroup_uniform_texture_ref_ex(grp, "volume_data_tx", &input_volume_data_tx_, no_interp); - DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_TRANSPARENCY); - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_NEQUAL; - eval_holdout_ps_ = DRW_pass_create("DeferredHoldout", state); - GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL_HOLDOUT); - DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_volume_homogeneous_ps_); - DRW_shgroup_uniform_texture_ref(grp, "combined_tx", &input_combined_tx_); - DRW_shgroup_uniform_texture_ref(grp, "transparency_data_tx", &input_transparency_data_tx_); - DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_TRANSPARENCY); - DRW_shgroup_call_procedural_triangles(grp, nullptr, 1); - } -} - -DRWShadingGroup *DeferredPass::material_add(::Material *material, GPUMaterial *gpumat) -{ - if (material->blend_flag & MA_BL_SS_REFRACTION) { - return refraction_layer_.material_add(material, gpumat); - } - else { - return opaque_layer_.material_add(material, gpumat); - } -} - -DRWShadingGroup *DeferredPass::prepass_add(::Material *material, GPUMaterial *gpumat) -{ - if (material->blend_flag & MA_BL_SS_REFRACTION) { - return refraction_layer_.prepass_add(material, gpumat); - } - else { - return opaque_layer_.prepass_add(material, gpumat); - } -} - -void DeferredPass::volume_add(Object *ob) -{ - volumetric_layer_.volume_add(ob); -} - -void DeferredPass::render(const DRWView *drw_view, - GBuffer &gbuffer, - HiZBuffer &hiz_front, - HiZBuffer &hiz_back, - RaytraceBuffer &rt_buffer_opaque_, - RaytraceBuffer &rt_buffer_refract_, - GPUFrameBuffer *view_fb) -{ - DRW_stats_group_start("OpaqueLayer"); - opaque_layer_.render(drw_view, gbuffer, hiz_front, hiz_back, rt_buffer_opaque_, view_fb); - DRW_stats_group_end(); - - DRW_stats_group_start("RefractionLayer"); - refraction_layer_.render(drw_view, gbuffer, hiz_front, hiz_back, rt_buffer_refract_, view_fb); - DRW_stats_group_end(); - - /* NOTE(fclem): Reuse the same rtbuf_buf as refraction but should not use it. */ - DRW_stats_group_start("VolumetricLayer"); - volumetric_layer_.render(drw_view, gbuffer, hiz_front, hiz_back, rt_buffer_refract_, view_fb); - DRW_stats_group_end(); - - gbuffer.render_end(); - rt_buffer_opaque_.render_end(drw_view); - rt_buffer_refract_.render_end(drw_view); + gbuffer.release(); } /** \} */ diff --git a/source/blender/draw/engines/eevee/eevee_shading.hh b/source/blender/draw/engines/eevee/eevee_shading.hh index 273b262a8dc..5d40d82f934 100644 --- a/source/blender/draw/engines/eevee/eevee_shading.hh +++ b/source/blender/draw/engines/eevee/eevee_shading.hh @@ -62,8 +62,7 @@ class ForwardPass { DRWPass *opaque_culled_ps_ = nullptr; DRWPass *transparent_ps_ = nullptr; - GPUTexture *input_hiz_tx_ = nullptr; - GPUTexture *input_radiance_tx_ = nullptr; + GPUTexture *input_screen_radiance_tx_ = nullptr; public: ForwardPass(Instance &inst) : inst_(inst){}; @@ -89,7 +88,7 @@ class ForwardPass { DRWShadingGroup *material_transparent_add(::Material *blender_mat, GPUMaterial *gpumat); DRWShadingGroup *prepass_transparent_add(::Material *blender_mat, GPUMaterial *gpumat); - void render(const DRWView *view, GBuffer &gbuffer, HiZBuffer &hiz, GPUFrameBuffer *view_fb); + void render(const DRWView *view, GPUTexture *depth_tx, GPUTexture *combined_tx); }; /** \} */ @@ -102,17 +101,15 @@ class DeferredLayer { private: Instance &inst_; - /* TODO */ - // GPUTexture *input_emission_data_tx_ = nullptr; - // GPUTexture *input_diffuse_data_tx_ = nullptr; - // GPUTexture *input_depth_tx_ = nullptr; - DRWPass *prepass_ps_ = nullptr; DRWPass *prepass_culled_ps_ = nullptr; DRWPass *gbuffer_ps_ = nullptr; DRWPass *gbuffer_culled_ps_ = nullptr; DRWPass *volume_ps_ = nullptr; + /* Closures bits from the materials in this pass. */ + eClosureBits closure_bits_; + public: DeferredLayer(Instance &inst) : inst_(inst){}; @@ -121,14 +118,12 @@ class DeferredLayer { DRWShadingGroup *prepass_add(::Material *blender_mat, GPUMaterial *gpumat); void volume_add(Object *ob); void render(const DRWView *view, - GBuffer &gbuffer, - HiZBuffer &hiz_front, - HiZBuffer &hiz_back, - RaytraceBuffer &rt_buffer, - GPUFrameBuffer *view_fb); + RaytraceBuffer *rt_buffer, + GPUTexture *depth_tx, + GPUTexture *combined_tx); private: - void update_pass_inputs(GBuffer &gbuffer, HiZBuffer &hiz_front, HiZBuffer &hiz_back); + void deferred_shgroup_resources(DRWShadingGroup *grp); }; class DeferredPass { @@ -143,29 +138,11 @@ class DeferredPass { DeferredLayer refraction_layer_; DeferredLayer volumetric_layer_; - DRWPass *eval_direct_ps_ = nullptr; + DRWPass *eval_ps_ = nullptr; DRWPass *eval_subsurface_ps_ = nullptr; - DRWPass *eval_transparency_ps_ = nullptr; - DRWPass *eval_holdout_ps_ = nullptr; - // DRWPass *eval_volume_heterogeneous_ps_ = nullptr; - DRWPass *eval_volume_homogeneous_ps_ = nullptr; /* References only. */ GPUTexture *input_combined_tx_ = nullptr; - GPUTexture *input_depth_behind_tx_ = nullptr; - GPUTexture *input_diffuse_tx_ = nullptr; - GPUTexture *input_emission_data_tx_ = nullptr; - GPUTexture *input_hiz_front_tx_ = nullptr; - GPUTexture *input_hiz_back_tx_ = nullptr; - GPUTexture *input_reflect_color_tx_ = nullptr; - GPUTexture *input_reflect_normal_tx_ = nullptr; - GPUTexture *input_transmit_color_tx_ = nullptr; - GPUTexture *input_transmit_data_tx_ = nullptr; - GPUTexture *input_transmit_normal_tx_ = nullptr; - GPUTexture *input_transparency_data_tx_ = nullptr; - GPUTexture *input_volume_data_tx_ = nullptr; - // GPUTexture *input_volume_radiance_tx_ = nullptr; - // GPUTexture *input_volume_transmittance_tx_ = nullptr; public: DeferredPass(Instance &inst) @@ -176,12 +153,10 @@ class DeferredPass { DRWShadingGroup *prepass_add(::Material *material, GPUMaterial *gpumat); void volume_add(Object *ob); void render(const DRWView *drw_view, - GBuffer &gbuffer, - HiZBuffer &hiz_front, - HiZBuffer &hiz_back, RaytraceBuffer &rtbuffer_opaque, RaytraceBuffer &rtbuffer_refract, - GPUFrameBuffer *view_fb); + GPUTexture *depth_tx, + GPUTexture *combined_tx); }; /** \} */ diff --git a/source/blender/draw/engines/eevee/eevee_shadow.cc b/source/blender/draw/engines/eevee/eevee_shadow.cc index 51ec4ab9807..a5ad7623d0d 100644 --- a/source/blender/draw/engines/eevee/eevee_shadow.cc +++ b/source/blender/draw/engines/eevee/eevee_shadow.cc @@ -1048,6 +1048,8 @@ void ShadowModule::debug_end_sync(void) * Needs to be called after LightModule::set_view(); */ void ShadowModule::set_view(const DRWView *view, GPUTexture *depth_tx) { + GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); + /* Only process each view once. */ bool do_process_view = (view != last_processed_view); last_processed_view = view; @@ -1220,15 +1222,16 @@ void ShadowModule::set_view(const DRWView *view, GPUTexture *depth_tx) DRW_stats_group_end(); DRW_view_set_active(view); + if (prev_fb) { + GPU_framebuffer_bind(prev_fb); + } } -void ShadowModule::debug_draw(GPUFrameBuffer *view_fb, HiZBuffer &hiz) +void ShadowModule::debug_draw(GPUFrameBuffer *view_fb) { if (debug_draw_ps_ == nullptr) { return; } - input_depth_tx_ = hiz.texture_get(); - const DRWView *view = DRW_view_get_active(); if (debug_view_ != nullptr) { diff --git a/source/blender/draw/engines/eevee/eevee_shadow.hh b/source/blender/draw/engines/eevee/eevee_shadow.hh index 52bc51eb3b0..24a0c81aff1 100644 --- a/source/blender/draw/engines/eevee/eevee_shadow.hh +++ b/source/blender/draw/engines/eevee/eevee_shadow.hh @@ -599,7 +599,7 @@ class ShadowModule { void set_view(const DRWView *view, GPUTexture *depth_tx); void debug_end_sync(void); - void debug_draw(GPUFrameBuffer *view_fb, HiZBuffer &hiz); + void debug_draw(GPUFrameBuffer *view_fb); GPUTexture *atlas_tx_get(void) { diff --git a/source/blender/draw/engines/eevee/eevee_view.cc b/source/blender/draw/engines/eevee/eevee_view.cc index 8a96d01ac63..7bc250ba286 100644 --- a/source/blender/draw/engines/eevee/eevee_view.cc +++ b/source/blender/draw/engines/eevee/eevee_view.cc @@ -81,6 +81,9 @@ void ShadingView::sync(int2 render_extent_) velocity_.sync(extent_); rt_buffer_opaque_.sync(extent_); rt_buffer_refract_.sync(extent_); + inst_.hiz_back.view_sync(extent_); + inst_.hiz_front.view_sync(extent_); + inst_.gbuffer.view_sync(extent_); { /* Query temp textures and create framebuffers. */ @@ -94,8 +97,6 @@ void ShadingView::sync(int2 render_extent_) postfx_tx_ = DRW_texture_pool_query_2d(UNPACK2(extent_), GPU_RGBA16F, owner); view_fb_.ensure(GPU_ATTACHMENT_TEXTURE(depth_tx_), GPU_ATTACHMENT_TEXTURE(combined_tx_)); - - gbuffer_.sync(depth_tx_, combined_tx_, owner); } } @@ -119,22 +120,17 @@ void ShadingView::render(void) inst_.shading_passes.background.render(); } - inst_.shading_passes.deferred.render(render_view_, - gbuffer_, - hiz_front_, - hiz_back_, - rt_buffer_opaque_, - rt_buffer_refract_, - view_fb_); + inst_.shading_passes.deferred.render( + render_view_, rt_buffer_opaque_, rt_buffer_refract_, depth_tx_, combined_tx_); inst_.lightprobes.draw_cache_display(); inst_.lookdev.render_overlay(view_fb_); - inst_.shading_passes.forward.render(render_view_, gbuffer_, hiz_front_, view_fb_); + inst_.shading_passes.forward.render(render_view_, depth_tx_, combined_tx_); - inst_.lights.debug_draw(view_fb_, hiz_front_); - inst_.shadows.debug_draw(view_fb_, hiz_front_); + inst_.lights.debug_draw(view_fb_); + inst_.shadows.debug_draw(view_fb_); velocity_.render(depth_tx_); @@ -209,16 +205,15 @@ void LightProbeView::sync(Texture &color_tx, if (!is_only_background_) { /* Query temp textures and create framebuffers. */ - /* HACK: View name should be unique and static. - * With this, we can reuse the same texture across views. */ - DrawEngineType *owner = (DrawEngineType *)name_; - gbuffer_.sync(depth_tx, color_tx, owner, layer_); rt_buffer_opaque_.sync(extent_); rt_buffer_refract_.sync(extent_); + inst_.hiz_back.view_sync(extent_); + inst_.hiz_front.view_sync(extent_); + inst_.gbuffer.view_sync(extent_); } } -void LightProbeView::render(void) +void LightProbeView::render(GPUTexture *depth_tx) { if (!is_only_background_) { inst_.lightprobes.set_view(view_, extent_); @@ -236,8 +231,8 @@ void LightProbeView::render(void) GPU_framebuffer_clear_depth(view_fb_, 1.0f); inst_.shading_passes.deferred.render( - view_, gbuffer_, hiz_front_, hiz_back_, rt_buffer_opaque_, rt_buffer_refract_, view_fb_); - inst_.shading_passes.forward.render(view_, gbuffer_, hiz_front_, view_fb_); + view_, rt_buffer_opaque_, rt_buffer_refract_, depth_tx, nullptr); + inst_.shading_passes.forward.render(view_, depth_tx, nullptr); } DRW_stats_group_end(); } diff --git a/source/blender/draw/engines/eevee/eevee_view.hh b/source/blender/draw/engines/eevee/eevee_view.hh index 3dfdd548e21..65b9ad981da 100644 --- a/source/blender/draw/engines/eevee/eevee_view.hh +++ b/source/blender/draw/engines/eevee/eevee_view.hh @@ -54,10 +54,6 @@ class ShadingView { MotionBlur mb_; Velocity velocity_; - /** GBuffer for deferred passes. */ - GBuffer gbuffer_; - /** HiZBuffer for screenspace effects. */ - HiZBuffer hiz_front_, hiz_back_; /** Raytracing persistent buffers. Only opaque and refraction can have surface tracing. */ RaytraceBuffer rt_buffer_opaque_; RaytraceBuffer rt_buffer_refract_; @@ -90,8 +86,6 @@ class ShadingView { dof_(inst, name), mb_(inst, name), velocity_(inst, name), - hiz_front_(inst), - hiz_back_(inst), rt_buffer_opaque_(inst), rt_buffer_refract_(inst){}; @@ -124,10 +118,6 @@ class LightProbeView { const char *name_; /** Matrix to apply to the viewmat. */ const float (*face_matrix_)[4]; - /** GBuffer for deferred passes. */ - GBuffer gbuffer_; - /** HiZBuffer for screenspace effects. */ - HiZBuffer hiz_front_, hiz_back_; /** Raytracing persistent buffers. Only opaque and refraction can have surface tracing. */ RaytraceBuffer rt_buffer_opaque_; RaytraceBuffer rt_buffer_refract_; @@ -146,8 +136,6 @@ class LightProbeView { : inst_(inst), name_(name), face_matrix_(face_matrix), - hiz_front_(inst), - hiz_back_(inst), rt_buffer_opaque_(inst), rt_buffer_refract_(inst), layer_(layer_){}; @@ -160,7 +148,7 @@ class LightProbeView { const float4x4 &viewmat, bool is_only_background); - void render(void); + void render(GPUTexture *depth_tx); }; /** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/eevee_culling_debug_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_culling_debug_frag.glsl index 2101d9711e0..8479ac44314 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_culling_debug_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_culling_debug_frag.glsl @@ -12,7 +12,7 @@ void main(void) { - float depth = texelFetch(depth_tx, ivec2(gl_FragCoord.xy), 0).r; + float depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r; float vP_z = get_view_z_from_depth(depth); vec3 P = get_world_space_from_depth(uvcoordsvar.xy, depth); diff --git a/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_deferred_eval_frag.glsl index ca8c0c32533..13afe0add60 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_deferred_eval_frag.glsl @@ -10,24 +10,22 @@ #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) #pragma BLENDER_REQUIRE(eevee_shadow_lib.glsl) #pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_cubemap_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_lightprobe_eval_grid_lib.glsl) void main(void) { + ivec2 texel = ivec2(gl_FragCoord.xy); + float gbuffer_depth = texelFetch(hiz_tx, texel, 0).r; vec2 uv = uvcoordsvar.xy; - float gbuffer_depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r; vec3 vP = get_view_space_from_depth(uv, gbuffer_depth); vec3 P = point_view_to_world(vP); vec3 V = cameraVec(P); - vec4 tra_col_in = texture(transmit_color_tx, uv); - vec4 tra_nor_in = texture(transmit_normal_tx, uv); - vec4 tra_dat_in = texture(transmit_data_tx, uv); - vec4 ref_col_in = texture(reflect_color_tx, uv); - vec4 ref_nor_in = texture(reflect_normal_tx, uv); + vec4 tra_col_in = texelFetch(transmit_color_tx, texel, 0); + vec4 tra_nor_in = texelFetch(transmit_normal_tx, texel, 0); + vec4 tra_dat_in = texelFetch(transmit_data_tx, texel, 0); + vec4 ref_col_in = texelFetch(reflect_color_tx, texel, 0); + vec4 ref_nor_in = texelFetch(reflect_normal_tx, texel, 0); - ClosureEmission emission = gbuffer_load_emission_data(emission_data_tx, uv); ClosureDiffuse diffuse = gbuffer_load_diffuse_data(tra_col_in, tra_nor_in, tra_dat_in); ClosureReflection reflection = gbuffer_load_reflection_data(ref_col_in, ref_nor_in); @@ -44,15 +42,16 @@ void main(void) light_eval(diffuse, reflection, P, V, vP.z, thickness, radiance_diffuse, radiance_reflection); - out_combined = vec4(emission.emission, 0.0); - out_diffuse.rgb = radiance_diffuse; - /* FIXME(fclem): This won't work after the first light batch since we use additive blending. */ - out_diffuse.a = fract(float(diffuse.sss_id) / 1024.0) * 1024.0; - /* Do not apply color to diffuse term for SSS material. */ - if (diffuse.sss_id == 0u) { - out_diffuse.rgb *= diffuse.color; - out_combined.rgb += out_diffuse.rgb; + out_combined = vec4(0.0); + out_combined.xyz += radiance_reflection * reflection.color; + + if (diffuse.sss_id != 0u) { + // imageStore(sss_radiance, texel, vec4(radiance_diffuse, float(diffuse.sss_id % 1024))); + } + else { + out_combined.xyz += radiance_diffuse * diffuse.color; } - out_specular = radiance_reflection * reflection.color; - out_combined.rgb += out_specular; + + // output_renderpass(rpass_diffuse_light, vec3(1.0), vec4(radiance_diffuse, 0.0)); + // output_renderpass(rpass_specular_light, vec3(1.0), vec4(radiance_reflection, 0.0)); } diff --git a/source/blender/draw/engines/eevee/shaders/eevee_deferred_holdout_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_deferred_holdout_frag.glsl deleted file mode 100644 index d2840493e4b..00000000000 --- a/source/blender/draw/engines/eevee/shaders/eevee_deferred_holdout_frag.glsl +++ /dev/null @@ -1,18 +0,0 @@ - -/** - * Save radiance from main pass to subtract to final render. - * - * This way all screen space effects (SSS, SSR) are not altered by the presence of the holdout. - **/ - -#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) - -void main(void) -{ - vec3 combined_radiance = texture(combined_tx, uvcoordsvar.xy).rgb; - - ClosureTransparency transparency_data = gbuffer_load_transparency_data(transparency_data_tx, - uvcoordsvar.xy); - - out_holdout = combined_radiance * transparency_data.holdout; -} diff --git a/source/blender/draw/engines/eevee/shaders/eevee_deferred_transparent_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_deferred_transparent_frag.glsl deleted file mode 100644 index 7438aa0bba4..00000000000 --- a/source/blender/draw/engines/eevee/shaders/eevee_deferred_transparent_frag.glsl +++ /dev/null @@ -1,47 +0,0 @@ - -/** - * Apply transmittance to all radiance passes. - * - * We needs to evaluate the transmittance of homogeneous volumes if any is present. - * Hopefully, this has O(1) complexity as we do not need to raymarch the volume. - * - * Using blend mode multiply. - **/ - -#pragma BLENDER_REQUIRE(eevee_volume_eval_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) - -void main(void) -{ - ClosureVolume volume_data = gbuffer_load_volume_data(volume_data_tx, uvcoordsvar.xy); - - /* For volumes from solid objects. */ - // float depth_max = linear_z(texture(depth_max_tx, uv).r); - // float depth_min = linear_z(texture(depth_min_tx, uv).r); - - /* Refine bounds to skip empty areas. */ - // float dist_from_bbox = intersect_bbox_ray(P, V, bbox); - // depth_min = max(dist_from_bbox, depth_min); - - vec3 volume_transmittance; - if (volume_data.anisotropy == VOLUME_HETEROGENEOUS) { - volume_transmittance = volume_data.transmittance; - } - else { - // volume_eval_homogeneous(P, depth_min, depth_max, volume_transmittance); - volume_transmittance = vec3(0.0); - } - - vec3 surface_transmittance = - gbuffer_load_transparency_data(transparency_data_tx, uvcoordsvar.xy).transmittance; - - vec3 final_transmittance = volume_transmittance * surface_transmittance; - - /* Multiply transmittance all radiance buffers. Remember that blend mode is multiply. */ - out_combined = vec4(final_transmittance, avg(final_transmittance)); - out_diffuse = final_transmittance; - out_specular = final_transmittance; - out_volume = final_transmittance; - out_background = final_transmittance; - out_holdout = final_transmittance; -} diff --git a/source/blender/draw/engines/eevee/shaders/eevee_deferred_volume_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_deferred_volume_frag.glsl deleted file mode 100644 index ba562bd3d5e..00000000000 --- a/source/blender/draw/engines/eevee/shaders/eevee_deferred_volume_frag.glsl +++ /dev/null @@ -1,46 +0,0 @@ - -/** - * Apply heterogeneous volume lighting and evaluates homogeneous volumetrics if needed. - * - * We read volume parameters from the gbuffer and consider them constant for the whole volume. - * This only applies to solid objects not volumes. - **/ - -#pragma BLENDER_REQUIRE(common_view_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_bsdf_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_culling_iter_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_shadow_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_volume_eval_lib.glsl) - -void main(void) -{ - ClosureVolume volume_data = gbuffer_load_volume_data(volume_data_tx, uvcoordsvar.xy); - - /* For volumes from solid objects. */ - // float depth_max = linear_z(texture(depth_max_tx, uv).r); - // float depth_min = linear_z(texture(depth_min_tx, uv).r); - - /* Refine bounds to skip empty areas. */ - // float dist_from_bbox = intersect_bbox_ray(P, V, bbox); - // depth_min = max(dist_from_bbox, depth_min); - - vec3 volume_radiance; - if (volume_data.anisotropy == VOLUME_HETEROGENEOUS) { - volume_radiance = volume_data.scattering; - } - else { - // volume_eval_homogeneous(P, depth_min, depth_max, volume_radiance); - volume_radiance = vec3(0.0); - } - - /* Apply transmittance of surface on volumetric radiance because - * the volume is behind the surface. */ - ClosureTransparency transparency_data = gbuffer_load_transparency_data(transparency_data_tx, - uvcoordsvar.xy); - volume_radiance *= transparency_data.transmittance; - - out_combined = vec4(volume_radiance, 0.0); - out_volume = volume_radiance; -} diff --git a/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_lib.glsl b/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_lib.glsl index 224a376bde4..d06c79706a2 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_gbuffer_lib.glsl @@ -191,82 +191,3 @@ ClosureRefraction gbuffer_load_refraction_data(sampler2D transmit_color_tx, } /** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Volume data - * - * Pack all volumetric effects. - * - * \{ */ - -#define VOLUME_HETEROGENEOUS -2.0 - -uvec4 gbuffer_store_volume_data(ClosureVolume data_in) -{ - uvec4 data_out; - data_out.x = gbuffer_encode_color(data_in.emission); - data_out.y = gbuffer_encode_color(data_in.scattering); - data_out.z = gbuffer_encode_color(data_in.transmittance); - data_out.w = floatBitsToUint(data_in.anisotropy); - return data_out; -} - -ClosureVolume gbuffer_load_volume_data(usampler2D gbuffer_tx, vec2 uv) -{ - uvec4 data_in = texture(gbuffer_tx, uv); - - ClosureVolume data_out; - data_out.emission = gbuffer_decode_color(data_in.x); - data_out.scattering = gbuffer_decode_color(data_in.y); - data_out.transmittance = gbuffer_decode_color(data_in.z); - data_out.anisotropy = uintBitsToFloat(data_in.w); - return data_out; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Emission data - * - * \{ */ - -vec3 gbuffer_store_emission_data(ClosureEmission data_in) -{ - return data_in.emission; -} - -ClosureEmission gbuffer_load_emission_data(sampler2D gbuffer_tx, vec2 uv) -{ - vec4 data_in = texture(gbuffer_tx, uv); - - ClosureEmission data_out; - data_out.emission = data_in.xyz; - return data_out; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Transparency data - * - * \{ */ - -vec4 gbuffer_store_transparency_data(ClosureTransparency data_in) -{ - vec4 data_out; - data_out.xyz = data_in.transmittance; - data_out.w = data_in.holdout; - return data_out; -} - -ClosureTransparency gbuffer_load_transparency_data(sampler2D gbuffer_tx, vec2 uv) -{ - vec4 data_in = texture(gbuffer_tx, uv); - - ClosureTransparency data_out; - data_out.transmittance = data_in.xyz; - data_out.holdout = data_in.w; - return data_out; -} - -/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl deleted file mode 100644 index 4abd6d9233b..00000000000 --- a/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copy input depth texture to lower left corner of the destination, filling any padding with - * clamped texture extrapolation. - */ - -void main() -{ - vec2 uv = gl_FragCoord.xy / vec2(textureSize(depth_tx, 0).xy); - - out_depth = texture(depth_tx, uv).r; -} diff --git a/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl deleted file mode 100644 index cbde1352e06..00000000000 --- a/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Shader that down-sample depth buffer, creating a Hierarchical-Z buffer. - * Saves max value of each 2x2 texel in the mipmap above the one we are rendering to. - * Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/ - * - * Major simplification has been made since we pad the buffer to always be bigger than input to - * avoid mipmapping misalignement. - */ - -#pragma BLENDER_REQUIRE(common_math_lib.glsl) - -#ifndef GPU_ARB_texture_gather -vec4 texGather(sampler2D tex, vec2 uv) -{ - vec4 ofs = vec2(0.5, 0.5, -0.5, -0.5) * texel_size.xyxy; - return vec4(texture(tex, uv + ofs.zw).r, - texture(tex, uv + ofs.zy).r, - texture(tex, uv + ofs.xw).r, - texture(tex, uv + ofs.xy).r); -} -#else -# define texGather(a, b) textureGather(a, b) -#endif - -void main() -{ - /* NOTE(@fclem): textureSize() does not work the same on all implementations - * when changing the min and max texture levels. Use uniform instead (see T87801). */ - vec2 uv = gl_FragCoord.xy * texel_size; - - vec4 samp = texGather(depth_tx, uv); - - out_depth = max_v4(samp); -} diff --git a/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl index 10e7c59509b..7fe3242a09e 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_shadow_debug_frag.glsl @@ -336,9 +336,9 @@ void main() return; } - float mouse_depth = texelFetch(depth_tx, drw_view.mouse_pixel, 0).r; + float mouse_depth = texelFetch(hiz_tx, drw_view.mouse_pixel, 0).r; vec3 mouse_P = get_world_space_from_depth( - vec2(drw_view.mouse_pixel) / vec2(textureSize(depth_tx, 0)), mouse_depth); + vec2(drw_view.mouse_pixel) * drw_view.viewport_size_inverse, mouse_depth); ivec4 mouse_tile; debug_tile_index_from_position(mouse_P, mouse_tile); @@ -346,7 +346,7 @@ void main() return; } - float depth = texelFetch(depth_tx, ivec2(gl_FragCoord.xy), 0).r; + float depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r; vec3 P = get_world_space_from_depth(uvcoordsvar.xy, depth); /* Make it pass the depth test. */ gl_FragDepth = depth - 1e-6; diff --git a/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl index 70fe3af6832..169ca555112 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl @@ -44,12 +44,13 @@ vec3 burley_eval(vec3 d, float r) void main(void) { vec2 center_uv = uvcoordsvar.xy; + ivec2 texel = ivec2(gl_FragCoord.xy); - float gbuffer_depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r; + float gbuffer_depth = texelFetch(hiz_tx, texel, 0).r; vec3 vP = get_view_space_from_depth(center_uv, gbuffer_depth); - vec4 tra_col_in = texture(transmit_color_tx, center_uv); - vec4 tra_nor_in = texture(transmit_normal_tx, center_uv); - vec4 tra_dat_in = texture(transmit_data_tx, center_uv); + vec4 tra_col_in = texelFetch(transmit_color_tx, texel, 0); + vec4 tra_nor_in = texelFetch(transmit_normal_tx, texel, 0); + vec4 tra_dat_in = texelFetch(transmit_data_tx, texel, 0); ClosureDiffuse diffuse = gbuffer_load_diffuse_data(tra_col_in, tra_nor_in, tra_dat_in); diff --git a/source/blender/draw/engines/eevee/shaders/eevee_surface_deferred_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_surface_deferred_frag.glsl index 4030c16085d..3a596bed0a4 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_surface_deferred_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_surface_deferred_frag.glsl @@ -7,6 +7,9 @@ #pragma BLENDER_REQUIRE(eevee_nodetree_eval_lib.glsl) #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) +/* TODO(fclem): Renderpasses. */ +#define output_renderpass(a, b, c, d) + void main(void) { g_data = init_globals(); @@ -21,49 +24,84 @@ void main(void) nodetree_surface(); - float alpha = saturate(1.0 - avg(g_transparency_data.transmittance)); - vec3 V = cameraVec(g_data.P); + out_transmittance = vec4(1.0 - g_transparency_data.holdout); + float transmittance_mono = saturate(avg(g_transparency_data.transmittance)); +#if 1 /* TODO(fclem): Alpha clipped materials. */ - if (alpha > 0.0) { + /* Apply transmittance. */ + out_transmittance *= vec4(g_transparency_data.transmittance, transmittance_mono); +#else + /* Stochastique monochromatic transmittance. + * Pixels are discarded based on alpha. We need to compensate the applied transmittance + * term on all radiance channels. */ + if (transmittance_mono < 1.0) { + float alpha = 1.0 - transmittance_mono; g_diffuse_data.color /= alpha; g_reflection_data.color /= alpha; g_refraction_data.color /= alpha; g_emission_data.emission /= alpha; } +#endif + out_radiance = vec4(g_emission_data.emission, g_transparency_data.holdout); + +#ifdef MATERIAL_EMISSION + output_renderpass(rpass_emission, transmittance, vec4(g_emission_data.emission, 0.0)); +#endif + +#ifdef MATERIAL_VOLUME + output_renderpass(rpass_volume_light, transmittance, vec4(, 0.0)); +#endif if (gl_FrontFacing) { g_refraction_data.ior = safe_rcp(g_refraction_data.ior); } + vec3 V = cameraVec(g_data.P); g_reflection_data.N = ensure_valid_reflection(g_data.Ng, V, g_reflection_data.N); - { - out_reflection_color = g_reflection_data.color; - out_reflection_normal.xy = gbuffer_encode_normal(g_reflection_data.N); - out_reflection_normal.z = max(1e-4, g_reflection_data.roughness); + ivec2 out_texel = ivec2(gl_FragCoord.xy); + + if (true) { + vec4 out_color; + out_color.xyz = g_reflection_data.color; + imageStore(gbuff_reflection_color, out_texel, out_color); + + vec4 out_normal; + out_normal.xy = gbuffer_encode_normal(g_reflection_data.N); + out_normal.z = max(1e-4, g_reflection_data.roughness); + imageStore(gbuff_reflection_normal, out_texel, out_normal); } if (g_data.transmit_rand == 0.0) { - out_transmit_color = g_refraction_data.color; - out_transmit_normal.xy = gbuffer_encode_normal(g_refraction_data.N); - out_transmit_normal.z = -1.0; - out_transmit_normal.w = thickness; - out_transmit_data.x = g_refraction_data.ior; - out_transmit_data.y = g_refraction_data.roughness; + vec4 out_color; + out_color.xyz = g_refraction_data.color; + imageStore(gbuff_transmit_color, out_texel, out_color); + + vec4 out_normal; + out_normal.xy = gbuffer_encode_normal(g_refraction_data.N); + out_normal.z = -1.0; + out_normal.w = thickness; + imageStore(gbuff_transmit_normal, out_texel, out_normal); + + vec4 out_data; + out_data.x = g_refraction_data.ior; + out_data.y = g_refraction_data.roughness; + imageStore(gbuff_transmit_data, out_texel, out_data); } else { - if (g_diffuse_data.sss_id == 1u) { - g_diffuse_data.sss_id = uint(resource_handle + 1); - } /* Output diffuse / SSS in transmit data. */ - out_transmit_color = g_diffuse_data.color; - out_transmit_normal.xy = gbuffer_encode_normal(g_diffuse_data.N); - out_transmit_normal.z = fract(float(g_diffuse_data.sss_id) / 1024.0); - out_transmit_normal.w = thickness; - out_transmit_data = g_diffuse_data.sss_radius; - } + vec4 out_color; + out_color.xyz = g_diffuse_data.color; + imageStore(gbuff_transmit_color, out_texel, out_color); + + vec4 out_normal; + out_normal.xy = gbuffer_encode_normal(g_diffuse_data.N); + out_normal.z = (g_diffuse_data.sss_id == 1u) ? fract(float(resource_handle + 1) / 1024.0) : 0; + out_normal.w = thickness; + imageStore(gbuff_transmit_normal, out_texel, out_normal); - out_volume_data = gbuffer_store_volume_data(g_volume_data); - out_emission_data = gbuffer_store_emission_data(g_emission_data); - out_transparency_data = gbuffer_store_transparency_data(g_transparency_data); + vec4 out_data; + out_data.xyz = g_diffuse_data.sss_radius; + imageStore(gbuff_transmit_data, out_texel, out_data); + } } diff --git a/source/blender/draw/engines/eevee/shaders/eevee_volume_deferred_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_volume_deferred_frag.glsl index d20f9b0fb57..b20bd50a20b 100644 --- a/source/blender/draw/engines/eevee/shaders/eevee_volume_deferred_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/eevee_volume_deferred_frag.glsl @@ -61,7 +61,4 @@ void main(void) g_transparency_data.transmittance = vec3(1.0); g_transparency_data.holdout = 0.0; - - out_volume_data = gbuffer_store_volume_data(g_volume_data); - out_transparency_data = gbuffer_store_transparency_data(g_transparency_data); } diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_culling_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_culling_info.hh index 8a76a3a13cd..4ba152c131e 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/eevee_culling_info.hh +++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_culling_info.hh @@ -54,7 +54,7 @@ GPU_SHADER_CREATE_INFO(eevee_light_data) GPU_SHADER_CREATE_INFO(eevee_culling_debug) .do_static_compilation(true) - .sampler(0, ImageType::DEPTH_2D, "depth_tx") + .sampler(0, ImageType::FLOAT_2D, "hiz_tx") .fragment_out(0, Type::VEC4, "out_debug_color") .additional_info("eevee_shared", "draw_view") .fragment_source("eevee_culling_debug_frag.glsl") diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_deferred_info.hh index 7a438b14f44..6c22249349e 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_deferred_info.hh @@ -7,82 +7,36 @@ GPU_SHADER_CREATE_INFO(eevee_utility_texture).sampler(8, ImageType::FLOAT_2D_ARRAY, "utility_tx"); -GPU_SHADER_CREATE_INFO(eevee_deferred_direct) +#define image_out(slot, qualifier, format, name) \ + image(slot, format, qualifier, ImageType::FLOAT_2D, name, Frequency::PASS) + +GPU_SHADER_CREATE_INFO(eevee_deferred_eval) .do_static_compilation(true) .auto_resource_location(true) .sampler(0, ImageType::FLOAT_2D, "hiz_tx") - .sampler(1, ImageType::FLOAT_2D, "emission_data_tx") .sampler(2, ImageType::FLOAT_2D, "transmit_color_tx") .sampler(3, ImageType::FLOAT_2D, "transmit_normal_tx") .sampler(4, ImageType::FLOAT_2D, "transmit_data_tx") .sampler(5, ImageType::FLOAT_2D, "reflect_color_tx") .sampler(6, ImageType::FLOAT_2D, "reflect_normal_tx") .fragment_out(0, Type::VEC4, "out_combined") - .fragment_out(1, Type::VEC4, "out_diffuse") - .fragment_out(2, Type::VEC3, "out_specular") + /* Renderpasses. */ + // .image_out(0, Qualifier::READ_WRITE, GPU_RGBA16F, "rpass_diffuse_light") + // .image_out(1, Qualifier::READ_WRITE, GPU_RGBA16F, "rpass_specular_light") + /* Raytracing. */ + // .image_out(2, Qualifier::WRITE, GPU_RGBA16F, "ray_data") + /* SubSurfaceScattering. */ + // .image_out(3, Qualifier::WRITE, GPU_RGBA16F, "sss_radiance") .additional_info("eevee_shared", "draw_view") - .fragment_source("eevee_deferred_direct_frag.glsl") + .fragment_source("eevee_deferred_eval_frag.glsl") .additional_info("draw_fullscreen", "eevee_transmittance_data", "eevee_utility_texture", - "eevee_lightprobe_data", + // "eevee_lightprobe_data", "eevee_light_data", "eevee_shadow_data", "eevee_sampling_data"); -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Holdout - * \{ */ - -GPU_SHADER_CREATE_INFO(eevee_deferred_holdout) - .do_static_compilation(true) - .sampler(0, ImageType::FLOAT_2D, "combined_tx") - .sampler(1, ImageType::FLOAT_2D, "transparency_data_tx") - .fragment_out(5, Type::VEC3, "out_holdout") - .additional_info("eevee_shared") - .fragment_source("eevee_deferred_holdout_frag.glsl") - .additional_info("draw_fullscreen", "draw_view"); - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Transparency - * \{ */ - -GPU_SHADER_CREATE_INFO(eevee_deferred_transparent) - .do_static_compilation(true) - .sampler(0, ImageType::UINT_2D, "volume_data_tx") - .sampler(1, ImageType::FLOAT_2D, "transparency_data_tx") - .fragment_out(0, Type::VEC4, "out_combined") - .fragment_out(1, Type::VEC3, "out_diffuse") - .fragment_out(2, Type::VEC3, "out_specular") - .fragment_out(3, Type::VEC3, "out_volume") - .fragment_out(4, Type::VEC3, "out_background") - .fragment_out(5, Type::VEC3, "out_holdout") - .additional_info("eevee_shared") - .fragment_source("eevee_deferred_transparent_frag.glsl") - .additional_info("draw_fullscreen", "draw_view", "eevee_light_data"); - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Volume - * \{ */ - -GPU_SHADER_CREATE_INFO(eevee_deferred_volume) - .do_static_compilation(true) - .sampler(0, ImageType::FLOAT_2D, "transparency_data_tx") - .sampler(1, ImageType::UINT_2D, "volume_data_tx") - .fragment_out(0, Type::VEC4, "out_combined") - .fragment_out(1, Type::VEC3, "out_volume") - .additional_info("eevee_shared") - .fragment_source("eevee_deferred_volume_frag.glsl") - .additional_info("draw_fullscreen", - "draw_view", - "eevee_utility_texture", - "eevee_light_data", - "eevee_shadow_data"); +#undef image_out /** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_material_info.hh index 0b310d7c309..c2bd8805aa2 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_material_info.hh @@ -64,29 +64,31 @@ GPU_SHADER_INTERFACE_INFO(eevee_surface_iface, "interp") .smooth(Type::FLOAT, "hair_thickness") .flat(Type::INT, "hair_strand_id"); +#define image_out(slot, qualifier, format, name) \ + image(slot, format, qualifier, ImageType::FLOAT_2D, name, Frequency::PASS) + GPU_SHADER_CREATE_INFO(eevee_surface_deferred) .vertex_out(eevee_surface_iface) - /* Diffuse or Transmission Color. */ - .fragment_out(0, Type::VEC3, "out_transmit_color") - /* RG: Normal (negative if Tranmission), B: SSS ID, A: Min-Thickness */ - .fragment_out(1, Type::VEC4, "out_transmit_normal") - /* RGB: SSS RGB Radius. - * or - * R: Transmission IOR, G: Transmission Roughness, B: Unused. */ - .fragment_out(2, Type::VEC3, "out_transmit_data") - /* Reflection Color. */ - .fragment_out(3, Type::VEC3, "out_reflection_color") - /* RG: Normal, B: Roughness X, A: Roughness Y. */ - .fragment_out(4, Type::VEC4, "out_reflection_normal") - /* Volume Emission, Absorption, Scatter, Phase. */ - .fragment_out(5, Type::UVEC4, "out_volume_data") - /* Emission. */ - .fragment_out(6, Type::VEC3, "out_emission_data") - /* Transparent BSDF, Holdout. */ - .fragment_out(7, Type::VEC4, "out_transparency_data") + /* Note: This removes the possibility of using gl_FragDepth. */ + .early_fragment_test(true) + /* Direct output. */ + .fragment_out(0, Type::VEC4, "out_radiance", DualBlend::SRC_0) + .fragment_out(0, Type::VEC4, "out_transmittance", DualBlend::SRC_1) + /* Gbuffer. */ + .image_out(0, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_transmit_color") + .image_out(1, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_transmit_data") + .image_out(2, Qualifier::WRITE, GPU_RGBA16F, "gbuff_transmit_normal") + .image_out(3, Qualifier::WRITE, GPU_R11F_G11F_B10F, "gbuff_reflection_color") + .image_out(4, Qualifier::WRITE, GPU_RGBA16F, "gbuff_reflection_normal") + /* Renderpasses. */ + .image_out(5, Qualifier::READ_WRITE, GPU_RGBA16F, "rpass_emission") + .image_out(6, Qualifier::READ_WRITE, GPU_RGBA16F, "rpass_volume_light") + /* TODO: AOVs maybe? */ .fragment_source("eevee_surface_deferred_frag.glsl") .additional_info("eevee_sampling_data", "eevee_utility_texture"); +#undef image_out + GPU_SHADER_CREATE_INFO(eevee_surface_forward) .auto_resource_location(true) .vertex_out(eevee_surface_iface) diff --git a/source/blender/draw/engines/eevee/shaders/infos/eevee_shadow_info.hh b/source/blender/draw/engines/eevee/shaders/infos/eevee_shadow_info.hh index d68bcc3db98..efb93e745a3 100644 --- a/source/blender/draw/engines/eevee/shaders/infos/eevee_shadow_info.hh +++ b/source/blender/draw/engines/eevee/shaders/infos/eevee_shadow_info.hh @@ -182,7 +182,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_debug) .storage_buf(0, Qualifier::READ, "ShadowTileMapData", "tilemaps_buf[]") .storage_buf(1, Qualifier::READ, "uvec2", "pages_cached_buf[]") .storage_buf(2, Qualifier::READ, "ShadowPagesInfoData", "pages_infos_buf") - .sampler(0, ImageType::DEPTH_2D, "depth_tx") + .sampler(0, ImageType::FLOAT_2D, "hiz_tx") .sampler(1, ImageType::FLOAT_2D, "atlas_tx") .sampler(2, ImageType::UINT_2D, "tilemaps_tx") .sampler(3, ImageType::UINT_2D, "debug_page_tx") |