Cycles: shadow pass support. Note that this only takes into account lamps,
emitting objects or world lighting do not contribute to the shadow pass. Consider this more as a pass useful for some compositing tricks, unlike other lighting passes this pass can't be used to exactly reconstruct the combined pass.
This commit is contained in:
parent
1e5424564c
commit
755f018324
@ -197,6 +197,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
|
||||
col.prop(rl, "use_pass_emit")
|
||||
col.prop(rl, "use_pass_environment")
|
||||
col.prop(rl, "use_pass_ambient_occlusion")
|
||||
col.prop(rl, "use_pass_shadow")
|
||||
|
||||
col = split.column()
|
||||
col.label()
|
||||
|
@ -160,9 +160,10 @@ static PassType get_pass_type(BL::RenderPass b_pass)
|
||||
return PASS_BACKGROUND;
|
||||
case BL::RenderPass::type_AO:
|
||||
return PASS_AO;
|
||||
case BL::RenderPass::type_SHADOW:
|
||||
return PASS_SHADOW;
|
||||
|
||||
case BL::RenderPass::type_DIFFUSE:
|
||||
case BL::RenderPass::type_SHADOW:
|
||||
case BL::RenderPass::type_COLOR:
|
||||
case BL::RenderPass::type_REFRACTION:
|
||||
case BL::RenderPass::type_SPECULAR:
|
||||
|
@ -136,6 +136,7 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
|
||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->background = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->ao = make_float3(0.0f, 0.0f, 0.0f);
|
||||
L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else
|
||||
L->emission = make_float3(0.0f, 0.0f, 0.0f);
|
||||
@ -215,26 +216,35 @@ __device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput,
|
||||
#endif
|
||||
}
|
||||
|
||||
__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, int bounce)
|
||||
__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, int bounce, bool is_lamp)
|
||||
{
|
||||
#ifdef __PASSES__
|
||||
if(L->use_light_pass) {
|
||||
if(bounce == 0) {
|
||||
/* directly visible lighting */
|
||||
L->direct_diffuse += throughput*bsdf_eval->diffuse;
|
||||
L->direct_glossy += throughput*bsdf_eval->glossy;
|
||||
L->direct_transmission += throughput*bsdf_eval->transmission;
|
||||
L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow;
|
||||
L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
|
||||
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;
|
||||
L->shadow.y += shadow.y;
|
||||
L->shadow.z += shadow.z;
|
||||
L->shadow.w += average(sum);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* indirectly visible lighting after BSDF bounce */
|
||||
float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission;
|
||||
L->indirect += throughput*sum;
|
||||
L->indirect += throughput*sum*shadow;
|
||||
}
|
||||
}
|
||||
else
|
||||
L->emission += throughput*bsdf_eval->diffuse;
|
||||
L->emission += throughput*bsdf_eval->diffuse*shadow;
|
||||
#else
|
||||
*L += throughput*(*bsdf_eval);
|
||||
*L += throughput*(*bsdf_eval)*shadow;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,8 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
|
||||
}
|
||||
|
||||
__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
|
||||
float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval)
|
||||
float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval,
|
||||
bool *is_lamp)
|
||||
{
|
||||
LightSample ls;
|
||||
|
||||
@ -135,6 +136,8 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
|
||||
ray->t = 0.0f;
|
||||
}
|
||||
|
||||
*is_lamp = (ls.prim == ~0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,8 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, sample, L->color_glossy);
|
||||
if(flag & PASS_TRANSMISSION_COLOR)
|
||||
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, sample, L->color_transmission);
|
||||
if(flag & PASS_SHADOW)
|
||||
kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, sample, L->shadow);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -327,6 +327,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
|
||||
Ray light_ray;
|
||||
BsdfEval L_light;
|
||||
bool is_lamp;
|
||||
|
||||
#ifdef __MULTI_LIGHT__
|
||||
/* index -1 means randomly sample from distribution */
|
||||
@ -336,14 +337,13 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
#else
|
||||
const int i = -1;
|
||||
#endif
|
||||
if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &L_light)) {
|
||||
if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
bsdf_eval_mul(&L_light, shadow);
|
||||
path_radiance_accum_light(&L, throughput, &L_light, state.bounce);
|
||||
path_radiance_accum_light(&L, throughput, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
#ifdef __MULTI_LIGHT__
|
||||
|
@ -175,7 +175,8 @@ typedef enum PassType {
|
||||
PASS_TRANSMISSION_DIRECT = 32768,
|
||||
PASS_EMISSION = 65536,
|
||||
PASS_BACKGROUND = 131072,
|
||||
PASS_AO = 262144
|
||||
PASS_AO = 262144,
|
||||
PASS_SHADOW = 524288
|
||||
} PassType;
|
||||
|
||||
#define PASS_ALL (~0)
|
||||
@ -206,6 +207,8 @@ typedef struct PathRadiance {
|
||||
float3 indirect_diffuse;
|
||||
float3 indirect_glossy;
|
||||
float3 indirect_transmission;
|
||||
|
||||
float4 shadow;
|
||||
} PathRadiance;
|
||||
|
||||
typedef struct BsdfEval {
|
||||
@ -464,7 +467,7 @@ typedef struct KernelFilm {
|
||||
int pass_emission;
|
||||
int pass_background;
|
||||
int pass_ao;
|
||||
int pass_pad2;
|
||||
int pass_shadow;
|
||||
} KernelFilm;
|
||||
|
||||
typedef struct KernelBackground {
|
||||
|
@ -186,15 +186,28 @@ bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int comp
|
||||
assert(pass.components == components);
|
||||
|
||||
/* RGBA */
|
||||
for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
|
||||
float4 f = make_float4(in[0], in[1], in[2], in[3]);
|
||||
if(type == PASS_SHADOW) {
|
||||
for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
|
||||
float4 f = make_float4(in[0], in[1], in[2], in[3]);
|
||||
float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
|
||||
|
||||
pixels[0] = f.x*scale_exposure;
|
||||
pixels[1] = f.y*scale_exposure;
|
||||
pixels[2] = f.z*scale_exposure;
|
||||
pixels[0] = f.x*invw;
|
||||
pixels[1] = f.y*invw;
|
||||
pixels[2] = f.z*invw;
|
||||
pixels[3] = 1.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
|
||||
float4 f = make_float4(in[0], in[1], in[2], in[3]);
|
||||
|
||||
/* clamp since alpha might be > 1.0 due to russian roulette */
|
||||
pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
|
||||
pixels[0] = f.x*scale_exposure;
|
||||
pixels[1] = f.y*scale_exposure;
|
||||
pixels[2] = f.z*scale_exposure;
|
||||
|
||||
/* clamp since alpha might be > 1.0 due to russian roulette */
|
||||
pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,10 @@ void Pass::add(PassType type, vector<Pass>& passes)
|
||||
pass.components = 4;
|
||||
pass.exposure = true;
|
||||
break;
|
||||
case PASS_SHADOW:
|
||||
pass.components = 4;
|
||||
pass.exposure = false;
|
||||
break;
|
||||
}
|
||||
|
||||
passes.push_back(pass);
|
||||
@ -232,6 +236,9 @@ void Film::device_update(Device *device, DeviceScene *dscene)
|
||||
case PASS_AO:
|
||||
kfilm->pass_ao = kfilm->pass_stride;
|
||||
kfilm->use_light_pass = 1;
|
||||
case PASS_SHADOW:
|
||||
kfilm->pass_shadow = kfilm->pass_stride;
|
||||
kfilm->use_light_pass = 1;
|
||||
case PASS_NONE:
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user