EEVEE-Next: Planar Probe Pipeline #113203
|
@ -152,7 +152,9 @@ class DATA_PT_lightprobe_eevee_next(DataButtonsPanel, Panel):
|
|||
sub.prop(probe, "clip_end", text="End")
|
||||
|
||||
elif probe.type == 'PLANAR':
|
||||
# Currently unsupported
|
||||
col = layout.column()
|
||||
row = col.row()
|
||||
col.prop(probe, "clip_start", text="Clipping Offset")
|
||||
pass
|
||||
else:
|
||||
# Currently unsupported
|
||||
|
|
|
@ -395,6 +395,7 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
|
|||
col = layout.column(heading="Light Probes")
|
||||
col.prop(ob, "hide_probe_volume", text="Volume", toggle=False, invert_checkbox=True)
|
||||
col.prop(ob, "hide_probe_cubemap", text="Cubemap", toggle=False, invert_checkbox=True)
|
||||
col.prop(ob, "hide_probe_planar", text="Planar", toggle=False, invert_checkbox=True)
|
||||
|
||||
if ob.type == 'GPENCIL':
|
||||
col = layout.column(heading="Grease Pencil")
|
||||
|
|
|
@ -153,6 +153,7 @@ set(SRC
|
|||
engines/eevee_next/eevee_material.cc
|
||||
engines/eevee_next/eevee_motion_blur.cc
|
||||
engines/eevee_next/eevee_pipeline.cc
|
||||
engines/eevee_next/eevee_planar_probes.cc
|
||||
engines/eevee_next/eevee_precompute.cc
|
||||
engines/eevee_next/eevee_raytrace.cc
|
||||
engines/eevee_next/eevee_reflection_probes.cc
|
||||
|
@ -289,6 +290,7 @@ set(SRC
|
|||
engines/eevee_next/eevee_material.hh
|
||||
engines/eevee_next/eevee_motion_blur.hh
|
||||
engines/eevee_next/eevee_pipeline.hh
|
||||
engines/eevee_next/eevee_planar_probes.hh
|
||||
engines/eevee_next/eevee_precompute.hh
|
||||
engines/eevee_next/eevee_raytrace.hh
|
||||
engines/eevee_next/eevee_reflection_probes.hh
|
||||
|
|
|
@ -76,6 +76,7 @@ void Instance::init(const int2 &output_res,
|
|||
shadows.init();
|
||||
motion_blur.init();
|
||||
main_view.init();
|
||||
planar_probes.init();
|
||||
/* Irradiance Cache needs reflection probes to be initialized. */
|
||||
reflection_probes.init();
|
||||
irradiance_cache.init();
|
||||
|
@ -108,6 +109,7 @@ void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager)
|
|||
depth_of_field.init();
|
||||
shadows.init();
|
||||
main_view.init();
|
||||
planar_probes.init();
|
||||
/* Irradiance Cache needs reflection probes to be initialized. */
|
||||
reflection_probes.init();
|
||||
irradiance_cache.init();
|
||||
|
@ -150,6 +152,7 @@ void Instance::begin_sync()
|
|||
pipelines.begin_sync();
|
||||
cryptomatte.begin_sync();
|
||||
reflection_probes.begin_sync();
|
||||
planar_probes.begin_sync();
|
||||
light_probes.begin_sync();
|
||||
|
||||
gpencil_engine_enabled = false;
|
||||
|
@ -279,6 +282,7 @@ void Instance::end_sync()
|
|||
pipelines.end_sync();
|
||||
light_probes.end_sync();
|
||||
reflection_probes.end_sync();
|
||||
planar_probes.end_sync();
|
||||
volume.end_sync();
|
||||
|
||||
global_ubo_.push_update();
|
||||
|
@ -315,12 +319,23 @@ void Instance::render_sync()
|
|||
DRW_curves_update();
|
||||
}
|
||||
|
||||
bool Instance::do_probe_sync() const
|
||||
bool Instance::do_reflection_probe_sync() const
|
||||
{
|
||||
if (!reflection_probes.update_probes_this_sample_) {
|
||||
return false;
|
||||
}
|
||||
if (materials.queued_shaders_count > 0) {
|
||||
return false;
|
||||
}
|
||||
if (!reflection_probes.update_probes_this_sample_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Instance::do_planar_probe_sync() const
|
||||
{
|
||||
if (!planar_probes.update_probes_) {
|
||||
return false;
|
||||
}
|
||||
if (materials.queued_shaders_count > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -439,6 +454,7 @@ void Instance::render_frame(RenderLayer *render_layer, const char *view_name)
|
|||
* are other light probes in the scene. */
|
||||
if (DEG_id_type_any_exists(this->depsgraph, ID_LP)) {
|
||||
reflection_probes.update_probes_next_sample_ = true;
|
||||
planar_probes.update_probes_ = true;
|
||||
}
|
||||
|
||||
while (!sampling.finished()) {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "eevee_material.hh"
|
||||
#include "eevee_motion_blur.hh"
|
||||
#include "eevee_pipeline.hh"
|
||||
#include "eevee_planar_probes.hh"
|
||||
#include "eevee_raytrace.hh"
|
||||
#include "eevee_reflection_probes.hh"
|
||||
#include "eevee_renderbuffers.hh"
|
||||
|
@ -64,6 +65,7 @@ class Instance {
|
|||
AmbientOcclusion ambient_occlusion;
|
||||
RayTraceModule raytracing;
|
||||
ReflectionProbeModule reflection_probes;
|
||||
PlanarProbeModule planar_probes;
|
||||
VelocityModule velocity;
|
||||
MotionBlurModule motion_blur;
|
||||
DepthOfField depth_of_field;
|
||||
|
@ -121,6 +123,7 @@ class Instance {
|
|||
ambient_occlusion(*this, global_ubo_.ao),
|
||||
raytracing(*this, global_ubo_.raytrace),
|
||||
reflection_probes(*this),
|
||||
planar_probes(*this),
|
||||
velocity(*this),
|
||||
motion_blur(*this),
|
||||
depth_of_field(*this),
|
||||
|
@ -158,7 +161,8 @@ class Instance {
|
|||
/**
|
||||
* Return true when probe pipeline is used during this sample.
|
||||
*/
|
||||
bool do_probe_sync() const;
|
||||
bool do_reflection_probe_sync() const;
|
||||
bool do_planar_probe_sync() const;
|
||||
|
||||
/* Render. */
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ MaterialPass MaterialModule::material_pass_get(Object *ob,
|
|||
::Material *blender_mat,
|
||||
eMaterialPipeline pipeline_type,
|
||||
eMaterialGeometry geometry_type,
|
||||
bool probe_capture)
|
||||
eMaterialProbe probe_capture)
|
||||
{
|
||||
bNodeTree *ntree = (blender_mat->use_nodes && blender_mat->nodetree != nullptr) ?
|
||||
blender_mat->nodetree :
|
||||
|
@ -267,8 +267,10 @@ Material &MaterialModule::material_sync(Object *ob,
|
|||
* to avoid this shader compilation in another context. */
|
||||
mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
|
||||
mat.capture = material_pass_get(ob, blender_mat, MAT_PIPE_CAPTURE, geometry_type);
|
||||
mat.probe_prepass = MaterialPass();
|
||||
mat.probe_shading = MaterialPass();
|
||||
mat.reflection_probe_prepass = MaterialPass();
|
||||
mat.reflection_probe_shading = MaterialPass();
|
||||
mat.planar_probe_prepass = MaterialPass();
|
||||
mat.planar_probe_shading = MaterialPass();
|
||||
mat.volume = MaterialPass();
|
||||
}
|
||||
else {
|
||||
|
@ -276,14 +278,22 @@ Material &MaterialModule::material_sync(Object *ob,
|
|||
mat.prepass = material_pass_get(ob, blender_mat, prepass_pipe, geometry_type);
|
||||
mat.shading = material_pass_get(ob, blender_mat, surface_pipe, geometry_type);
|
||||
mat.capture = MaterialPass();
|
||||
mat.probe_prepass = MaterialPass();
|
||||
mat.probe_shading = MaterialPass();
|
||||
mat.reflection_probe_prepass = MaterialPass();
|
||||
mat.reflection_probe_shading = MaterialPass();
|
||||
mat.planar_probe_prepass = MaterialPass();
|
||||
mat.planar_probe_shading = MaterialPass();
|
||||
|
||||
if (inst_.do_probe_sync()) {
|
||||
mat.probe_prepass = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_DEFERRED_PREPASS, geometry_type, true);
|
||||
mat.probe_shading = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, true);
|
||||
if (inst_.do_reflection_probe_sync()) {
|
||||
mat.reflection_probe_prepass = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_DEFERRED_PREPASS, geometry_type, MAT_PROBE_REFLECTION);
|
||||
mat.reflection_probe_shading = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_REFLECTION);
|
||||
}
|
||||
if (inst_.do_planar_probe_sync()) {
|
||||
mat.planar_probe_prepass = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_PLANAR_PREPASS, geometry_type, MAT_PROBE_PLANAR);
|
||||
mat.planar_probe_shading = material_pass_get(
|
||||
ob, blender_mat, MAT_PIPE_DEFERRED, geometry_type, MAT_PROBE_PLANAR);
|
||||
}
|
||||
|
||||
if (GPU_material_has_volume_output(mat.shading.gpumat)) {
|
||||
|
|
|
@ -35,6 +35,7 @@ enum eMaterialPipeline {
|
|||
MAT_PIPE_VOLUME,
|
||||
MAT_PIPE_SHADOW,
|
||||
MAT_PIPE_CAPTURE,
|
||||
MAT_PIPE_PLANAR_PREPASS,
|
||||
};
|
||||
|
||||
enum eMaterialGeometry {
|
||||
|
@ -47,6 +48,12 @@ enum eMaterialGeometry {
|
|||
MAT_GEOM_WORLD,
|
||||
};
|
||||
|
||||
enum eMaterialProbe {
|
||||
MAT_PROBE_NONE = 0,
|
||||
MAT_PROBE_REFLECTION,
|
||||
MAT_PROBE_PLANAR,
|
||||
};
|
||||
|
||||
static inline void material_type_from_shader_uuid(uint64_t shader_uuid,
|
||||
eMaterialPipeline &pipeline_type,
|
||||
eMaterialGeometry &geometry_type)
|
||||
|
@ -154,13 +161,13 @@ struct ShaderKey {
|
|||
eMaterialGeometry geometry,
|
||||
eMaterialPipeline pipeline,
|
||||
char blend_flags,
|
||||
bool probe_capture)
|
||||
eMaterialProbe probe_capture)
|
||||
{
|
||||
shader = GPU_material_get_shader(gpumat);
|
||||
options = blend_flags;
|
||||
options = (options << 6u) | shader_uuid_from_material_type(pipeline, geometry);
|
||||
options = (options << 16u) | shader_closure_bits_from_flag(gpumat);
|
||||
options = (options << 1u) | uint64_t(probe_capture);
|
||||
options = (options << 2u) | uint64_t(probe_capture);
|
||||
}
|
||||
|
||||
uint64_t hash() const
|
||||
|
@ -220,7 +227,8 @@ struct MaterialPass {
|
|||
|
||||
struct Material {
|
||||
bool is_alpha_blend_transparent;
|
||||
MaterialPass shadow, shading, prepass, capture, probe_prepass, probe_shading, volume;
|
||||
MaterialPass shadow, shading, prepass, capture, reflection_probe_prepass,
|
||||
reflection_probe_shading, planar_probe_prepass, planar_probe_shading, volume;
|
||||
};
|
||||
|
||||
struct MaterialArray {
|
||||
|
@ -276,7 +284,7 @@ class MaterialModule {
|
|||
::Material *blender_mat,
|
||||
eMaterialPipeline pipeline_type,
|
||||
eMaterialGeometry geometry_type,
|
||||
bool probe_capture = false);
|
||||
eMaterialProbe probe_capture = MAT_PROBE_NONE);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -797,12 +797,11 @@ void DeferredProbeLayer::begin_sync()
|
|||
}
|
||||
|
||||
DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
||||
|
||||
prepass_double_sided_ps_ = &prepass_ps_.sub("DoubleSided");
|
||||
prepass_double_sided_ps_->state_set(state_depth_only);
|
||||
|
||||
prepass_single_sided_ps_ = &prepass_ps_.sub("SingleSided");
|
||||
prepass_single_sided_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK);
|
||||
/* Only setting up static pass because we don't use motion vectors for light-probes. */
|
||||
prepass_double_sided_static_ps_ = &prepass_ps_.sub("DoubleSided");
|
||||
prepass_double_sided_static_ps_->state_set(state_depth_only);
|
||||
prepass_single_sided_static_ps_ = &prepass_ps_.sub("SingleSided");
|
||||
prepass_single_sided_static_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK);
|
||||
}
|
||||
{
|
||||
gbuffer_ps_.init();
|
||||
|
@ -869,8 +868,8 @@ void DeferredProbeLayer::end_sync()
|
|||
PassMain::Sub *DeferredProbeLayer::prepass_add(::Material *blender_mat, GPUMaterial *gpumat)
|
||||
{
|
||||
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
|
||||
prepass_single_sided_ps_ :
|
||||
prepass_double_sided_ps_;
|
||||
prepass_single_sided_static_ps_ :
|
||||
prepass_double_sided_static_ps_;
|
||||
|
||||
return &pass->sub(GPU_material_get_name(gpumat));
|
||||
}
|
||||
|
@ -951,6 +950,115 @@ void DeferredProbePipeline::render(View &view,
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deferred Planar Probe Pipeline
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void PlanarProbePipeline::begin_sync()
|
||||
{
|
||||
{
|
||||
prepass_ps_.init();
|
||||
prepass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
prepass_ps_.bind_ubo(CLIP_PLANE_BUF, inst_.planar_probes.world_clip_buf_);
|
||||
inst_.bind_uniform_data(&prepass_ps_);
|
||||
inst_.sampling.bind_resources(&prepass_ps_);
|
||||
|
||||
DRWState state_depth_only = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
||||
|
||||
prepass_double_sided_static_ps_ = &prepass_ps_.sub("DoubleSided.Static");
|
||||
prepass_double_sided_static_ps_->state_set(state_depth_only);
|
||||
|
||||
prepass_single_sided_static_ps_ = &prepass_ps_.sub("SingleSided.Static");
|
||||
prepass_single_sided_static_ps_->state_set(state_depth_only | DRW_STATE_CULL_BACK);
|
||||
}
|
||||
{
|
||||
gbuffer_ps_.init();
|
||||
gbuffer_ps_.bind_image(GBUF_CLOSURE_SLOT, &inst_.gbuffer.closure_tx);
|
||||
gbuffer_ps_.bind_image(GBUF_COLOR_SLOT, &inst_.gbuffer.color_tx);
|
||||
gbuffer_ps_.bind_image(GBUF_HEADER_SLOT, &inst_.gbuffer.header_tx);
|
||||
gbuffer_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
inst_.bind_uniform_data(&gbuffer_ps_);
|
||||
inst_.sampling.bind_resources(&gbuffer_ps_);
|
||||
inst_.hiz_buffer.bind_resources(&gbuffer_ps_);
|
||||
inst_.cryptomatte.bind_resources(&gbuffer_ps_);
|
||||
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_EQUAL;
|
||||
|
||||
gbuffer_double_sided_ps_ = &gbuffer_ps_.sub("DoubleSided");
|
||||
gbuffer_double_sided_ps_->state_set(state);
|
||||
|
||||
gbuffer_single_sided_ps_ = &gbuffer_ps_.sub("SingleSided");
|
||||
gbuffer_single_sided_ps_->state_set(state | DRW_STATE_CULL_BACK);
|
||||
}
|
||||
{
|
||||
PassSimple &pass = eval_light_ps_;
|
||||
pass.init();
|
||||
pass.shader_set(inst_.shaders.static_shader_get(DEFERRED_CAPTURE_EVAL));
|
||||
inst_.bind_uniform_data(&pass);
|
||||
inst_.gbuffer.bind_resources(&pass);
|
||||
inst_.lights.bind_resources(&pass);
|
||||
inst_.shadows.bind_resources(&pass);
|
||||
inst_.sampling.bind_resources(&pass);
|
||||
inst_.hiz_buffer.bind_resources(&pass);
|
||||
inst_.irradiance_cache.bind_resources(&pass);
|
||||
pass.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
}
|
||||
|
||||
closure_bits_ = CLOSURE_NONE;
|
||||
}
|
||||
|
||||
void PlanarProbePipeline::end_sync()
|
||||
{
|
||||
/* No-op for now. */
|
||||
}
|
||||
|
||||
PassMain::Sub *PlanarProbePipeline::prepass_add(::Material *blender_mat, GPUMaterial *gpumat)
|
||||
{
|
||||
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
|
||||
prepass_single_sided_static_ps_ :
|
||||
prepass_double_sided_static_ps_;
|
||||
return &pass->sub(GPU_material_get_name(gpumat));
|
||||
}
|
||||
|
||||
PassMain::Sub *PlanarProbePipeline::material_add(::Material *blender_mat, GPUMaterial *gpumat)
|
||||
{
|
||||
eClosureBits closure_bits = shader_closure_bits_from_flag(gpumat);
|
||||
closure_bits_ |= closure_bits;
|
||||
|
||||
PassMain::Sub *pass = (blender_mat->blend_flag & MA_BL_CULL_BACKFACE) ?
|
||||
gbuffer_single_sided_ps_ :
|
||||
gbuffer_double_sided_ps_;
|
||||
return &pass->sub(GPU_material_get_name(gpumat));
|
||||
}
|
||||
|
||||
void PlanarProbePipeline::render(View &view, Framebuffer &combined_fb, int2 extent)
|
||||
{
|
||||
GPU_debug_group_begin("Planar.Capture");
|
||||
|
||||
GPU_framebuffer_bind(combined_fb);
|
||||
GPU_framebuffer_clear_depth(combined_fb, 1.0f);
|
||||
inst_.manager->submit(prepass_ps_, view);
|
||||
|
||||
inst_.lights.set_view(view, extent);
|
||||
inst_.shadows.set_view(view);
|
||||
inst_.irradiance_cache.set_view(view);
|
||||
|
||||
inst_.gbuffer.acquire(extent, closure_bits_);
|
||||
|
||||
GPU_framebuffer_bind(combined_fb);
|
||||
GPU_framebuffer_clear_color(combined_fb, float4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
inst_.manager->submit(gbuffer_ps_, view);
|
||||
inst_.manager->submit(eval_light_ps_, view);
|
||||
|
||||
inst_.gbuffer.release();
|
||||
|
||||
GPU_debug_group_end();
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Capture Pipeline
|
||||
*
|
||||
|
|
|
@ -176,10 +176,7 @@ class ForwardPipeline {
|
|||
/** \name Deferred lighting.
|
||||
* \{ */
|
||||
|
||||
class DeferredLayer {
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
struct DeferredLayerBase {
|
||||
PassMain prepass_ps_ = {"Prepass"};
|
||||
PassMain::Sub *prepass_single_sided_static_ps_ = nullptr;
|
||||
PassMain::Sub *prepass_single_sided_moving_ps_ = nullptr;
|
||||
|
@ -190,14 +187,19 @@ class DeferredLayer {
|
|||
PassMain::Sub *gbuffer_single_sided_ps_ = nullptr;
|
||||
PassMain::Sub *gbuffer_double_sided_ps_ = nullptr;
|
||||
|
||||
/* Closures bits from the materials in this pass. */
|
||||
eClosureBits closure_bits_ = CLOSURE_NONE;
|
||||
};
|
||||
|
||||
class DeferredLayer : private DeferredLayerBase {
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
/* Evaluate all light objects contribution. */
|
||||
PassSimple eval_light_ps_ = {"EvalLights"};
|
||||
/* Combine direct and indirect light contributions and apply BSDF color. */
|
||||
PassSimple combine_ps_ = {"Combine"};
|
||||
|
||||
/* Closures bits from the materials in this pass. */
|
||||
eClosureBits closure_bits_ = CLOSURE_NONE;
|
||||
|
||||
/**
|
||||
* Accumulation textures for all stages of lighting evaluation (Light, SSR, SSSS, SSGI ...).
|
||||
* These are split and separate from the main radiance buffer in order to accumulate light for
|
||||
|
@ -214,7 +216,9 @@ class DeferredLayer {
|
|||
GPUTexture *indirect_reflect_tx_ = nullptr;
|
||||
GPUTexture *indirect_refract_tx_ = nullptr;
|
||||
|
||||
/* TODO(fclem): This should be a TextureFromPool. */
|
||||
Texture radiance_behind_tx_ = {"radiance_behind_tx"};
|
||||
/* TODO(fclem): This shouldn't be part of the pipeline but of the view. */
|
||||
Texture radiance_feedback_tx_ = {"radiance_feedback_tx"};
|
||||
float4x4 radiance_feedback_persmat_;
|
||||
|
||||
|
@ -290,23 +294,12 @@ class VolumePipeline {
|
|||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deferred Probe Capture.
|
||||
* \{ */
|
||||
class DeferredProbeLayer {
|
||||
class DeferredProbeLayer : DeferredLayerBase {
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
PassMain prepass_ps_ = {"Prepass"};
|
||||
PassMain::Sub *prepass_single_sided_ps_ = nullptr;
|
||||
PassMain::Sub *prepass_double_sided_ps_ = nullptr;
|
||||
|
||||
PassMain gbuffer_ps_ = {"Shading"};
|
||||
PassMain::Sub *gbuffer_single_sided_ps_ = nullptr;
|
||||
PassMain::Sub *gbuffer_double_sided_ps_ = nullptr;
|
||||
|
||||
PassSimple eval_light_ps_ = {"EvalLights"};
|
||||
|
||||
/* Closures bits from the materials in this pass. */
|
||||
eClosureBits closure_bits_;
|
||||
|
||||
public:
|
||||
DeferredProbeLayer(Instance &inst) : inst_(inst){};
|
||||
|
||||
|
@ -337,6 +330,33 @@ class DeferredProbePipeline {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deferred Planar Probe Capture.
|
||||
* \{ */
|
||||
|
||||
class PlanarProbePipeline : DeferredLayerBase {
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
||||
PassSimple eval_light_ps_ = {"EvalLights"};
|
||||
|
||||
/* Closures bits from the materials in this pass. */
|
||||
eClosureBits closure_bits_ = CLOSURE_NONE;
|
||||
|
||||
public:
|
||||
PlanarProbePipeline(Instance &inst) : inst_(inst){};
|
||||
|
||||
void begin_sync();
|
||||
void end_sync();
|
||||
|
||||
PassMain::Sub *prepass_add(::Material *material, GPUMaterial *gpumat);
|
||||
PassMain::Sub *material_add(::Material *material, GPUMaterial *gpumat);
|
||||
|
||||
void render(View &view, Framebuffer &combined_fb, int2 extent);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Capture Pipeline
|
||||
*
|
||||
|
@ -449,6 +469,7 @@ class PipelineModule {
|
|||
WorldPipeline world;
|
||||
WorldVolumePipeline world_volume;
|
||||
DeferredProbePipeline probe;
|
||||
PlanarProbePipeline planar;
|
||||
DeferredPipeline deferred;
|
||||
ForwardPipeline forward;
|
||||
ShadowPipeline shadow;
|
||||
|
@ -463,6 +484,7 @@ class PipelineModule {
|
|||
world(inst),
|
||||
world_volume(inst),
|
||||
probe(inst),
|
||||
planar(inst),
|
||||
deferred(inst),
|
||||
forward(inst),
|
||||
shadow(inst),
|
||||
|
@ -472,6 +494,7 @@ class PipelineModule {
|
|||
void begin_sync()
|
||||
{
|
||||
probe.begin_sync();
|
||||
planar.begin_sync();
|
||||
deferred.begin_sync();
|
||||
forward.sync();
|
||||
shadow.sync();
|
||||
|
@ -482,6 +505,7 @@ class PipelineModule {
|
|||
void end_sync()
|
||||
{
|
||||
probe.end_sync();
|
||||
planar.end_sync();
|
||||
deferred.end_sync();
|
||||
}
|
||||
|
||||
|
@ -489,15 +513,27 @@ class PipelineModule {
|
|||
::Material *blender_mat,
|
||||
GPUMaterial *gpumat,
|
||||
eMaterialPipeline pipeline_type,
|
||||
bool probe_capture)
|
||||
eMaterialProbe probe_capture)
|
||||
{
|
||||
if (probe_capture) {
|
||||
if (probe_capture == MAT_PROBE_REFLECTION) {
|
||||
switch (pipeline_type) {
|
||||
case MAT_PIPE_DEFERRED_PREPASS:
|
||||
return probe.prepass_add(blender_mat, gpumat);
|
||||
case MAT_PIPE_DEFERRED:
|
||||
return probe.material_add(blender_mat, gpumat);
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (probe_capture == MAT_PROBE_PLANAR) {
|
||||
switch (pipeline_type) {
|
||||
case MAT_PIPE_PLANAR_PREPASS:
|
||||
return planar.prepass_add(blender_mat, gpumat);
|
||||
case MAT_PIPE_DEFERRED:
|
||||
return planar.material_add(blender_mat, gpumat);
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -532,6 +568,9 @@ class PipelineModule {
|
|||
return shadow.surface_material_add(gpumat);
|
||||
case MAT_PIPE_CAPTURE:
|
||||
return capture.surface_material_add(gpumat);
|
||||
case MAT_PIPE_PLANAR_PREPASS:
|
||||
BLI_assert_unreachable();
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "eevee_planar_probes.hh"
|
||||
#include "eevee_instance.hh"
|
||||
|
||||
namespace blender::eevee {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Planar Probe Module
|
||||
* \{ */
|
||||
|
||||
void PlanarProbeModule::init()
|
||||
{
|
||||
update_probes_ = !probes_.is_empty();
|
||||
}
|
||||
|
||||
void PlanarProbeModule::begin_sync()
|
||||
{
|
||||
for (PlanarProbe &planar_probe : probes_.values()) {
|
||||
planar_probe.is_probe_used = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PlanarProbeModule::sync_object(Object *ob, ObjectHandle &ob_handle)
|
||||
{
|
||||
const ::LightProbe *light_probe = (::LightProbe *)ob->data;
|
||||
if (light_probe->type != LIGHTPROBE_TYPE_PLANAR) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO Cull out of view planars. */
|
||||
|
||||
PlanarProbe &probe = find_or_insert(ob_handle);
|
||||
probe.plane_to_world = float4x4(ob->object_to_world);
|
||||
probe.world_to_plane = float4x4(ob->world_to_object);
|
||||
probe.clipping_offset = light_probe->clipsta;
|
||||
probe.is_probe_used = true;
|
||||
}
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
|
||||
|
||||
void PlanarProbeModule::end_sync()
|
||||
{
|
||||
remove_unused_probes();
|
||||
|
||||
// if (probes_.is_empty()) {
|
||||
// update_probes_ = true;
|
||||
// instance_.sampling.reset();
|
||||
// }
|
||||
}
|
||||
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Jeroen Bakker
commented
use float clip_distance (only start) use float clip_distance (only start)
|
||||
float4x4 PlanarProbeModule::reflection_matrix_get(const float4x4 &plane_to_world,
|
||||
const float4x4 &world_to_plane)
|
||||
{
|
||||
return math::normalize(plane_to_world) * math::from_scale<float4x4>(float3(1, 1, -1)) *
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Clément Foucault
commented
What's this? What's this?
|
||||
math::normalize(world_to_plane);
|
||||
}
|
||||
|
||||
float4 PlanarProbeModule::reflection_clip_plane_get(const float4x4 &plane_to_world,
|
||||
float clip_offset)
|
||||
{
|
||||
/* Compute clip plane equation / normal. */
|
||||
float4 plane_equation = float4(-math::normalize(plane_to_world.z_axis()));
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Clément Foucault
commented
Use R11G11B10 for radiance and a separate DEPTH32F for depth. Use R11G11B10 for radiance and a separate DEPTH32F for depth.
I think you should add a `Framebuffer` too (unconfigured here).
|
||||
plane_equation.w = -math::dot(plane_equation.xyz(), plane_to_world.location());
|
||||
plane_equation.w -= clip_offset;
|
||||
return plane_equation;
|
||||
}
|
||||
|
||||
void PlanarProbeModule::set_view(const draw::View &main_view, int2 main_view_extent)
|
||||
{
|
||||
const int64_t num_probes = probes_.size();
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Clément Foucault
commented
capturing capturing `this`?
|
||||
if (resources_.size() != num_probes) {
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Clément Foucault
commented
Use Use `lookup_or_add_default` instead
|
||||
resources_.reinitialize(num_probes);
|
||||
}
|
||||
|
||||
/* TODO resolution percentage. */
|
||||
int2 extent = main_view_extent;
|
||||
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ;
|
||||
color_tx_.ensure_2d_array(GPU_R11F_G11F_B10F, extent, num_probes, usage);
|
||||
depth_tx_.ensure_2d_array(GPU_DEPTH_COMPONENT32F, extent, num_probes, usage);
|
||||
|
||||
int resource_index = 0;
|
||||
for (PlanarProbe &probe : probes_.values()) {
|
||||
PlanarProbeResources &res = resources_[resource_index];
|
||||
|
||||
float4x4 winmat = main_view.winmat();
|
||||
float4x4 viewmat = main_view.viewmat();
|
||||
viewmat = viewmat * reflection_matrix_get(probe.plane_to_world, probe.world_to_plane);
|
||||
res.view.sync(viewmat, winmat);
|
||||
res.view.visibility_test(false);
|
||||
|
||||
world_clip_buf_.plane = reflection_clip_plane_get(probe.plane_to_world, probe.clipping_offset);
|
||||
world_clip_buf_.push_update();
|
||||
|
||||
res.combined_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx_, resource_index),
|
||||
GPU_ATTACHMENT_TEXTURE_LAYER(color_tx_, resource_index));
|
||||
|
||||
instance_.pipelines.planar.render(res.view, res.combined_fb, main_view_extent);
|
||||
}
|
||||
}
|
||||
|
||||
PlanarProbe &PlanarProbeModule::find_or_insert(ObjectHandle &ob_handle)
|
||||
{
|
||||
PlanarProbe &planar_probe = probes_.lookup_or_add_default(ob_handle.object_key.hash());
|
||||
return planar_probe;
|
||||
}
|
||||
|
||||
void PlanarProbeModule::remove_unused_probes()
|
||||
{
|
||||
probes_.remove_if(
|
||||
[](const PlanarProbes::MutableItem &item) { return !item.value.is_probe_used; });
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup eevee
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "eevee_shader_shared.hh"
|
||||
|
||||
#include "BKE_cryptomatte.hh"
|
||||
|
||||
extern "C" {
|
||||
struct Material;
|
||||
}
|
||||
|
||||
namespace blender::eevee {
|
||||
|
||||
class Instance;
|
||||
struct ObjectHandle;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Planar Probe
|
||||
* \{ */
|
||||
|
||||
struct PlanarProbe {
|
||||
/* Copy of object matrices. */
|
||||
float4x4 plane_to_world;
|
||||
float4x4 world_to_plane;
|
||||
/* Offset to the clipping plane in the normal direction. */
|
||||
float clipping_offset;
|
||||
/* Index in the resource array. */
|
||||
int resource_index;
|
||||
/* Pruning flag. */
|
||||
bool is_probe_used = false;
|
||||
};
|
||||
|
||||
struct PlanarProbeResources : NonCopyable {
|
||||
Framebuffer combined_fb = {"planar.combined_fb"};
|
||||
draw::View view = {"planar.view"};
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Planar Probe Module
|
||||
* \{ */
|
||||
|
||||
class PlanarProbeModule {
|
||||
using PlanarProbes = Map<uint64_t, PlanarProbe>;
|
||||
using Resources = Array<PlanarProbeResources>;
|
||||
|
||||
private:
|
||||
Instance &instance_;
|
||||
|
||||
PlanarProbes probes_;
|
||||
Resources resources_;
|
||||
|
||||
Texture color_tx_ = {"planar.color_tx"};
|
||||
Texture depth_tx_ = {"planar.depth_tx"};
|
||||
|
||||
ClipPlaneBuf world_clip_buf_ = {"world_clip_buf"};
|
||||
|
||||
bool update_probes_ = false;
|
||||
|
||||
public:
|
||||
PlanarProbeModule(Instance &instance) : instance_(instance) {}
|
||||
|
||||
void init();
|
||||
void begin_sync();
|
||||
void sync_object(Object *ob, ObjectHandle &ob_handle);
|
||||
void end_sync();
|
||||
|
||||
void set_view(const draw::View &main_view, int2 main_view_extent);
|
||||
|
||||
template<typename T> void bind_resources(draw::detail::PassBase<T> * /*pass*/) {}
|
||||
|
||||
private:
|
||||
PlanarProbe &find_or_insert(ObjectHandle &ob_handle);
|
||||
void remove_unused_probes();
|
||||
|
||||
/**
|
||||
* Create the reflection matrix that reflect along the XY plane of the given transform.
|
||||
* The transform does not need to be normalized but is expected to be orthogonal.
|
||||
*/
|
||||
float4x4 reflection_matrix_get(const float4x4 &plane_to_world, const float4x4 &world_to_plane);
|
||||
|
||||
/**
|
||||
* Create the reflection clip plane equation that clips along the XY plane of the given
|
||||
* transform. The `clip_offset` will push the clip plane a bit further to avoid missing pixels in
|
||||
* reflections. The transform does not need to be normalized but is expected to be orthogonal.
|
||||
*/
|
||||
float4 reflection_clip_plane_get(const float4x4 &plane_to_world, float clip_offset);
|
||||
|
||||
friend class Instance;
|
||||
friend class PlanarProbePipeline;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
|
@ -154,7 +154,7 @@ void ReflectionProbeModule::sync_object(Object *ob, ObjectHandle &ob_handle)
|
|||
probe.do_render |= is_dirty;
|
||||
probe.is_probe_used = true;
|
||||
|
||||
const bool probe_sync_active = instance_.do_probe_sync();
|
||||
const bool probe_sync_active = instance_.do_reflection_probe_sync();
|
||||
if (!probe_sync_active && probe.do_render) {
|
||||
update_probes_next_sample_ = true;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ void ReflectionProbeModule::end_sync()
|
|||
}
|
||||
}
|
||||
|
||||
const bool do_update = instance_.do_probe_sync() || (only_world && world_updated);
|
||||
const bool do_update = instance_.do_reflection_probe_sync() || (only_world && world_updated);
|
||||
if (!do_update) {
|
||||
if (update_probes_next_sample_ && !update_probes_this_sample_) {
|
||||
DRW_viewport_request_redraw();
|
||||
|
@ -548,7 +548,7 @@ std::ostream &operator<<(std::ostream &os, const ReflectionProbe &probe)
|
|||
std::optional<ReflectionProbeUpdateInfo> ReflectionProbeModule::update_info_pop(
|
||||
const ReflectionProbe::Type probe_type)
|
||||
{
|
||||
const bool do_probe_sync = instance_.do_probe_sync();
|
||||
const bool do_probe_sync = instance_.do_reflection_probe_sync();
|
||||
const bool only_world = has_only_world_probe();
|
||||
const int max_shift = int(log2(max_resolution_));
|
||||
for (const Map<uint64_t, ReflectionProbe>::Item &item : probes_.items()) {
|
||||
|
|
|
@ -336,11 +336,6 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
}
|
||||
}
|
||||
|
||||
/* WORKAROUND: Needed because node_tree isn't present in test shaders. */
|
||||
if (pipeline_type == MAT_PIPE_DEFERRED) {
|
||||
info.additional_info("eevee_render_pass_out");
|
||||
}
|
||||
|
||||
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_AO) &&
|
||||
ELEM(pipeline_type, MAT_PIPE_FORWARD, MAT_PIPE_DEFERRED) &&
|
||||
ELEM(geometry_type, MAT_GEOM_MESH, MAT_GEOM_CURVES))
|
||||
|
@ -356,10 +351,14 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
}
|
||||
}
|
||||
|
||||
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT) == false &&
|
||||
pipeline_type == MAT_PIPE_FORWARD)
|
||||
{
|
||||
/* Opaque forward do support AOVs and render pass if not using transparency. */
|
||||
bool supports_render_passes = (pipeline_type == MAT_PIPE_DEFERRED);
|
||||
/* Opaque forward do support AOVs and render pass if not using transparency. */
|
||||
if (!GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT) &&
|
||||
(pipeline_type == MAT_PIPE_FORWARD)) {
|
||||
supports_render_passes = true;
|
||||
}
|
||||
|
||||
if (supports_render_passes) {
|
||||
info.additional_info("eevee_render_pass_out");
|
||||
info.additional_info("eevee_cryptomatte_out");
|
||||
}
|
||||
|
@ -561,6 +560,9 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
|
|||
case MAT_PIPE_DEFERRED_PREPASS:
|
||||
info.additional_info("eevee_surf_depth");
|
||||
break;
|
||||
case MAT_PIPE_PLANAR_PREPASS:
|
||||
info.additional_info("eevee_surf_depth", "eevee_clip_plane");
|
||||
break;
|
||||
case MAT_PIPE_SHADOW:
|
||||
/* Determine surface shadow shader depending on used update technique. */
|
||||
switch (ShadowModule::shadow_technique) {
|
||||
|
|
|
@ -139,7 +139,10 @@ void SyncModule::sync_mesh(Object *ob,
|
|||
|
||||
bool is_shadow_caster = false;
|
||||
bool is_alpha_blend = false;
|
||||
bool do_probe_sync = inst_.do_probe_sync() && !(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP);
|
||||
bool do_reflection_probe_sync = inst_.do_reflection_probe_sync() &&
|
||||
!(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP);
|
||||
bool do_planar_probe_sync = inst_.do_planar_probe_sync() &&
|
||||
!(ob->visibility_flag & OB_HIDE_PROBE_PLANAR);
|
||||
for (auto i : material_array.gpu_materials.index_range()) {
|
||||
GPUBatch *geom = mat_geom[i];
|
||||
if (geom == nullptr) {
|
||||
|
@ -163,9 +166,15 @@ void SyncModule::sync_mesh(Object *ob,
|
|||
geometry_call(material.prepass.sub_pass, geom, res_handle);
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
Clément Foucault
commented
Add a TODO that we should not compile the shader and create a subpass if the object has no visibiility for these passes. Add a TODO that we should not compile the shader and create a subpass if the object has no visibiility for these passes.
|
||||
geometry_call(material.shadow.sub_pass, geom, res_handle);
|
||||
geometry_call(material.capture.sub_pass, geom, res_handle);
|
||||
if (do_probe_sync) {
|
||||
geometry_call(material.probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.probe_shading.sub_pass, geom, res_handle);
|
||||
/* TODO: We should not compile the shader and create a subpass if the object has no visibiility
|
||||
* for these passes. */
|
||||
if (do_reflection_probe_sync) {
|
||||
geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle);
|
||||
}
|
||||
if (do_planar_probe_sync) {
|
||||
geometry_call(material.planar_probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.planar_probe_shading.sub_pass, geom, res_handle);
|
||||
}
|
||||
|
||||
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
|
||||
|
@ -212,7 +221,10 @@ bool SyncModule::sync_sculpt(Object *ob,
|
|||
|
||||
bool is_shadow_caster = false;
|
||||
bool is_alpha_blend = false;
|
||||
bool do_probe_sync = inst_.do_probe_sync() && !(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP);
|
||||
bool do_reflection_probe_sync = inst_.do_reflection_probe_sync() &&
|
||||
!(ob->visibility_flag & OB_HIDE_PROBE_CUBEMAP);
|
||||
bool do_planar_probe_sync = inst_.do_reflection_probe_sync() &&
|
||||
!(ob->visibility_flag & OB_HIDE_PROBE_PLANAR);
|
||||
for (SculptBatch &batch :
|
||||
sculpt_batches_per_material_get(ob_ref.object, material_array.gpu_materials))
|
||||
{
|
||||
|
@ -229,9 +241,12 @@ bool SyncModule::sync_sculpt(Object *ob,
|
|||
|
||||
/* TODO(Miguel Pozo): Is this needed ? */
|
||||
geometry_call(material.capture.sub_pass, geom, res_handle);
|
||||
if (do_probe_sync) {
|
||||
geometry_call(material.probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.probe_shading.sub_pass, geom, res_handle);
|
||||
if (do_reflection_probe_sync) {
|
||||
geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle);
|
||||
geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle);
|
||||
}
|
||||
if (do_planar_probe_sync) {
|
||||
geometry_call(material.planar_probe_prepass.sub_pass, geom, res_handle);
|
||||
}
|
||||
|
||||
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
|
||||
|
@ -496,6 +511,7 @@ void SyncModule::sync_light_probe(Object *ob, ObjectHandle &ob_handle)
|
|||
{
|
||||
inst_.light_probes.sync_probe(ob, ob_handle);
|
||||
inst_.reflection_probes.sync_object(ob, ob_handle);
|
||||
inst_.planar_probes.sync_object(ob, ob_handle);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -107,6 +107,8 @@ void ShadingView::render()
|
|||
DRW_stats_group_start(name_);
|
||||
DRW_view_set_active(render_view_);
|
||||
|
||||
inst_.planar_probes.set_view(render_view_new_, extent_);
|
||||
|
||||
/* If camera has any motion, compute motion vector in the film pass. Otherwise, we avoid float
|
||||
* precision issue by setting the motion of all static geometry to 0. */
|
||||
float4 clear_velocity = float4(inst_.velocity.camera_has_motion() ? VELOCITY_INVALID : 0.0f);
|
||||
|
|
|
@ -161,4 +161,22 @@ class CaptureView {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Capture Planar View
|
||||
*
|
||||
* View for capturing planar probes outside a ShadingView.
|
||||
* \{ */
|
||||
|
||||
class CapturePlanarView {
|
||||
private:
|
||||
Instance &inst_;
|
||||
Framebuffer capture_fb_ = {"Planar.Capture"};
|
||||
|
||||
public:
|
||||
CapturePlanarView(Instance &inst) : inst_(inst) {}
|
||||
void render_probes();
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::eevee
|
||||
|
|
|
@ -37,6 +37,7 @@ void main()
|
|||
/* World opacity. */
|
||||
out_background = mix(vec4(0.0, 0.0, 0.0, 1.0), out_background, world_opacity_fade);
|
||||
|
||||
#ifdef MAT_RENDER_PASS_SUPPORT
|
||||
/* Clear Render Buffers. */
|
||||
ivec2 texel = ivec2(gl_FragCoord.xy);
|
||||
|
||||
|
@ -56,4 +57,5 @@ void main()
|
|||
output_renderpass_value(uniform_buf.render_pass.shadow_id, 1.0);
|
||||
/** NOTE: AO is done on its own pass. */
|
||||
imageStore(rp_cryptomatte_img, texel, vec4(0.0));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -151,11 +151,11 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred)
|
|||
.fragment_source("eevee_surf_deferred_frag.glsl")
|
||||
.additional_info("eevee_global_ubo",
|
||||
"eevee_utility_texture",
|
||||
"eevee_sampling_data",
|
||||
"eevee_hiz_data",
|
||||
/* Added at runtime because of test shaders not having `node_tree`. */
|
||||
// "eevee_render_pass_out",
|
||||
"eevee_cryptomatte_out");
|
||||
// "eevee_render_pass_out",
|
||||
// "eevee_cryptomatte_out",
|
||||
"eevee_sampling_data",
|
||||
"eevee_hiz_data");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_surf_forward)
|
||||
/* Early fragment test is needed for render passes support for forward surfaces. */
|
||||
|
@ -195,8 +195,9 @@ GPU_SHADER_CREATE_INFO(eevee_surf_world)
|
|||
.fragment_out(0, Type::VEC4, "out_background")
|
||||
.fragment_source("eevee_surf_world_frag.glsl")
|
||||
.additional_info("eevee_global_ubo",
|
||||
"eevee_render_pass_out",
|
||||
"eevee_cryptomatte_out",
|
||||
/* Optionally added depending on the material. */
|
||||
// "eevee_render_pass_out",
|
||||
// "eevee_cryptomatte_out",
|
||||
"eevee_utility_texture");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_surf_shadow)
|
||||
|
|
|
@ -562,6 +562,7 @@ class Texture : NonCopyable {
|
|||
tx_ = create(UNPACK3(extent), mip_len, format, usage, data, false, false);
|
||||
}
|
||||
|
||||
Texture(Texture &&other) = default;
|
||||
~Texture()
|
||||
{
|
||||
free();
|
||||
|
|
|
@ -76,7 +76,8 @@ typedef struct LightProbe {
|
|||
float surfel_density;
|
||||
|
||||
/**
|
||||
* Resolution of the light probe when baked to a texture. Contains `eLightProbeResolution`.
|
||||
* Resolution of the cube light probe when baked to a texture.
|
||||
* Contains `eLightProbeResolution`.
|
||||
*/
|
||||
int resolution;
|
||||
|
||||
|
|
|
@ -803,6 +803,7 @@ enum {
|
|||
OB_SHADOW_CATCHER = 1 << 10,
|
||||
OB_HIDE_PROBE_VOLUME = 1 << 11,
|
||||
OB_HIDE_PROBE_CUBEMAP = 1 << 12,
|
||||
OB_HIDE_PROBE_PLANAR = 1 << 13,
|
||||
};
|
||||
|
||||
/** #Object.shapeflag */
|
||||
|
|
|
@ -2921,6 +2921,11 @@ static void rna_def_object_visibility(StructRNA *srna)
|
|||
prop, "Disable in Cubemap Probes", "Globally disable in cubemap probes");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw");
|
||||
|
||||
prop = RNA_def_property(srna, "hide_probe_planar", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "visibility_flag", OB_HIDE_PROBE_PLANAR);
|
||||
RNA_def_property_ui_text(prop, "Disable in Planar Probes", "Globally disable in planar probes");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw");
|
||||
|
||||
/* Instancer options. */
|
||||
prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER);
|
||||
|
|
Loading…
Reference in New Issue
This shouldn't be a power of 2. But a screen percentage. Should be fine to change the meaning of it in the RNA for planar.
I added its own attribute, otherwise bpy API will get confusing.