diff options
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 13 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 8 | ||||
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 41 | ||||
-rw-r--r-- | intern/cycles/integrator/path_trace_work_gpu.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/integrator_shade_surface.h | 31 | ||||
-rw-r--r-- | intern/cycles/kernel/integrator/integrator_shadow_state_template.h | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_accumulate.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_shader.h | 11 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/render/integrator.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/render/integrator.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_world.c | 1 |
14 files changed, 119 insertions, 30 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 2a51e0be2a4..0f92238015d 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -125,6 +125,11 @@ enum_texture_limit = ( ('8192', "8192", "Limit texture size to 8192 pixels", 7), ) +enum_fast_gi_method = ( + ('REPLACE', "Replace", "Replace global illumination with ambient occlusion after a specified number of bounces"), + ('ADD', "Add", "Add ambient occlusion to diffuse surfaces"), +) + # NOTE: Identifiers are expected to be an upper case version of identifiers from `Pass::get_type_enum()` enum_view3d_shading_render_pass = ( ('', "General", ""), @@ -724,6 +729,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Approximate diffuse indirect light with background tinted ambient occlusion. This provides fast alternative to full global illumination, for interactive viewport rendering or final renders with reduced quality", default=False, ) + + fast_gi_method: EnumProperty( + name="Fast GI Method", + default='REPLACE', + description="Fast GI approximation method", + items=enum_fast_gi_method + ) + ao_bounces: IntProperty( name="AO Bounces", default=1, diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 0ed2dd24f2e..facf1b08676 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -465,8 +465,7 @@ class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel): layout.active = cscene.use_fast_gi col = layout.column(align=True) - col.prop(cscene, "ao_bounces", text="Viewport Bounces") - col.prop(cscene, "ao_bounces_render", text="Render Bounces") + col.prop(cscene, "fast_gi_method", text="Method") if world: light = world.light_settings @@ -474,6 +473,11 @@ class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel): col.prop(light, "ao_factor", text="AO Factor") col.prop(light, "distance", text="AO Distance") + if cscene.fast_gi_method == 'REPLACE': + col = layout.column(align=True) + col.prop(cscene, "ao_bounces", text="Viewport Bounces") + col.prop(cscene, "ao_bounces_render", text="Render Bounces") + class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel): bl_label = "Motion Blur" diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index db5eadeed56..25e7ec71577 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -1375,6 +1375,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, { Background *background = scene->background; Integrator *integrator = scene->integrator; + PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); BL::World b_world = b_scene.world(); @@ -1466,14 +1467,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, graph->connect(background->output("Background"), out->input("Surface")); } + /* Visibility */ if (b_world) { - /* AO */ - BL::WorldLighting b_light = b_world.light_settings(); - - integrator->set_ao_factor(b_light.ao_factor()); - integrator->set_ao_distance(b_light.distance()); - - /* visibility */ PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility"); uint visibility = 0; @@ -1485,16 +1480,38 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, background->set_visibility(visibility); } - else { - integrator->set_ao_factor(1.0f); - integrator->set_ao_distance(10.0f); - } shader->set_graph(graph); shader->tag_update(scene); } - PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + /* Fast GI */ + if (b_world) { + BL::WorldLighting b_light = b_world.light_settings(); + enum { FAST_GI_METHOD_REPLACE = 0, FAST_GI_METHOD_ADD = 1, FAST_GI_METHOD_NUM }; + + const bool use_fast_gi = get_boolean(cscene, "use_fast_gi"); + if (use_fast_gi) { + const int fast_gi_method = get_enum( + cscene, "fast_gi_method", FAST_GI_METHOD_NUM, FAST_GI_METHOD_REPLACE); + integrator->set_ao_factor((fast_gi_method == FAST_GI_METHOD_REPLACE) ? b_light.ao_factor() : + 0.0f); + integrator->set_ao_additive_factor( + (fast_gi_method == FAST_GI_METHOD_ADD) ? b_light.ao_factor() : 0.0f); + } + else { + integrator->set_ao_factor(0.0f); + integrator->set_ao_additive_factor(0.0f); + } + + integrator->set_ao_distance(b_light.distance()); + } + else { + integrator->set_ao_factor(0.0f); + integrator->set_ao_additive_factor(0.0f); + integrator->set_ao_distance(10.0f); + } + background->set_transparent(b_scene.render().film_transparent()); if (background->get_transparent()) { diff --git a/intern/cycles/integrator/path_trace_work_gpu.cpp b/intern/cycles/integrator/path_trace_work_gpu.cpp index 36f275e1075..605c1efca0f 100644 --- a/intern/cycles/integrator/path_trace_work_gpu.cpp +++ b/intern/cycles/integrator/path_trace_work_gpu.cpp @@ -1082,7 +1082,7 @@ bool PathTraceWorkGPU::kernel_creates_shadow_paths(DeviceKernel kernel) bool PathTraceWorkGPU::kernel_creates_ao_paths(DeviceKernel kernel) { - return (device_scene_->data.film.pass_ao != PASS_UNUSED) && + return (device_scene_->data.kernel_features & KERNEL_FEATURE_AO) && (kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE || kernel == DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE); } diff --git a/intern/cycles/kernel/integrator/integrator_shade_surface.h b/intern/cycles/kernel/integrator/integrator_shade_surface.h index 3724b05c6b0..2a0bf4a3046 100644 --- a/intern/cycles/kernel/integrator/integrator_shade_surface.h +++ b/intern/cycles/kernel/integrator/integrator_shade_surface.h @@ -325,17 +325,25 @@ ccl_device_forceinline bool integrate_surface_volume_only_bounce(IntegratorState #endif #if defined(__AO__) -ccl_device_forceinline void integrate_surface_ao_pass( - KernelGlobals kg, - IntegratorState state, - ccl_private const ShaderData *ccl_restrict sd, - ccl_private const RNGState *ccl_restrict rng_state, - ccl_global float *ccl_restrict render_buffer) +ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, + IntegratorState state, + ccl_private const ShaderData *ccl_restrict sd, + ccl_private const RNGState *ccl_restrict + rng_state, + ccl_global float *ccl_restrict render_buffer) { + if (!(kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) && + !(INTEGRATOR_STATE(state, path, flag) & PATH_RAY_CAMERA)) { + return; + } + float bsdf_u, bsdf_v; path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); - const float3 ao_N = shader_bsdf_ao_normal(kg, sd); + float3 ao_N; + const float3 ao_weight = shader_bsdf_ao( + kg, sd, kernel_data.integrator.ao_additive_factor, &ao_N); + float3 ao_D; float ao_pdf; sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); @@ -379,6 +387,10 @@ ccl_device_forceinline void integrate_surface_ao_pass( INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, bounce) = bounce; INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, transparent_bounce) = transparent_bounce; INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, throughput) = throughput; + + if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) { + INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unshadowed_throughput) = ao_weight; + } } #endif /* defined(__AO__) */ @@ -487,10 +499,9 @@ ccl_device bool integrate_surface(KernelGlobals kg, #if defined(__AO__) /* Ambient occlusion pass. */ - if ((kernel_data.film.pass_ao != PASS_UNUSED) && - (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_CAMERA)) { + if (kernel_data.kernel_features & KERNEL_FEATURE_AO) { PROFILING_EVENT(PROFILING_SHADE_SURFACE_AO); - integrate_surface_ao_pass(kg, state, &sd, &rng_state, render_buffer); + integrate_surface_ao(kg, state, &sd, &rng_state, render_buffer); } #endif diff --git a/intern/cycles/kernel/integrator/integrator_shadow_state_template.h b/intern/cycles/kernel/integrator/integrator_shadow_state_template.h index bc35b644ee1..1fbadde2642 100644 --- a/intern/cycles/kernel/integrator/integrator_shadow_state_template.h +++ b/intern/cycles/kernel/integrator/integrator_shadow_state_template.h @@ -42,7 +42,10 @@ KERNEL_STRUCT_MEMBER(shadow_path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING) /* Throughput. */ KERNEL_STRUCT_MEMBER(shadow_path, float3, throughput, KERNEL_FEATURE_PATH_TRACING) /* Throughput for shadow pass. */ -KERNEL_STRUCT_MEMBER(shadow_path, float3, unshadowed_throughput, KERNEL_FEATURE_SHADOW_PASS) +KERNEL_STRUCT_MEMBER(shadow_path, + float3, + unshadowed_throughput, + KERNEL_FEATURE_SHADOW_PASS | KERNEL_FEATURE_AO_ADDITIVE) /* Ratio of throughput to distinguish diffuse and glossy render passes. */ KERNEL_STRUCT_MEMBER(shadow_path, float3, diffuse_glossy_ratio, KERNEL_FEATURE_LIGHT_PASSES) /* Number of intersections found by ray-tracing. */ diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 54492bef974..c494cb4e189 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -410,7 +410,13 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, /* Ambient occlusion. */ if (path_flag & PATH_RAY_SHADOW_FOR_AO) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, contribution); + if ((kernel_data.kernel_features & KERNEL_FEATURE_AO_PASS) && (path_flag & PATH_RAY_CAMERA)) { + kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, contribution); + } + if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) { + const float3 ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput); + kernel_accum_combined_pass(kg, path_flag, sample, contribution * ao_weight, buffer); + } return; } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index d25191b72cf..22db6d0124e 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -457,19 +457,26 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const return (is_zero(N)) ? sd->N : normalize(N); } -ccl_device float3 shader_bsdf_ao_normal(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device float3 shader_bsdf_ao(KernelGlobals kg, + ccl_private const ShaderData *sd, + const float ao_factor, + ccl_private float3 *N_) { + float3 eval = zero_float3(); float3 N = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; + if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; + eval += sc->weight * ao_factor; N += bsdf->N * fabsf(average(sc->weight)); } } - return (is_zero(N)) ? sd->N : normalize(N); + *N_ = (is_zero(N)) ? sd->N : normalize(N); + return eval; } #ifdef __SUBSURFACE__ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index df6b6b5be20..94c27a1fca5 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1147,6 +1147,7 @@ typedef struct KernelIntegrator { int ao_bounces; float ao_bounces_distance; float ao_bounces_factor; + float ao_additive_factor; /* transparent */ int transparent_min_bounce; @@ -1179,7 +1180,7 @@ typedef struct KernelIntegrator { int has_shadow_catcher; /* padding */ - int pad1, pad2; + int pad1; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); @@ -1561,6 +1562,11 @@ enum KernelFeatureFlag : unsigned int { /* Shadow render pass. */ KERNEL_FEATURE_SHADOW_PASS = (1U << 24U), + + /* AO. */ + KERNEL_FEATURE_AO_PASS = (1U << 25U), + KERNEL_FEATURE_AO_ADDITIVE = (1U << 26U), + KERNEL_FEATURE_AO = (KERNEL_FEATURE_AO_PASS | KERNEL_FEATURE_AO_ADDITIVE), }; /* Shader node feature mask, to specialize shader evaluation for kernels. */ diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 1f7882ea91e..bd18c777eb5 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -680,6 +680,10 @@ uint Film::get_kernel_features(const Scene *scene) const kernel_features |= KERNEL_FEATURE_SHADOW_PASS; } } + + if (pass_type == PASS_AO) { + kernel_features |= KERNEL_FEATURE_AO_PASS; + } } return kernel_features; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index d74d14242bb..16d9fc60fd3 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -55,6 +55,7 @@ NODE_DEFINE(Integrator) SOCKET_INT(ao_bounces, "AO Bounces", 0); SOCKET_FLOAT(ao_factor, "AO Factor", 0.0f); SOCKET_FLOAT(ao_distance, "AO Distance", FLT_MAX); + SOCKET_FLOAT(ao_additive_factor, "AO Additive Factor", 0.0f); SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024); SOCKET_FLOAT(volume_step_rate, "Volume Step Rate", 1.0f); @@ -159,6 +160,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->ao_bounces = ao_bounces; kintegrator->ao_bounces_distance = ao_distance; kintegrator->ao_bounces_factor = ao_factor; + kintegrator->ao_additive_factor = ao_additive_factor; /* Transparent Shadows * We only need to enable transparent shadows, if we actually have @@ -268,6 +270,17 @@ void Integrator::tag_update(Scene *scene, uint32_t flag) } } +uint Integrator::get_kernel_features(const Scene *scene) const +{ + uint kernel_features = 0; + + if (ao_additive_factor != 0.0f) { + kernel_features |= KERNEL_FEATURE_AO_ADDITIVE; + } + + return kernel_features; +} + AdaptiveSampling Integrator::get_adaptive_sampling() const { AdaptiveSampling adaptive_sampling; diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 5ad419e02ca..91efc25e51e 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -47,6 +47,7 @@ class Integrator : public Node { NODE_SOCKET_API(int, ao_bounces) NODE_SOCKET_API(float, ao_factor) NODE_SOCKET_API(float, ao_distance) + NODE_SOCKET_API(float, ao_additive_factor) NODE_SOCKET_API(int, volume_max_steps) NODE_SOCKET_API(float, volume_step_rate) @@ -101,6 +102,8 @@ class Integrator : public Node { void tag_update(Scene *scene, uint32_t flag); + uint get_kernel_features(const Scene *scene) const; + AdaptiveSampling get_adaptive_sampling() const; DenoiseParams get_denoise_params() const; }; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 7c5e1a86f5e..669f5abf7d6 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -522,6 +522,7 @@ void Scene::update_kernel_features() } kernel_features |= film->get_kernel_features(this); + kernel_features |= integrator->get_kernel_features(this); dscene.data.kernel_features = kernel_features; diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index 826e6d21c36..68f11d71de2 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -128,6 +128,7 @@ static void rna_def_lighting(BlenderRNA *brna) prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "aodist"); + RNA_def_property_range(prop, 0, FLT_MAX); RNA_def_property_ui_text( prop, "Distance", "Length of rays, defines how far away other faces give occlusion effect"); RNA_def_property_update(prop, 0, "rna_World_update"); |