forked from bartvdbraak/blender
Cycles: volume sampling method can now be set per material/world.
This gives you "Multiple Importance", "Distance" and "Equiangular" choices. What multiple importance sampling does is make things more robust to certain types of noise at the cost of a bit more noise in cases where the individual strategies are always better. So if you've got a pretty dense volume that's lit from far away then distance sampling is usually more efficient. If you've got a light inside or near the volume then equiangular sampling is better. If you have a combination of both, then the multiple importance sampling will be better.
This commit is contained in:
parent
a29807cd63
commit
5fa68133c9
@ -108,10 +108,10 @@ enum_integrator = (
|
|||||||
('PATH', "Path Tracing", "Pure path tracing integrator"),
|
('PATH', "Path Tracing", "Pure path tracing integrator"),
|
||||||
)
|
)
|
||||||
|
|
||||||
enum_volume_homogeneous_sampling = (
|
enum_volume_sampling = (
|
||||||
('DISTANCE', "Distance", "Use Distance Sampling"),
|
('DISTANCE', "Distance", "Use distance sampling, best for dense volumes with lights far away"),
|
||||||
('EQUI_ANGULAR', "Equi-angular", "Use Equi-angular Sampling"),
|
('EQUIANGULAR', "Equiangular", "Use equiangular sampling, best for volumes with low density with light inside or near the volume"),
|
||||||
('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling"),
|
('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -147,13 +147,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
default='PATH',
|
default='PATH',
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.volume_homogeneous_sampling = EnumProperty(
|
|
||||||
name="Homogeneous Sampling",
|
|
||||||
description="Sampling method to use for homogeneous volumes",
|
|
||||||
items=enum_volume_homogeneous_sampling,
|
|
||||||
default='DISTANCE',
|
|
||||||
)
|
|
||||||
|
|
||||||
cls.use_square_samples = BoolProperty(
|
cls.use_square_samples = BoolProperty(
|
||||||
name="Square Samples",
|
name="Square Samples",
|
||||||
description="Square sampling values for easier artist control",
|
description="Square sampling values for easier artist control",
|
||||||
@ -237,7 +230,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||||||
name="Volume Samples",
|
name="Volume Samples",
|
||||||
description="Number of volume scattering samples to render for each AA sample",
|
description="Number of volume scattering samples to render for each AA sample",
|
||||||
min=1, max=10000,
|
min=1, max=10000,
|
||||||
default=1,
|
default=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
cls.sampling_pattern = EnumProperty(
|
cls.sampling_pattern = EnumProperty(
|
||||||
@ -603,6 +596,12 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
|
|||||||
"(not using any textures), for faster rendering",
|
"(not using any textures), for faster rendering",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
cls.volume_sampling = EnumProperty(
|
||||||
|
name="Volume Sampling",
|
||||||
|
description="Sampling method to use for volumes",
|
||||||
|
items=enum_volume_sampling,
|
||||||
|
default='DISTANCE',
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
@ -673,6 +672,12 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
|
|||||||
"(not using any textures), for faster rendering",
|
"(not using any textures), for faster rendering",
|
||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
cls.volume_sampling = EnumProperty(
|
||||||
|
name="Volume Sampling",
|
||||||
|
description="Sampling method to use for volumes",
|
||||||
|
items=enum_volume_sampling,
|
||||||
|
default='EQUIANGULAR',
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def unregister(cls):
|
def unregister(cls):
|
||||||
|
@ -176,16 +176,11 @@ class CyclesRender_PT_volume_sampling(CyclesButtonsPanel, Panel):
|
|||||||
scene = context.scene
|
scene = context.scene
|
||||||
cscene = scene.cycles
|
cscene = scene.cycles
|
||||||
|
|
||||||
split = layout.split(align=True)
|
row = layout.row()
|
||||||
|
row.label("Heterogeneous:")
|
||||||
sub = split.column(align=True)
|
row = layout.row()
|
||||||
sub.label("Heterogeneous:")
|
row.prop(cscene, "volume_step_size")
|
||||||
sub.prop(cscene, "volume_step_size")
|
row.prop(cscene, "volume_max_steps")
|
||||||
sub.prop(cscene, "volume_max_steps")
|
|
||||||
|
|
||||||
sub = split.column(align=True)
|
|
||||||
sub.label("Homogeneous:")
|
|
||||||
sub.prop(cscene, "volume_homogeneous_sampling", text="")
|
|
||||||
|
|
||||||
|
|
||||||
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
|
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
|
||||||
@ -829,8 +824,6 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
|
|||||||
world = context.world
|
world = context.world
|
||||||
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
|
panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
|
||||||
|
|
||||||
layout.prop(world.cycles, "homogeneous_volume")
|
|
||||||
|
|
||||||
|
|
||||||
class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
|
class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
|
||||||
bl_label = "Ambient Occlusion"
|
bl_label = "Ambient Occlusion"
|
||||||
@ -922,15 +915,24 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
|
|||||||
cworld = world.cycles
|
cworld = world.cycles
|
||||||
cscene = context.scene.cycles
|
cscene = context.scene.cycles
|
||||||
|
|
||||||
col = layout.column()
|
split = layout.split()
|
||||||
|
|
||||||
col.prop(cworld, "sample_as_light")
|
col = split.column()
|
||||||
sub = col.row(align=True)
|
|
||||||
|
col.label(text="Surface:")
|
||||||
|
col.prop(cworld, "sample_as_light", text="Multiple Importance")
|
||||||
|
|
||||||
|
sub = col.column(align=True)
|
||||||
sub.active = cworld.sample_as_light
|
sub.active = cworld.sample_as_light
|
||||||
sub.prop(cworld, "sample_map_resolution")
|
sub.prop(cworld, "sample_map_resolution")
|
||||||
if cscene.progressive == 'BRANCHED_PATH':
|
if cscene.progressive == 'BRANCHED_PATH':
|
||||||
sub.prop(cworld, "samples")
|
sub.prop(cworld, "samples")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Volume:")
|
||||||
|
col.prop(cworld, "volume_sampling", text="")
|
||||||
|
col.prop(cworld, "homogeneous_volume", text="Homogeneous")
|
||||||
|
|
||||||
|
|
||||||
class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
|
class CyclesMaterial_PT_preview(CyclesButtonsPanel, Panel):
|
||||||
bl_label = "Preview"
|
bl_label = "Preview"
|
||||||
@ -979,8 +981,6 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
|
|||||||
|
|
||||||
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
|
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
|
||||||
|
|
||||||
layout.prop(cmat, "homogeneous_volume")
|
|
||||||
|
|
||||||
|
|
||||||
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
|
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
|
||||||
bl_label = "Displacement"
|
bl_label = "Displacement"
|
||||||
@ -1023,10 +1023,18 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
|
|||||||
col.label()
|
col.label()
|
||||||
col.prop(mat, "pass_index")
|
col.prop(mat, "pass_index")
|
||||||
|
|
||||||
col = layout.column()
|
split = layout.split()
|
||||||
col.prop(cmat, "sample_as_light")
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Surface:")
|
||||||
|
col.prop(cmat, "sample_as_light", text="Multiple Importance")
|
||||||
col.prop(cmat, "use_transparent_shadow")
|
col.prop(cmat, "use_transparent_shadow")
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
col.label(text="Volume:")
|
||||||
|
col.prop(cmat, "volume_sampling", text="")
|
||||||
|
col.prop(cmat, "homogeneous_volume", text="Homogeneous")
|
||||||
|
|
||||||
|
|
||||||
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
|
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
|
||||||
bl_label = ""
|
bl_label = ""
|
||||||
|
@ -977,6 +977,7 @@ void BlenderSync::sync_materials(bool update_all)
|
|||||||
shader->use_mis = get_boolean(cmat, "sample_as_light");
|
shader->use_mis = get_boolean(cmat, "sample_as_light");
|
||||||
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
|
shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
|
||||||
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
|
shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
|
||||||
|
shader->volume_sampling_method = RNA_enum_get(&cmat, "volume_sampling");
|
||||||
|
|
||||||
shader->set_graph(graph);
|
shader->set_graph(graph);
|
||||||
shader->tag_update(scene);
|
shader->tag_update(scene);
|
||||||
@ -1006,6 +1007,7 @@ void BlenderSync::sync_world(bool update_all)
|
|||||||
/* volume */
|
/* volume */
|
||||||
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
|
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
|
||||||
shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
|
shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
|
||||||
|
shader->volume_sampling_method = RNA_enum_get(&cworld, "volume_sampling");
|
||||||
}
|
}
|
||||||
else if(b_world) {
|
else if(b_world) {
|
||||||
ShaderNode *closure, *out;
|
ShaderNode *closure, *out;
|
||||||
|
@ -177,7 +177,6 @@ void BlenderSync::sync_integrator()
|
|||||||
integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
|
integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
|
||||||
integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
|
integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
|
||||||
|
|
||||||
integrator->volume_homogeneous_sampling = RNA_enum_get(&cscene, "volume_homogeneous_sampling");
|
|
||||||
integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
|
integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
|
||||||
integrator->volume_step_size = get_float(cscene, "volume_step_size");
|
integrator->volume_step_size = get_float(cscene, "volume_step_size");
|
||||||
|
|
||||||
|
@ -89,7 +89,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
|
|||||||
volume_ray.t = (hit)? isect.t: FLT_MAX;
|
volume_ray.t = (hit)? isect.t: FLT_MAX;
|
||||||
|
|
||||||
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
|
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
|
||||||
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, false);
|
int sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
|
||||||
|
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, false, sampling_method);
|
||||||
|
|
||||||
if(decoupled) {
|
if(decoupled) {
|
||||||
/* cache steps along volume for repeated sampling */
|
/* cache steps along volume for repeated sampling */
|
||||||
@ -99,6 +100,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray,
|
|||||||
shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
|
shader_setup_from_volume(kg, &volume_sd, &volume_ray, state.bounce, state.transparent_bounce);
|
||||||
kernel_volume_decoupled_record(kg, &state,
|
kernel_volume_decoupled_record(kg, &state,
|
||||||
&volume_ray, &volume_sd, &volume_segment, heterogeneous);
|
&volume_ray, &volume_sd, &volume_segment, heterogeneous);
|
||||||
|
|
||||||
|
volume_segment.sampling_method = sampling_method;
|
||||||
|
|
||||||
/* emission */
|
/* emission */
|
||||||
if(volume_segment.closure_flag & SD_EMISSION)
|
if(volume_segment.closure_flag & SD_EMISSION)
|
||||||
@ -468,7 +471,8 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
|
|||||||
volume_ray.t = (hit)? isect.t: FLT_MAX;
|
volume_ray.t = (hit)? isect.t: FLT_MAX;
|
||||||
|
|
||||||
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
|
bool heterogeneous = volume_stack_is_heterogeneous(kg, state.volume_stack);
|
||||||
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true);
|
int sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
|
||||||
|
bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method);
|
||||||
|
|
||||||
if(decoupled) {
|
if(decoupled) {
|
||||||
/* cache steps along volume for repeated sampling */
|
/* cache steps along volume for repeated sampling */
|
||||||
@ -479,6 +483,8 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
|
|||||||
kernel_volume_decoupled_record(kg, &state,
|
kernel_volume_decoupled_record(kg, &state,
|
||||||
&volume_ray, &volume_sd, &volume_segment, heterogeneous);
|
&volume_ray, &volume_sd, &volume_segment, heterogeneous);
|
||||||
|
|
||||||
|
volume_segment.sampling_method = sampling_method;
|
||||||
|
|
||||||
/* emission */
|
/* emission */
|
||||||
if(volume_segment.closure_flag & SD_EMISSION)
|
if(volume_segment.closure_flag & SD_EMISSION)
|
||||||
path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce);
|
path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state.bounce);
|
||||||
@ -814,7 +820,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
|
|||||||
|
|
||||||
/* direct light sampling */
|
/* direct light sampling */
|
||||||
if(volume_segment.closure_flag & SD_SCATTER) {
|
if(volume_segment.closure_flag & SD_SCATTER) {
|
||||||
|
volume_segment.sampling_method = volume_stack_sampling_method(kg, state.volume_stack);
|
||||||
|
|
||||||
bool all = kernel_data.integrator.sample_all_lights_direct;
|
bool all = kernel_data.integrator.sample_all_lights_direct;
|
||||||
|
|
||||||
kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
|
kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
|
||||||
throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment);
|
throughput, &state, &L, 1.0f, all, &volume_ray, &volume_segment);
|
||||||
|
|
||||||
|
@ -577,7 +577,8 @@ enum ShaderDataFlag {
|
|||||||
SD_AO = 512, /* have ao closure? */
|
SD_AO = 512, /* have ao closure? */
|
||||||
SD_TRANSPARENT = 1024, /* have transparent closure? */
|
SD_TRANSPARENT = 1024, /* have transparent closure? */
|
||||||
|
|
||||||
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
|
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|
|
||||||
|
SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
|
||||||
|
|
||||||
/* shader flags */
|
/* shader flags */
|
||||||
SD_USE_MIS = 2048, /* direct light sample */
|
SD_USE_MIS = 2048, /* direct light sample */
|
||||||
@ -586,13 +587,17 @@ enum ShaderDataFlag {
|
|||||||
SD_HAS_ONLY_VOLUME = 16384, /* has only volume shader, no surface */
|
SD_HAS_ONLY_VOLUME = 16384, /* has only volume shader, no surface */
|
||||||
SD_HETEROGENEOUS_VOLUME = 32768, /* has heterogeneous volume */
|
SD_HETEROGENEOUS_VOLUME = 32768, /* has heterogeneous volume */
|
||||||
SD_HAS_BSSRDF_BUMP = 65536, /* bssrdf normal uses bump */
|
SD_HAS_BSSRDF_BUMP = 65536, /* bssrdf normal uses bump */
|
||||||
|
SD_VOLUME_EQUIANGULAR = 131072, /* use equiangular sampling */
|
||||||
|
SD_VOLUME_MIS = 262144, /* use multiple importance sampling */
|
||||||
|
|
||||||
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|SD_HAS_BSSRDF_BUMP),
|
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
|
||||||
|
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
|
||||||
|
SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS),
|
||||||
|
|
||||||
/* object flags */
|
/* object flags */
|
||||||
SD_HOLDOUT_MASK = 131072, /* holdout for camera rays */
|
SD_HOLDOUT_MASK = 524288, /* holdout for camera rays */
|
||||||
SD_OBJECT_MOTION = 262144, /* has object motion blur */
|
SD_OBJECT_MOTION = 1048576, /* has object motion blur */
|
||||||
SD_TRANSFORM_APPLIED = 524288, /* vertices have transform applied */
|
SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */
|
||||||
|
|
||||||
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
|
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
|
||||||
};
|
};
|
||||||
@ -894,7 +899,6 @@ typedef struct KernelIntegrator {
|
|||||||
int aa_samples;
|
int aa_samples;
|
||||||
|
|
||||||
/* volume render */
|
/* volume render */
|
||||||
int volume_homogeneous_sampling;
|
|
||||||
int use_volumes;
|
int use_volumes;
|
||||||
int volume_max_steps;
|
int volume_max_steps;
|
||||||
float volume_step_size;
|
float volume_step_size;
|
||||||
|
@ -116,6 +116,36 @@ ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, VolumeStack *st
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stack)
|
||||||
|
{
|
||||||
|
if(kernel_data.integrator.num_all_lights == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int method = -1;
|
||||||
|
|
||||||
|
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
|
||||||
|
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*2);
|
||||||
|
|
||||||
|
if(shader_flag & SD_VOLUME_MIS) {
|
||||||
|
return SD_VOLUME_MIS;
|
||||||
|
}
|
||||||
|
else if(shader_flag & SD_VOLUME_EQUIANGULAR) {
|
||||||
|
if(method == 0)
|
||||||
|
return SD_VOLUME_MIS;
|
||||||
|
|
||||||
|
method = SD_VOLUME_EQUIANGULAR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(method == SD_VOLUME_EQUIANGULAR)
|
||||||
|
return SD_VOLUME_MIS;
|
||||||
|
|
||||||
|
method = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
/* Volume Shadows
|
/* Volume Shadows
|
||||||
*
|
*
|
||||||
* These functions are used to attenuate shadow rays to lights. Both absorption
|
* These functions are used to attenuate shadow rays to lights. Both absorption
|
||||||
@ -562,6 +592,8 @@ typedef struct VolumeSegment {
|
|||||||
|
|
||||||
float3 accum_emission; /* accumulated emission at end of segment */
|
float3 accum_emission; /* accumulated emission at end of segment */
|
||||||
float3 accum_transmittance; /* accumulated transmittance at end of segment */
|
float3 accum_transmittance; /* accumulated transmittance at end of segment */
|
||||||
|
|
||||||
|
int sampling_method; /* volume sampling method */
|
||||||
} VolumeSegment;
|
} VolumeSegment;
|
||||||
|
|
||||||
/* record volume steps to the end of the volume.
|
/* record volume steps to the end of the volume.
|
||||||
@ -709,6 +741,8 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
|
|||||||
{
|
{
|
||||||
int closure_flag = segment->closure_flag;
|
int closure_flag = segment->closure_flag;
|
||||||
|
|
||||||
|
/* XXX add probalistic scattering! */
|
||||||
|
|
||||||
if(!(closure_flag & SD_SCATTER))
|
if(!(closure_flag & SD_SCATTER))
|
||||||
return VOLUME_PATH_MISSED;
|
return VOLUME_PATH_MISSED;
|
||||||
|
|
||||||
@ -737,8 +771,8 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
|
|||||||
bool distance_sample = true;
|
bool distance_sample = true;
|
||||||
bool use_mis = false;
|
bool use_mis = false;
|
||||||
|
|
||||||
if(kernel_data.integrator.volume_homogeneous_sampling && light_P) {
|
if(segment->sampling_method && light_P) {
|
||||||
if(kernel_data.integrator.volume_homogeneous_sampling == 2) {
|
if(segment->sampling_method == SD_VOLUME_MIS) {
|
||||||
/* multiple importance sample: randomly pick between
|
/* multiple importance sample: randomly pick between
|
||||||
* equiangular and distance sampling strategy */
|
* equiangular and distance sampling strategy */
|
||||||
if(xi < 0.5f) {
|
if(xi < 0.5f) {
|
||||||
@ -872,7 +906,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* decide if we need to use decoupled or not */
|
/* decide if we need to use decoupled or not */
|
||||||
ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneous, bool direct)
|
ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneous, bool direct, int sampling_method)
|
||||||
{
|
{
|
||||||
/* decoupled ray marching for heterogenous volumes not supported on the GPU,
|
/* decoupled ray marching for heterogenous volumes not supported on the GPU,
|
||||||
* which also means equiangular and multiple importance sampling is not
|
* which also means equiangular and multiple importance sampling is not
|
||||||
@ -882,9 +916,8 @@ ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneou
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* equiangular sampling only implemented for decoupled */
|
/* equiangular and multiple importance sampling only implemented for decoupled */
|
||||||
bool equiangular = kernel_data.integrator.volume_homogeneous_sampling != 0;
|
if(sampling_method != 0)
|
||||||
if(equiangular)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* for all light sampling use decoupled, reusing shader evaluations is
|
/* for all light sampling use decoupled, reusing shader evaluations is
|
||||||
|
@ -101,11 +101,6 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
|
|||||||
if(!transparent_shadows)
|
if(!transparent_shadows)
|
||||||
kintegrator->transparent_shadows = false;
|
kintegrator->transparent_shadows = false;
|
||||||
|
|
||||||
if(kintegrator->num_all_lights > 0)
|
|
||||||
kintegrator->volume_homogeneous_sampling = volume_homogeneous_sampling;
|
|
||||||
else
|
|
||||||
kintegrator->volume_homogeneous_sampling = 0;
|
|
||||||
|
|
||||||
kintegrator->volume_max_steps = volume_max_steps;
|
kintegrator->volume_max_steps = volume_max_steps;
|
||||||
kintegrator->volume_step_size = volume_step_size;
|
kintegrator->volume_step_size = volume_step_size;
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ Shader::Shader()
|
|||||||
use_mis = true;
|
use_mis = true;
|
||||||
use_transparent_shadow = true;
|
use_transparent_shadow = true;
|
||||||
heterogeneous_volume = true;
|
heterogeneous_volume = true;
|
||||||
|
volume_sampling_method = 0;
|
||||||
|
|
||||||
has_surface = false;
|
has_surface = false;
|
||||||
has_surface_transparent = false;
|
has_surface_transparent = false;
|
||||||
@ -257,6 +258,10 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
|
|||||||
flag |= SD_HAS_BSSRDF_BUMP;
|
flag |= SD_HAS_BSSRDF_BUMP;
|
||||||
if(shader->has_converter_blackbody)
|
if(shader->has_converter_blackbody)
|
||||||
has_converter_blackbody = true;
|
has_converter_blackbody = true;
|
||||||
|
if(shader->volume_sampling_method == 1)
|
||||||
|
flag |= SD_VOLUME_EQUIANGULAR;
|
||||||
|
if(shader->volume_sampling_method == 2)
|
||||||
|
flag |= SD_VOLUME_MIS;
|
||||||
|
|
||||||
/* regular shader */
|
/* regular shader */
|
||||||
shader_flag[i++] = flag;
|
shader_flag[i++] = flag;
|
||||||
|
@ -68,6 +68,7 @@ public:
|
|||||||
bool use_mis;
|
bool use_mis;
|
||||||
bool use_transparent_shadow;
|
bool use_transparent_shadow;
|
||||||
bool heterogeneous_volume;
|
bool heterogeneous_volume;
|
||||||
|
int volume_sampling_method;
|
||||||
|
|
||||||
/* synchronization */
|
/* synchronization */
|
||||||
bool need_update;
|
bool need_update;
|
||||||
|
Loading…
Reference in New Issue
Block a user