Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/kernel_shader.h
| Show First 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | if (from_sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) { | ||||
| if (phases->num_closure >= MAX_VOLUME_CLOSURE) { | if (phases->num_closure >= MAX_VOLUME_CLOSURE) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __VOLUME__ */ | #endif /* __VOLUME__ */ | ||||
| ccl_device_inline void shader_prepare_surface_closures(INTEGRATOR_STATE_CONST_ARGS, | ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg, | ||||
| ConstIntegratorState state, | |||||
| ccl_private ShaderData *sd) | ccl_private ShaderData *sd) | ||||
| { | { | ||||
| /* Defensive sampling. | /* Defensive sampling. | ||||
| * | * | ||||
| * We can likely also do defensive sampling at deeper bounces, particularly | * We can likely also do defensive sampling at deeper bounces, particularly | ||||
| * for cases like a perfect mirror but possibly also others. This will need | * for cases like a perfect mirror but possibly also others. This will need | ||||
| * a good heuristic. */ | * a good heuristic. */ | ||||
| if (INTEGRATOR_STATE(path, bounce) + INTEGRATOR_STATE(path, transparent_bounce) == 0 && | if (INTEGRATOR_STATE(state, path, bounce) + INTEGRATOR_STATE(state, path, transparent_bounce) == | ||||
| 0 && | |||||
| sd->num_closure > 1) { | sd->num_closure > 1) { | ||||
| float sum = 0.0f; | float sum = 0.0f; | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private ShaderClosure *sc = &sd->closure[i]; | ccl_private ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { | if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { | ||||
| sum += sc->sample_weight; | sum += sc->sample_weight; | ||||
| } | } | ||||
| } | } | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private ShaderClosure *sc = &sd->closure[i]; | ccl_private ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { | if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { | ||||
| sc->sample_weight = max(sc->sample_weight, 0.125f * sum); | sc->sample_weight = max(sc->sample_weight, 0.125f * sum); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Filter glossy. | /* Filter glossy. | ||||
| * | * | ||||
| * Blurring of bsdf after bounces, for rays that have a small likelihood | * Blurring of bsdf after bounces, for rays that have a small likelihood | ||||
| * of following this particular path (diffuse, rough glossy) */ | * of following this particular path (diffuse, rough glossy) */ | ||||
| if (kernel_data.integrator.filter_glossy != FLT_MAX) { | if (kernel_data.integrator.filter_glossy != FLT_MAX) { | ||||
| float blur_pdf = kernel_data.integrator.filter_glossy * INTEGRATOR_STATE(path, min_ray_pdf); | float blur_pdf = kernel_data.integrator.filter_glossy * | ||||
| INTEGRATOR_STATE(state, path, min_ray_pdf); | |||||
| if (blur_pdf < 1.0f) { | if (blur_pdf < 1.0f) { | ||||
| float blur_roughness = sqrtf(1.0f - blur_pdf) * 0.5f; | float blur_roughness = sqrtf(1.0f - blur_pdf) * 0.5f; | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private ShaderClosure *sc = &sd->closure[i]; | ccl_private ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF(sc->type)) { | if (CLOSURE_IS_BSDF(sc->type)) { | ||||
| bsdf_blur(kg, sc, blur_roughness); | bsdf_blur(kg, sc, blur_roughness); | ||||
| Show All 29 Lines | ccl_device_forceinline bool _shader_bsdf_exclude(ClosureType type, uint light_shader_flags) | ||||
| if (light_shader_flags & SHADER_EXCLUDE_TRANSMIT) { | if (light_shader_flags & SHADER_EXCLUDE_TRANSMIT) { | ||||
| if (CLOSURE_IS_BSDF_TRANSMISSION(type)) { | if (CLOSURE_IS_BSDF_TRANSMISSION(type)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| ccl_device_inline float _shader_bsdf_multi_eval(ccl_global const KernelGlobals *kg, | ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg, | ||||
| ccl_private ShaderData *sd, | ccl_private ShaderData *sd, | ||||
| const float3 omega_in, | const float3 omega_in, | ||||
| const bool is_transmission, | const bool is_transmission, | ||||
| ccl_private const ShaderClosure *skip_sc, | ccl_private const ShaderClosure *skip_sc, | ||||
| ccl_private BsdfEval *result_eval, | ccl_private BsdfEval *result_eval, | ||||
| float sum_pdf, | float sum_pdf, | ||||
| float sum_sample_weight, | float sum_sample_weight, | ||||
| const uint light_shader_flags) | const uint light_shader_flags) | ||||
| Show All 27 Lines | |||||
| } | } | ||||
| #ifndef __KERNEL_CUDA__ | #ifndef __KERNEL_CUDA__ | ||||
| ccl_device | ccl_device | ||||
| #else | #else | ||||
| ccl_device_inline | ccl_device_inline | ||||
| #endif | #endif | ||||
| float | float | ||||
| shader_bsdf_eval(ccl_global const KernelGlobals *kg, | shader_bsdf_eval(KernelGlobals kg, | ||||
| ccl_private ShaderData *sd, | ccl_private ShaderData *sd, | ||||
| const float3 omega_in, | const float3 omega_in, | ||||
| const bool is_transmission, | const bool is_transmission, | ||||
| ccl_private BsdfEval *bsdf_eval, | ccl_private BsdfEval *bsdf_eval, | ||||
| const uint light_shader_flags) | const uint light_shader_flags) | ||||
| { | { | ||||
| bsdf_eval_init(bsdf_eval, false, zero_float3()); | bsdf_eval_init(bsdf_eval, false, zero_float3()); | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | if (sd->num_closure > 1) { | ||||
| weight *= sum / bssrdf_sc->sample_weight; | weight *= sum / bssrdf_sc->sample_weight; | ||||
| } | } | ||||
| return weight; | return weight; | ||||
| } | } | ||||
| /* Sample direction for picked BSDF, and return evaluation and pdf for all | /* Sample direction for picked BSDF, and return evaluation and pdf for all | ||||
| * BSDFs combined using MIS. */ | * BSDFs combined using MIS. */ | ||||
| ccl_device int shader_bsdf_sample_closure(ccl_global const KernelGlobals *kg, | ccl_device int shader_bsdf_sample_closure(KernelGlobals kg, | ||||
| ccl_private ShaderData *sd, | ccl_private ShaderData *sd, | ||||
| ccl_private const ShaderClosure *sc, | ccl_private const ShaderClosure *sc, | ||||
| float randu, | float randu, | ||||
| float randv, | float randv, | ||||
| ccl_private BsdfEval *bsdf_eval, | ccl_private BsdfEval *bsdf_eval, | ||||
| ccl_private float3 *omega_in, | ccl_private float3 *omega_in, | ||||
| ccl_private differential3 *domega_in, | ccl_private differential3 *domega_in, | ||||
| ccl_private float *pdf) | ccl_private float *pdf) | ||||
| Show All 37 Lines | if (CLOSURE_IS_BSDF(sc->type)) { | ||||
| roughness += weight * sqrtf(safe_sqrtf(bsdf_get_roughness_squared(sc))); | roughness += weight * sqrtf(safe_sqrtf(bsdf_get_roughness_squared(sc))); | ||||
| sum_weight += weight; | sum_weight += weight; | ||||
| } | } | ||||
| } | } | ||||
| return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; | return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_transparency(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| if (sd->flag & SD_HAS_ONLY_VOLUME) { | if (sd->flag & SD_HAS_ONLY_VOLUME) { | ||||
| return one_float3(); | return one_float3(); | ||||
| } | } | ||||
| else if (sd->flag & SD_TRANSPARENT) { | else if (sd->flag & SD_TRANSPARENT) { | ||||
| return sd->closure_transparent_extinction; | return sd->closure_transparent_extinction; | ||||
| } | } | ||||
| else { | else { | ||||
| return zero_float3(); | return zero_float3(); | ||||
| } | } | ||||
| } | } | ||||
| ccl_device void shader_bsdf_disable_transparency(ccl_global const KernelGlobals *kg, | ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private ShaderData *sd) | ||||
| ccl_private ShaderData *sd) | |||||
| { | { | ||||
| if (sd->flag & SD_TRANSPARENT) { | if (sd->flag & SD_TRANSPARENT) { | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private ShaderClosure *sc = &sd->closure[i]; | ccl_private ShaderClosure *sc = &sd->closure[i]; | ||||
| if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) { | if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) { | ||||
| sc->sample_weight = 0.0f; | sc->sample_weight = 0.0f; | ||||
| sc->weight = zero_float3(); | sc->weight = zero_float3(); | ||||
| } | } | ||||
| } | } | ||||
| sd->flag &= ~SD_TRANSPARENT; | sd->flag &= ~SD_TRANSPARENT; | ||||
| } | } | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_alpha(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd); | float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd); | ||||
| alpha = max(alpha, zero_float3()); | alpha = max(alpha, zero_float3()); | ||||
| alpha = min(alpha, one_float3()); | alpha = min(alpha, one_float3()); | ||||
| return alpha; | return alpha; | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_diffuse(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 eval = zero_float3(); | float3 eval = zero_float3(); | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type)) | if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type)) | ||||
| eval += sc->weight; | eval += sc->weight; | ||||
| } | } | ||||
| return eval; | return eval; | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_glossy(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 eval = zero_float3(); | float3 eval = zero_float3(); | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) | if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) | ||||
| eval += sc->weight; | eval += sc->weight; | ||||
| } | } | ||||
| return eval; | return eval; | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_transmission(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 eval = zero_float3(); | float3 eval = zero_float3(); | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) | if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) | ||||
| eval += sc->weight; | eval += sc->weight; | ||||
| } | } | ||||
| return eval; | return eval; | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_average_normal(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 N = zero_float3(); | float3 N = zero_float3(); | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) | if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) | ||||
| N += sc->N * fabsf(average(sc->weight)); | N += sc->N * fabsf(average(sc->weight)); | ||||
| } | } | ||||
| return (is_zero(N)) ? sd->N : normalize(N); | return (is_zero(N)) ? sd->N : normalize(N); | ||||
| } | } | ||||
| ccl_device float3 shader_bsdf_ao_normal(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_bsdf_ao_normal(KernelGlobals kg, ccl_private const ShaderData *sd) | ||||
| ccl_private const ShaderData *sd) | |||||
| { | { | ||||
| float3 N = zero_float3(); | float3 N = zero_float3(); | ||||
| for (int i = 0; i < sd->num_closure; i++) { | for (int i = 0; i < sd->num_closure; i++) { | ||||
| ccl_private const ShaderClosure *sc = &sd->closure[i]; | ccl_private const ShaderClosure *sc = &sd->closure[i]; | ||||
| if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { | if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { | ||||
| ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; | ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; | ||||
| N += bsdf->N * fabsf(average(sc->weight)); | N += bsdf->N * fabsf(average(sc->weight)); | ||||
| Show All 20 Lines | ccl_device float3 shader_bssrdf_normal(ccl_private const ShaderData *sd) | ||||
| } | } | ||||
| return (is_zero(N)) ? sd->N : normalize(N); | return (is_zero(N)) ? sd->N : normalize(N); | ||||
| } | } | ||||
| #endif /* __SUBSURFACE__ */ | #endif /* __SUBSURFACE__ */ | ||||
| /* Constant emission optimization */ | /* Constant emission optimization */ | ||||
| ccl_device bool shader_constant_emission_eval(ccl_global const KernelGlobals *kg, | ccl_device bool shader_constant_emission_eval(KernelGlobals kg, | ||||
| int shader, | int shader, | ||||
| ccl_private float3 *eval) | ccl_private float3 *eval) | ||||
| { | { | ||||
| int shader_index = shader & SHADER_MASK; | int shader_index = shader & SHADER_MASK; | ||||
| int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags; | int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags; | ||||
| if (shader_flag & SD_HAS_CONSTANT_EMISSION) { | if (shader_flag & SD_HAS_CONSTANT_EMISSION) { | ||||
| *eval = make_float3(kernel_tex_fetch(__shaders, shader_index).constant_emission[0], | *eval = make_float3(kernel_tex_fetch(__shaders, shader_index).constant_emission[0], | ||||
| Show All 27 Lines | ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd) | ||||
| } | } | ||||
| else { | else { | ||||
| return zero_float3(); | return zero_float3(); | ||||
| } | } | ||||
| } | } | ||||
| /* Holdout */ | /* Holdout */ | ||||
| ccl_device float3 shader_holdout_apply(ccl_global const KernelGlobals *kg, | ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) | ||||
| ccl_private ShaderData *sd) | |||||
| { | { | ||||
| float3 weight = zero_float3(); | float3 weight = zero_float3(); | ||||
| /* For objects marked as holdout, preserve transparency and remove all other | /* For objects marked as holdout, preserve transparency and remove all other | ||||
| * closures, replacing them with a holdout weight. */ | * closures, replacing them with a holdout weight. */ | ||||
| if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { | if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { | ||||
| if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) { | if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) { | ||||
| weight = one_float3() - sd->closure_transparent_extinction; | weight = one_float3() - sd->closure_transparent_extinction; | ||||
| Show All 21 Lines | ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) | ||||
| } | } | ||||
| return weight; | return weight; | ||||
| } | } | ||||
| /* Surface Evaluation */ | /* Surface Evaluation */ | ||||
| template<uint node_feature_mask> | template<uint node_feature_mask> | ||||
| ccl_device void shader_eval_surface(INTEGRATOR_STATE_CONST_ARGS, | ccl_device void shader_eval_surface(KernelGlobals kg, | ||||
| ConstIntegratorState state, | |||||
| ccl_private ShaderData *ccl_restrict sd, | ccl_private ShaderData *ccl_restrict sd, | ||||
| ccl_global float *ccl_restrict buffer, | ccl_global float *ccl_restrict buffer, | ||||
| int path_flag) | int path_flag) | ||||
| { | { | ||||
| /* If path is being terminated, we are tracing a shadow ray or evaluating | /* If path is being terminated, we are tracing a shadow ray or evaluating | ||||
| * emission, then we don't need to store closures. The emission and shadow | * emission, then we don't need to store closures. The emission and shadow | ||||
| * shader data also do not have a closure array to save GPU memory. */ | * shader data also do not have a closure array to save GPU memory. */ | ||||
| int max_closures; | int max_closures; | ||||
| if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) { | if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) { | ||||
| max_closures = 0; | max_closures = 0; | ||||
| } | } | ||||
| else { | else { | ||||
| max_closures = kernel_data.max_closures; | max_closures = kernel_data.max_closures; | ||||
| } | } | ||||
| sd->num_closure = 0; | sd->num_closure = 0; | ||||
| sd->num_closure_left = max_closures; | sd->num_closure_left = max_closures; | ||||
| #ifdef __OSL__ | #ifdef __OSL__ | ||||
| if (kg->osl) { | if (kg->osl) { | ||||
| if (sd->object == OBJECT_NONE && sd->lamp == LAMP_NONE) { | if (sd->object == OBJECT_NONE && sd->lamp == LAMP_NONE) { | ||||
| OSLShader::eval_background(INTEGRATOR_STATE_PASS, sd, path_flag); | OSLShader::eval_background(kg, state, sd, path_flag); | ||||
| } | } | ||||
| else { | else { | ||||
| OSLShader::eval_surface(INTEGRATOR_STATE_PASS, sd, path_flag); | OSLShader::eval_surface(kg, state, sd, path_flag); | ||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| #endif | #endif | ||||
| { | { | ||||
| #ifdef __SVM__ | #ifdef __SVM__ | ||||
| svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>( | svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>(kg, state, sd, buffer, path_flag); | ||||
| INTEGRATOR_STATE_PASS, sd, buffer, path_flag); | |||||
| #else | #else | ||||
| if (sd->object == OBJECT_NONE) { | if (sd->object == OBJECT_NONE) { | ||||
| sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f); | sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f); | ||||
| sd->flag |= SD_EMISSION; | sd->flag |= SD_EMISSION; | ||||
| } | } | ||||
| else { | else { | ||||
| ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( | ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( | ||||
| sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f)); | sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f)); | ||||
| if (bsdf != NULL) { | if (bsdf != NULL) { | ||||
| bsdf->N = sd->N; | bsdf->N = sd->N; | ||||
| sd->flag |= bsdf_diffuse_setup(bsdf); | sd->flag |= bsdf_diffuse_setup(bsdf); | ||||
| } | } | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| if (KERNEL_NODES_FEATURE(BSDF) && (sd->flag & SD_BSDF_NEEDS_LCG)) { | IF_KERNEL_NODES_FEATURE(BSDF) | ||||
| sd->lcg_state = lcg_state_init(INTEGRATOR_STATE(path, rng_hash), | { | ||||
| INTEGRATOR_STATE(path, rng_offset), | if (sd->flag & SD_BSDF_NEEDS_LCG) { | ||||
| INTEGRATOR_STATE(path, sample), | sd->lcg_state = lcg_state_init(INTEGRATOR_STATE(state, path, rng_hash), | ||||
| INTEGRATOR_STATE(state, path, rng_offset), | |||||
| INTEGRATOR_STATE(state, path, sample), | |||||
| 0xb4bc3953); | 0xb4bc3953); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /* Volume */ | /* Volume */ | ||||
| #ifdef __VOLUME__ | #ifdef __VOLUME__ | ||||
| ccl_device_inline float _shader_volume_phase_multi_eval( | ccl_device_inline float _shader_volume_phase_multi_eval( | ||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_private const ShaderVolumePhases *phases, | ccl_private const ShaderVolumePhases *phases, | ||||
| Show All 17 Lines | for (int i = 0; i < phases->num_closure; i++) { | ||||
| } | } | ||||
| sum_sample_weight += svc->sample_weight; | sum_sample_weight += svc->sample_weight; | ||||
| } | } | ||||
| return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; | return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f; | ||||
| } | } | ||||
| ccl_device float shader_volume_phase_eval(ccl_global const KernelGlobals *kg, | ccl_device float shader_volume_phase_eval(KernelGlobals kg, | ||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_private const ShaderVolumePhases *phases, | ccl_private const ShaderVolumePhases *phases, | ||||
| const float3 omega_in, | const float3 omega_in, | ||||
| ccl_private BsdfEval *phase_eval) | ccl_private BsdfEval *phase_eval) | ||||
| { | { | ||||
| bsdf_eval_init(phase_eval, false, zero_float3()); | bsdf_eval_init(phase_eval, false, zero_float3()); | ||||
| return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f); | return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f); | ||||
| } | } | ||||
| ccl_device int shader_volume_phase_sample(ccl_global const KernelGlobals *kg, | ccl_device int shader_volume_phase_sample(KernelGlobals kg, | ||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_private const ShaderVolumePhases *phases, | ccl_private const ShaderVolumePhases *phases, | ||||
| float randu, | float randu, | ||||
| float randv, | float randv, | ||||
| ccl_private BsdfEval *phase_eval, | ccl_private BsdfEval *phase_eval, | ||||
| ccl_private float3 *omega_in, | ccl_private float3 *omega_in, | ||||
| ccl_private differential3 *domega_in, | ccl_private differential3 *domega_in, | ||||
| ccl_private float *pdf) | ccl_private float *pdf) | ||||
| ▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | ccl_device int shader_volume_phase_sample(KernelGlobals kg, | ||||
| if (*pdf != 0.0f) { | if (*pdf != 0.0f) { | ||||
| bsdf_eval_init(phase_eval, false, eval); | bsdf_eval_init(phase_eval, false, eval); | ||||
| } | } | ||||
| return label; | return label; | ||||
| } | } | ||||
| ccl_device int shader_phase_sample_closure(ccl_global const KernelGlobals *kg, | ccl_device int shader_phase_sample_closure(KernelGlobals kg, | ||||
| ccl_private const ShaderData *sd, | ccl_private const ShaderData *sd, | ||||
| ccl_private const ShaderVolumeClosure *sc, | ccl_private const ShaderVolumeClosure *sc, | ||||
| float randu, | float randu, | ||||
| float randv, | float randv, | ||||
| ccl_private BsdfEval *phase_eval, | ccl_private BsdfEval *phase_eval, | ||||
| ccl_private float3 *omega_in, | ccl_private float3 *omega_in, | ||||
| ccl_private differential3 *domega_in, | ccl_private differential3 *domega_in, | ||||
| ccl_private float *pdf) | ccl_private float *pdf) | ||||
| { | { | ||||
| int label; | int label; | ||||
| float3 eval = zero_float3(); | float3 eval = zero_float3(); | ||||
| *pdf = 0.0f; | *pdf = 0.0f; | ||||
| label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); | label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); | ||||
| if (*pdf != 0.0f) | if (*pdf != 0.0f) | ||||
| bsdf_eval_init(phase_eval, false, eval); | bsdf_eval_init(phase_eval, false, eval); | ||||
| return label; | return label; | ||||
| } | } | ||||
| /* Volume Evaluation */ | /* Volume Evaluation */ | ||||
| template<const bool shadow, typename StackReadOp> | template<const bool shadow, typename StackReadOp> | ||||
| ccl_device_inline void shader_eval_volume(INTEGRATOR_STATE_CONST_ARGS, | ccl_device_inline void shader_eval_volume(KernelGlobals kg, | ||||
| ConstIntegratorState state, | |||||
| ccl_private ShaderData *ccl_restrict sd, | ccl_private ShaderData *ccl_restrict sd, | ||||
| const int path_flag, | const int path_flag, | ||||
| StackReadOp stack_read) | StackReadOp stack_read) | ||||
| { | { | ||||
| /* If path is being terminated, we are tracing a shadow ray or evaluating | /* If path is being terminated, we are tracing a shadow ray or evaluating | ||||
| * emission, then we don't need to store closures. The emission and shadow | * emission, then we don't need to store closures. The emission and shadow | ||||
| * shader data also do not have a closure array to save GPU memory. */ | * shader data also do not have a closure array to save GPU memory. */ | ||||
| int max_closures; | int max_closures; | ||||
| Show All 36 Lines | # ifdef __OBJECT_MOTION__ | ||||
| shader_setup_object_transforms(kg, sd, sd->time); | shader_setup_object_transforms(kg, sd, sd->time); | ||||
| # endif | # endif | ||||
| } | } | ||||
| /* evaluate shader */ | /* evaluate shader */ | ||||
| # ifdef __SVM__ | # ifdef __SVM__ | ||||
| # ifdef __OSL__ | # ifdef __OSL__ | ||||
| if (kg->osl) { | if (kg->osl) { | ||||
| OSLShader::eval_volume(INTEGRATOR_STATE_PASS, sd, path_flag); | OSLShader::eval_volume(kg, state, sd, path_flag); | ||||
| } | } | ||||
| else | else | ||||
| # endif | # endif | ||||
| { | { | ||||
| svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_VOLUME, SHADER_TYPE_VOLUME>( | svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_VOLUME, SHADER_TYPE_VOLUME>( | ||||
| INTEGRATOR_STATE_PASS, sd, NULL, path_flag); | kg, state, sd, NULL, path_flag); | ||||
| } | } | ||||
| # endif | # endif | ||||
| /* Merge closures to avoid exceeding number of closures limit. */ | /* Merge closures to avoid exceeding number of closures limit. */ | ||||
| if (!shadow) { | if (!shadow) { | ||||
| if (i > 0) { | if (i > 0) { | ||||
| shader_merge_volume_closures(sd); | shader_merge_volume_closures(sd); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif /* __VOLUME__ */ | #endif /* __VOLUME__ */ | ||||
| /* Displacement Evaluation */ | /* Displacement Evaluation */ | ||||
| ccl_device void shader_eval_displacement(INTEGRATOR_STATE_CONST_ARGS, ccl_private ShaderData *sd) | ccl_device void shader_eval_displacement(KernelGlobals kg, | ||||
| ConstIntegratorState state, | |||||
| ccl_private ShaderData *sd) | |||||
| { | { | ||||
| sd->num_closure = 0; | sd->num_closure = 0; | ||||
| sd->num_closure_left = 0; | sd->num_closure_left = 0; | ||||
| /* this will modify sd->P */ | /* this will modify sd->P */ | ||||
| #ifdef __SVM__ | #ifdef __SVM__ | ||||
| # ifdef __OSL__ | # ifdef __OSL__ | ||||
| if (kg->osl) | if (kg->osl) | ||||
| OSLShader::eval_displacement(INTEGRATOR_STATE_PASS, sd); | OSLShader::eval_displacement(kg, state, sd); | ||||
| else | else | ||||
| # endif | # endif | ||||
| { | { | ||||
| svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_DISPLACEMENT, SHADER_TYPE_DISPLACEMENT>( | svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_DISPLACEMENT, SHADER_TYPE_DISPLACEMENT>( | ||||
| INTEGRATOR_STATE_PASS, sd, NULL, 0); | kg, state, sd, NULL, 0); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| /* Cryptomatte */ | /* Cryptomatte */ | ||||
| ccl_device float shader_cryptomatte_id(ccl_global const KernelGlobals *kg, int shader) | ccl_device float shader_cryptomatte_id(KernelGlobals kg, int shader) | ||||
| { | { | ||||
| return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id; | return kernel_tex_fetch(__shaders, (shader & SHADER_MASK)).cryptomatte_id; | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||