diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-03-28 14:39:21 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-03-28 14:39:21 +0400 |
commit | 755f0183240527e9b274ce4f80f1cf1d7e414164 (patch) | |
tree | db8472ce0ba4b4372ad1d3b907edf58c0b674164 /intern | |
parent | 1e5424564c0c01d0772641f3896ffaa1a2616e2b (diff) |
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.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 1 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_accumulate.h | 24 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_emission.h | 5 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_passes.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 6 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/buffers.cpp | 27 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 7 |
9 files changed, 61 insertions, 21 deletions
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 3b78be6c6c9..c084dc7288a 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -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() diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 7f666706470..a5471655b5f 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -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: diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 7860913ce94..1e6605541ca 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -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 } diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 2243858a403..764ac599991 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -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; } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 44e06be8c16..51067630f09 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -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 } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 23860b41de3..f9eeccb1f11 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -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__ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index c198ee1d24e..453d5c826e6 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -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 { diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index c8d5dd2da8d..da0453e5822 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -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*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]); - pixels[0] = f.x*scale_exposure; - pixels[1] = f.y*scale_exposure; - pixels[2] = f.z*scale_exposure; + 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); + /* clamp since alpha might be > 1.0 due to russian roulette */ + pixels[3] = clamp(f.w*scale, 0.0f, 1.0f); + } } } diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 3fb1e385adc..5fd98e20240 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -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; } |