forked from bartvdbraak/blender
Cycles: ray visibility options now work for lamps and mesh lights, with and without
multiple importance sampling, so you can disable them for diffuse/glossy/transmission. The Light Path node here is still weak and does not give this info. To make that work we'd need to evaluate the shader multiple times which is slow and we can't detect well enough when it is actually needed.
This commit is contained in:
parent
b20a7e01d0
commit
58a290234b
@ -528,7 +528,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'} # todo: 'LAMP'
|
||||
return CyclesButtonsPanel.poll(context) and ob and ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'LAMP'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -159,6 +159,12 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI
|
||||
light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling");
|
||||
light->samples = get_int(clamp, "samples");
|
||||
|
||||
/* visibility */
|
||||
uint visibility = object_ray_visibility(b_ob);
|
||||
light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
|
||||
light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
|
||||
light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
|
||||
|
||||
/* tag */
|
||||
light->tag_update(scene);
|
||||
}
|
||||
|
@ -232,12 +232,9 @@ __device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughpu
|
||||
L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
|
||||
|
||||
if(is_lamp) {
|
||||
float3 sum = throughput*(bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission);
|
||||
|
||||
L->shadow.x += shadow.x*shadow_fac;
|
||||
L->shadow.y += shadow.y*shadow_fac;
|
||||
L->shadow.z += shadow.z*shadow_fac;
|
||||
L->shadow.w += average(sum);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -102,8 +102,6 @@ __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int li
|
||||
if(is_zero(light_eval))
|
||||
return false;
|
||||
|
||||
/* todo: use visibility flag to skip lights */
|
||||
|
||||
/* evaluate BSDF at shading point */
|
||||
float bsdf_pdf;
|
||||
|
||||
@ -117,6 +115,18 @@ __device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int li
|
||||
|
||||
bsdf_eval_mul(eval, light_eval/ls.pdf);
|
||||
|
||||
#ifdef __PASSES__
|
||||
/* use visibility flag to skip lights */
|
||||
if(ls.shader & SHADER_EXCLUDE_ANY) {
|
||||
if(ls.shader & SHADER_EXCLUDE_DIFFUSE)
|
||||
eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
|
||||
if(ls.shader & SHADER_EXCLUDE_GLOSSY)
|
||||
eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
|
||||
if(ls.shader & SHADER_EXCLUDE_TRANSMIT)
|
||||
eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(bsdf_eval_is_zero(eval))
|
||||
return false;
|
||||
|
||||
@ -185,7 +195,19 @@ __device_noinline bool indirect_lamp_emission(KernelGlobals *kg, Ray *ray, int p
|
||||
|
||||
if(!lamp_light_eval(kg, lamp, ray->P, ray->D, ray->t, &ls))
|
||||
return false;
|
||||
|
||||
|
||||
#ifdef __PASSES__
|
||||
/* use visibility flag to skip lights */
|
||||
if(ls.shader & SHADER_EXCLUDE_ANY) {
|
||||
if((ls.shader & SHADER_EXCLUDE_DIFFUSE) && (path_flag & PATH_RAY_DIFFUSE))
|
||||
return false;
|
||||
if((ls.shader & SHADER_EXCLUDE_GLOSSY) && (path_flag & PATH_RAY_GLOSSY))
|
||||
return false;
|
||||
if((ls.shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* todo: missing texture coordinates */
|
||||
float u = 0.0f;
|
||||
float v = 0.0f;
|
||||
|
@ -558,11 +558,11 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
|
||||
if(prim >= 0) {
|
||||
int object = __float_as_int(l.w);
|
||||
#ifdef __HAIR__
|
||||
int segment = __float_as_int(l.z);
|
||||
int segment = __float_as_int(l.z) & SHADER_MASK;
|
||||
#endif
|
||||
|
||||
#ifdef __HAIR__
|
||||
if (segment != (int)~0)
|
||||
if (segment != SHADER_MASK)
|
||||
curve_segment_light_sample(kg, prim, object, segment, randu, randv, time, ls);
|
||||
else
|
||||
#endif
|
||||
@ -571,6 +571,7 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
|
||||
/* compute incoming direction, distance and pdf */
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->shader |= __float_as_int(l.z) & (~SHADER_MASK);
|
||||
}
|
||||
else {
|
||||
int lamp = -prim-1;
|
||||
|
@ -326,8 +326,12 @@ typedef enum ShaderFlag {
|
||||
SHADER_CAST_SHADOW = (1 << 30),
|
||||
SHADER_AREA_LIGHT = (1 << 29),
|
||||
SHADER_USE_MIS = (1 << 28),
|
||||
SHADER_EXCLUDE_DIFFUSE = (1 << 27),
|
||||
SHADER_EXCLUDE_GLOSSY = (1 << 26),
|
||||
SHADER_EXCLUDE_TRANSMIT = (1 << 25),
|
||||
SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT),
|
||||
|
||||
SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS)
|
||||
SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY)
|
||||
} ShaderFlag;
|
||||
|
||||
/* Light Type */
|
||||
|
@ -259,6 +259,8 @@ Film::Film()
|
||||
mist_depth = 100.0f;
|
||||
mist_falloff = 1.0f;
|
||||
|
||||
use_light_visibility = false;
|
||||
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
@ -279,7 +281,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
kfilm->exposure = exposure;
|
||||
kfilm->pass_flag = 0;
|
||||
kfilm->pass_stride = 0;
|
||||
kfilm->use_light_pass = 0;
|
||||
kfilm->use_light_pass = use_light_visibility;
|
||||
|
||||
foreach(Pass& pass, passes) {
|
||||
kfilm->pass_flag |= pass.type;
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
float mist_depth;
|
||||
float mist_falloff;
|
||||
|
||||
bool use_light_visibility;
|
||||
|
||||
bool need_update;
|
||||
|
||||
Film();
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "device.h"
|
||||
#include "integrator.h"
|
||||
#include "film.h"
|
||||
#include "light.h"
|
||||
#include "mesh.h"
|
||||
#include "object.h"
|
||||
@ -116,6 +117,9 @@ Light::Light()
|
||||
|
||||
cast_shadow = true;
|
||||
use_mis = false;
|
||||
use_diffuse = true;
|
||||
use_glossy = true;
|
||||
use_transmission = true;
|
||||
|
||||
shader = 0;
|
||||
samples = 1;
|
||||
@ -221,17 +225,31 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
||||
bool transform_applied = mesh->transform_applied;
|
||||
Transform tfm = object->tfm;
|
||||
int object_id = j;
|
||||
int shader_id = SHADER_MASK;
|
||||
|
||||
if(transform_applied)
|
||||
object_id = ~object_id;
|
||||
|
||||
if(!(object->visibility & PATH_RAY_DIFFUSE)) {
|
||||
shader_id |= SHADER_EXCLUDE_DIFFUSE;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
if(!(object->visibility & PATH_RAY_GLOSSY)) {
|
||||
shader_id |= SHADER_EXCLUDE_GLOSSY;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
if(!(object->visibility & PATH_RAY_TRANSMIT)) {
|
||||
shader_id |= SHADER_EXCLUDE_TRANSMIT;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < mesh->triangles.size(); i++) {
|
||||
Shader *shader = scene->shaders[mesh->shader[i]];
|
||||
|
||||
if(shader->sample_as_light && shader->has_surface_emission) {
|
||||
distribution[offset].x = totarea;
|
||||
distribution[offset].y = __int_as_float(i + mesh->tri_offset);
|
||||
distribution[offset].z = __int_as_float(~0);
|
||||
distribution[offset].z = __int_as_float(shader_id);
|
||||
distribution[offset].w = __int_as_float(object_id);
|
||||
offset++;
|
||||
|
||||
@ -250,7 +268,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
||||
}
|
||||
}
|
||||
|
||||
/*sample as light disabled for strands*/
|
||||
/* sample as light disabled for strands */
|
||||
#if 0
|
||||
size_t i = 0;
|
||||
|
||||
@ -262,7 +280,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
|
||||
for(int j = 0; j < curve.num_segments(); j++) {
|
||||
distribution[offset].x = totarea;
|
||||
distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code
|
||||
distribution[offset].z = __int_as_float(j);
|
||||
distribution[offset].z = __int_as_float(j) & SHADER_MASK;
|
||||
distribution[offset].w = __int_as_float(object_id);
|
||||
offset++;
|
||||
|
||||
@ -493,6 +511,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
||||
}
|
||||
}
|
||||
}
|
||||
scene->film->use_light_visibility = false;
|
||||
|
||||
for(size_t i = 0; i < scene->lights.size(); i++) {
|
||||
Light *light = scene->lights[i];
|
||||
@ -504,6 +523,19 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
|
||||
if(!light->cast_shadow)
|
||||
shader_id &= ~SHADER_CAST_SHADOW;
|
||||
|
||||
if(!light->use_diffuse) {
|
||||
shader_id |= SHADER_EXCLUDE_DIFFUSE;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
if(!light->use_glossy) {
|
||||
shader_id |= SHADER_EXCLUDE_GLOSSY;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
if(!light->use_transmission) {
|
||||
shader_id |= SHADER_EXCLUDE_TRANSMIT;
|
||||
scene->film->use_light_visibility = true;
|
||||
}
|
||||
|
||||
if(light->type == LIGHT_POINT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
||||
|
@ -53,6 +53,9 @@ public:
|
||||
|
||||
bool cast_shadow;
|
||||
bool use_mis;
|
||||
bool use_diffuse;
|
||||
bool use_glossy;
|
||||
bool use_transmission;
|
||||
|
||||
int shader;
|
||||
int samples;
|
||||
|
Loading…
Reference in New Issue
Block a user