diff options
Diffstat (limited to 'intern/cycles/kernel')
33 files changed, 662 insertions, 345 deletions
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index c521e1383a4..0ff227938ae 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -91,6 +91,7 @@ set(SRC_SVM_HEADERS svm/svm_magic.h svm/svm_mapping.h svm/svm_math.h + svm/svm_math_util.h svm/svm_mix.h svm/svm_musgrave.h svm/svm_noise.h diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index ad7864cb8ea..b94bdeeb23f 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 Blender Foundation + * Copyright 2011-2014 Blender Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,24 +33,20 @@ CCL_NAMESPACE_BEGIN ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc) { - /* store roughness. could already convert to exponent to save some cycles - * in eval, but this is more consistent with other bsdfs and shader_blur. */ sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); sc->data1 = sc->data0; sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID; - return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc) { - /* store roughness. could already convert to exponent to save some cycles - * in eval, but this is more consistent with other bsdfs and shader_blur. */ sc->data0 = clamp(sc->data0, 1e-4f, 1.0f); sc->data1 = clamp(sc->data1, 1e-4f, 1.0f); sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID; - return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_ashikhmin_shirley_blur(ShaderClosure *sc, float roughness) @@ -73,7 +69,7 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c float out = 0.0f; - if (NdotI > 0.0f && NdotO > 0.0f) { + if(NdotI > 0.0f && NdotO > 0.0f) { NdotI = fmaxf(NdotI, 1e-6f); NdotO = fmaxf(NdotO, 1e-6f); float3 H = normalize(omega_in + I); @@ -86,7 +82,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0); float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1); - if (n_x == n_y) { /* => isotropic case */ + if(n_x == n_y) { + /* isotropic */ float e = n_x; float lobe = powf(HdotN, e); float norm = (n_x + 1.0f) / (8.0f * M_PI_F); @@ -94,7 +91,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c out = NdotO * norm * lobe * pump; *pdf = norm * lobe / HdotI; /* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper) */ } - else { /* => ANisotropic case */ + else { + /* anisotropic */ float3 X, Y; make_orthonormals_tangent(N, sc->T, &X, &Y); @@ -130,7 +128,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, float3 N = sc->N; float NdotI = dot(N, I); - if (NdotI > 0.0f) { + if(NdotI > 0.0f) { float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0); float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1); @@ -146,21 +144,23 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, /* sample spherical coords for h in tangent space */ float phi; float cos_theta; - if (n_x == n_y) { /* => simple isotropic sampling */ + if(n_x == n_y) { + /* isotropic sampling */ phi = M_2PI_F * randu; cos_theta = powf(randv, 1.0f / (n_x + 1.0f)); } - else { /* => more complex anisotropic sampling */ - if (randu < 0.25f) { /* first quadrant */ + else { + /* anisotropic sampling */ + if(randu < 0.25f) { /* first quadrant */ float remapped_randu = 4.0f * randu; bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); } - else if (randu < 0.5f) { /* second quadrant */ + else if(randu < 0.5f) { /* second quadrant */ float remapped_randu = 4.0f * (.5f - randu); bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); phi = M_PI_F - phi; } - else if (randu < 0.75f) { /* third quadrant */ + else if(randu < 0.75f) { /* third quadrant */ float remapped_randu = 4.0f * (randu - 0.5f); bsdf_ashikhmin_shirley_sample_first_quadrant(n_x, n_y, remapped_randu, randv, &phi, &cos_theta); phi = M_PI_F + phi; @@ -185,13 +185,12 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, /* half vector to world space */ float3 H = h.x*X + h.y*Y + h.z*N; float HdotI = dot(H, I); - if (HdotI < 0.0f) H = -H; + if(HdotI < 0.0f) H = -H; /* reflect I on H to get omega_in */ *omega_in = -I + (2.0f * HdotI) * H; /* leave the rest to eval_reflect */ - /* (could maybe optimize a few things by manual inlining, but I doubt it would make much difference) */ *eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf); #ifdef __RAY_DIFFERENTIALS__ @@ -201,7 +200,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng, #endif } - return LABEL_REFLECT | LABEL_GLOSSY; + return LABEL_REFLECT|LABEL_GLOSSY; } diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index 949fe869549..371f467000c 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -108,11 +108,6 @@ ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const return make_float3 (cos_pi, cos_pi, cos_pi); } -ccl_device float bsdf_translucent_albedo(const ShaderClosure *sc, const float3 I) -{ - return 1.0f; -} - ccl_device int bsdf_translucent_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf) { float3 N = sc->N; diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h index b856774375f..cdaf84f1750 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h @@ -41,9 +41,9 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo float npos = pos * (float)(MAXCOLORS - 1); int ipos = float_to_int(npos); - if (ipos < 0) + if(ipos < 0) return colors[0]; - if (ipos >= (MAXCOLORS - 1)) + if(ipos >= (MAXCOLORS - 1)) return colors[MAXCOLORS - 1]; float offset = npos - (float)ipos; return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset; @@ -52,7 +52,7 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo ccl_device int bsdf_diffuse_ramp_setup(ShaderClosure *sc) { sc->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID; - return SD_BSDF | SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness) diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h index e0b5454592b..4f4fd5d26b8 100644 --- a/intern/cycles/kernel/closure/bsdf_hair.h +++ b/intern/cycles/kernel/closure/bsdf_hair.h @@ -49,7 +49,7 @@ ccl_device int bsdf_hair_reflection_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID; sc->data0 = clamp(sc->data0, 0.001f, 1.0f); sc->data1 = clamp(sc->data1, 0.001f, 1.0f); - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc) @@ -57,7 +57,7 @@ ccl_device int bsdf_hair_transmission_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID; sc->data0 = clamp(sc->data0, 0.001f, 1.0f); sc->data1 = clamp(sc->data1, 0.001f, 1.0f); - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device float3 bsdf_hair_reflection_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 8737b0e2d94..9561885525f 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -305,7 +305,7 @@ ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc) @@ -315,7 +315,7 @@ ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) @@ -325,7 +325,7 @@ ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc) sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness) @@ -657,7 +657,7 @@ ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc) sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc) @@ -666,7 +666,7 @@ ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc) sc->data1 = clamp(sc->data1, 0.0f, 1.0f); /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) @@ -675,7 +675,7 @@ ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc) sc->data1 = sc->data0; /* alpha_y */ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; - return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness) diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index 6f685d5eeea..6d3b915c24a 100644 --- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -25,7 +25,7 @@ ccl_device float3 bsdf_oren_nayar_get_intensity(const ShaderClosure *sc, float3 float nv = max(dot(n, v), 0.0f); float t = dot(l, v) - nl * nv; - if (t > 0.0f) + if(t > 0.0f) t /= max(nl, nv) + FLT_MIN; float is = nl * (sc->data0 + sc->data1 * t); return make_float3(is, is, is); @@ -44,7 +44,7 @@ ccl_device int bsdf_oren_nayar_setup(ShaderClosure *sc) sc->data0 = 1.0f * div; sc->data1 = sigma * div; - return SD_BSDF | SD_BSDF_HAS_EVAL; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness) @@ -53,7 +53,7 @@ ccl_device void bsdf_oren_nayar_blur(ShaderClosure *sc, float roughness) ccl_device float3 bsdf_oren_nayar_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf) { - if (dot(sc->N, omega_in) > 0.0f) { + if(dot(sc->N, omega_in) > 0.0f) { *pdf = 0.5f * M_1_PI_F; return bsdf_oren_nayar_get_intensity(sc, sc->N, I, omega_in); } @@ -72,7 +72,7 @@ ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 { sample_uniform_hemisphere(sc->N, randu, randv, omega_in, pdf); - if (dot(Ng, *omega_in) > 0.0f) { + if(dot(Ng, *omega_in) > 0.0f) { *eval = bsdf_oren_nayar_get_intensity(sc, sc->N, I, *omega_in); #ifdef __RAY_DIFFERENTIALS__ @@ -86,7 +86,7 @@ ccl_device int bsdf_oren_nayar_sample(const ShaderClosure *sc, float3 Ng, float3 *eval = make_float3(0.0f, 0.0f, 0.0f); } - return LABEL_REFLECT | LABEL_DIFFUSE; + return LABEL_REFLECT|LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index 2b4e1c68640..f9f263719e9 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -41,9 +41,9 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float float npos = pos * (float)(MAXCOLORS - 1); int ipos = float_to_int(npos); - if (ipos < 0) + if(ipos < 0) return colors[0]; - if (ipos >= (MAXCOLORS - 1)) + if(ipos >= (MAXCOLORS - 1)) return colors[MAXCOLORS - 1]; float offset = npos - (float)ipos; return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset; @@ -54,7 +54,7 @@ ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc) sc->data0 = max(sc->data0, 0.0f); sc->type = CLOSURE_BSDF_PHONG_RAMP_ID; - return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY; + return SD_BSDF|SD_BSDF_HAS_EVAL; } ccl_device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness) @@ -67,11 +67,11 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const fl float cosNI = dot(sc->N, omega_in); float cosNO = dot(sc->N, I); - if (cosNI > 0 && cosNO > 0) { + if(cosNI > 0 && cosNO > 0) { // reflect the view vector float3 R = (2 * cosNO) * sc->N - I; float cosRI = dot(R, omega_in); - if (cosRI > 0) { + if(cosRI > 0) { float cosp = powf(cosRI, m_exponent); float common = 0.5f * M_1_PI_F * cosp; float out = cosNI * (m_exponent + 2) * common; @@ -93,7 +93,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo float cosNO = dot(sc->N, I); float m_exponent = sc->data0; - if (cosNO > 0) { + if(cosNO > 0) { // reflect the view vector float3 R = (2 * cosNO) * sc->N - I; @@ -111,12 +111,12 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo *omega_in = (cosf(phi) * sinTheta) * T + (sinf(phi) * sinTheta) * B + ( cosTheta) * R; - if (dot(Ng, *omega_in) > 0.0f) + if(dot(Ng, *omega_in) > 0.0f) { // common terms for pdf and eval float cosNI = dot(sc->N, *omega_in); // make sure the direction we chose is still in the right hemisphere - if (cosNI > 0) + if(cosNI > 0) { float cosp = powf(cosTheta, m_exponent); float common = 0.5f * M_1_PI_F * cosp; diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h index 9dd8d226f5b..16c16beee39 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -277,6 +277,7 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg, } else { /* pop */ + object = OBJECT_NONE; nodeAddr = traversalStack[stackPtr]; --stackPtr; } diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h index 5df6c75df86..207d5066fb2 100644 --- a/intern/cycles/kernel/geom/geom_primitive.h +++ b/intern/cycles/kernel/geom/geom_primitive.h @@ -144,7 +144,8 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) float3 center; #ifdef __HAIR__ - if(sd->type & PRIMITIVE_ALL_CURVE) { + bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE; + if(is_curve_primitive) { center = curve_motion_center_location(kg, sd); if(!(sd->flag & SD_TRANSFORM_APPLIED)) @@ -170,6 +171,13 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL); + +#ifdef __HAIR__ + if(is_curve_primitive && (sd->flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) { + object_position_transform(kg, sd, &motion_pre); + object_position_transform(kg, sd, &motion_post); + } +#endif } /* object motion. note that depending on the mesh having motion vectors, this diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h index 33a20494966..3cb6d168f80 100644 --- a/intern/cycles/kernel/geom/geom_volume.h +++ b/intern/cycles/kernel/geom/geom_volume.h @@ -52,7 +52,11 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, #ifdef __KERNEL_GPU__ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f); #else - float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); + float4 r; + if(sd->flag & SD_VOLUME_CUBIC) + r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC); + else + r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); #endif if(dx) *dx = 0.0f; @@ -68,7 +72,11 @@ ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *s #ifdef __KERNEL_GPU__ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f); #else - float4 r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); + float4 r; + if(sd->flag & SD_VOLUME_CUBIC) + r = kernel_tex_image_interp_3d_ex(id, P.x, P.y, P.z, INTERPOLATION_CUBIC); + else + r = kernel_tex_image_interp_3d(id, P.x, P.y, P.z); #endif if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index a1ec080e3d3..e80bfb32e89 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -198,10 +198,10 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, int num_samples = kernel_data.integrator.aa_samples; /* random number generator */ - RNG rng = cmj_hash(offset + i, 0); + RNG rng = cmj_hash(offset + i, kernel_data.integrator.seed); #if 0 - uint rng_state = cmj_hash(i, 0); + uint rng_state = cmj_hash(i, kernel_data.integrator.seed); float filter_x, filter_y; path_rng_init(kg, &rng_state, sample, num_samples, &rng, 0, 0, &filter_x, &filter_y); @@ -253,6 +253,10 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, /* data passes */ case SHADER_EVAL_NORMAL: { + if ((sd.flag & SD_HAS_BUMP)) { + shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); + } + /* compression: normal = (2 * color) - 1 */ out = sd.N * 0.5f + make_float3(0.5f, 0.5f, 0.5f); break; diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 403fd0a67f7..08c8bdd369d 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -25,10 +25,12 @@ #include "util_half.h" #include "util_types.h" -/* On 64bit linux single precision exponent is really slow comparing to the - * double precision version, even with float<->double conversion involved. +/* On x86_64, versions of glibc < 2.16 have an issue where expf is + * much slower than the double version. This was fixed in glibc 2.16. */ -#if !defined(__KERNEL_GPU__) && defined(__linux__) && defined(__x86_64__) +#if !defined(__KERNEL_GPU__) && defined(__x86_64__) && defined(__x86_64__) && \ + defined(__GNU_LIBRARY__) && defined(__GLIBC__ ) && defined(__GLIBC_MINOR__) && \ + (__GLIBC__ <= 2 && __GLIBC_MINOR__ < 16) # define expf(x) ((float)exp((double)(x))) #endif @@ -151,6 +153,13 @@ template<typename T> struct texture_image { ccl_always_inline float4 interp_3d(float x, float y, float z, bool periodic = false) { + return interp_3d_ex(x, y, z, interpolation, periodic); + } + + ccl_always_inline float4 interp_3d_ex(float x, float y, float z, + int interpolation = INTERPOLATION_LINEAR, + bool periodic = false) + { if(UNLIKELY(!data)) return make_float4(0.0f, 0.0f, 0.0f, 0.0f); @@ -174,7 +183,7 @@ template<typename T> struct texture_image { return read(data[ix + iy*width + iz*width*height]); } - else { + else if(interpolation == INTERPOLATION_LINEAR) { float tx = frac(x*(float)width - 0.5f, &ix); float ty = frac(y*(float)height - 0.5f, &iy); float tz = frac(z*(float)depth - 0.5f, &iz); @@ -212,6 +221,93 @@ template<typename T> struct texture_image { return r; } + else { + /* Tricubic b-spline interpolation. */ + const float tx = frac(x*(float)width - 0.5f, &ix); + const float ty = frac(y*(float)height - 0.5f, &iy); + const float tz = frac(z*(float)depth - 0.5f, &iz); + int pix, piy, piz, nnix, nniy, nniz; + + if(periodic) { + ix = wrap_periodic(ix, width); + iy = wrap_periodic(iy, height); + iz = wrap_periodic(iz, depth); + + pix = wrap_periodic(ix-1, width); + piy = wrap_periodic(iy-1, height); + piz = wrap_periodic(iz-1, depth); + + nix = wrap_periodic(ix+1, width); + niy = wrap_periodic(iy+1, height); + niz = wrap_periodic(iz+1, depth); + + nnix = wrap_periodic(ix+2, width); + nniy = wrap_periodic(iy+2, height); + nniz = wrap_periodic(iz+2, depth); + } + else { + ix = wrap_clamp(ix, width); + iy = wrap_clamp(iy, height); + iz = wrap_clamp(iz, depth); + + pix = wrap_clamp(ix-1, width); + piy = wrap_clamp(iy-1, height); + piz = wrap_clamp(iz-1, depth); + + nix = wrap_clamp(ix+1, width); + niy = wrap_clamp(iy+1, height); + niz = wrap_clamp(iz+1, depth); + + nnix = wrap_clamp(ix+2, width); + nniy = wrap_clamp(iy+2, height); + nniz = wrap_clamp(iz+2, depth); + } + + const int xc[4] = {pix, ix, nix, nnix}; + const int yc[4] = {width * piy, + width * iy, + width * niy, + width * nniy}; + const int zc[4] = {width * height * piz, + width * height * iz, + width * height * niz, + width * height * nniz}; + float u[4], v[4], w[4]; + + /* Some helper macro to keep code reasonable size, + * let compiler to inline all the matrix multiplications. + */ +#define SET_SPLINE_WEIGHTS(u, t) \ + { \ + u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \ + u[1] = (( 0.5f * t - 1.0f) * t ) * t + (2.0f/3.0f); \ + u[2] = (( -0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f/6.0f); \ + u[3] = (1.0f / 6.0f) * t * t * t; \ + } (void)0 +#define DATA(x, y, z) (read(data[xc[x] + yc[y] + zc[z]])) +#define COL_TERM(col, row) \ + (v[col] * (u[0] * DATA(0, col, row) + \ + u[1] * DATA(1, col, row) + \ + u[2] * DATA(2, col, row) + \ + u[3] * DATA(3, col, row))) +#define ROW_TERM(row) \ + (w[row] * (COL_TERM(0, row) + \ + COL_TERM(1, row) + \ + COL_TERM(2, row) + \ + COL_TERM(3, row))) + + SET_SPLINE_WEIGHTS(u, tx); + SET_SPLINE_WEIGHTS(v, ty); + SET_SPLINE_WEIGHTS(w, tz); + + /* Actual interpolation. */ + return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3); + +#undef COL_TERM +#undef ROW_TERM +#undef DATA +#undef SET_SPLINE_WEIGHTS + } } ccl_always_inline void dimensions_set(int width_, int height_, int depth_) @@ -244,6 +340,7 @@ typedef texture_image<uchar4> texture_image_uchar4; #define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size)) #define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y)) #define kernel_tex_image_interp_3d(tex, x, y, z) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp_3d(x, y, z) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp_3d(x, y, z)) +#define kernel_tex_image_interp_3d_ex(tex, x, y, z, interpolation) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp_3d_ex(x, y, z, interpolation) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp_3d_ex(x, y, z, interpolation)) #define kernel_data (kg->__data) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index e7f62f230f8..9dfbfd91881 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -167,12 +167,143 @@ ccl_device float3 sphere_light_sample(float3 P, float3 center, float radius, flo return disk_light_sample(normalize(P - center), randu, randv)*radius; } -ccl_device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv) +/* Uses the following paper: + * + * Carlos Urena et al. + * An Area-Preserving Parametrization for Spherical Rectangles. + * + * https://www.solidangle.com/research/egsr2013_spherical_rectangle.pdf + */ +ccl_device float3 area_light_sample(float3 P, + float3 light_p, + float3 axisu, float3 axisv, + float randu, float randv, + float *pdf) { - randu = randu - 0.5f; - randv = randv - 0.5f; + /* In our name system we're using P for the center, + * which is o in the paper. + */ + + float3 corner = light_p - axisu * 0.5f - axisv * 0.5f; + float axisu_len, axisv_len; + /* Compute local reference system R. */ + float3 x = normalize_len(axisu, &axisu_len); + float3 y = normalize_len(axisv, &axisv_len); + float3 z = cross(x, y); + /* Compute rectangle coords in local reference system. */ + float3 dir = corner - P; + float z0 = dot(dir, z); + /* Flip 'z' to make it point against Q. */ + if(z0 > 0.0f) { + z *= -1.0f; + z0 *= -1.0f; + } + float z0sq = z0 * z0; + float x0 = dot(dir, x); + float y0 = dot(dir, y); + float x1 = x0 + axisu_len; + float y1 = y0 + axisv_len; + float y0sq = y0 * y0; + float y1sq = y1 * y1; + /* Create vectors to four vertices. */ + float3 v00 = make_float3(x0, y0, z0); + float3 v01 = make_float3(x0, y1, z0); + float3 v10 = make_float3(x1, y0, z0); + float3 v11 = make_float3(x1, y1, z0); + /* Compute normals to edges. */ + float3 n0 = normalize(cross(v00, v10)); + float3 n1 = normalize(cross(v10, v11)); + float3 n2 = normalize(cross(v11, v01)); + float3 n3 = normalize(cross(v01, v00)); + /* Compute internal angles (gamma_i). */ + float g0 = safe_acosf(-dot(n0, n1)); + float g1 = safe_acosf(-dot(n1, n2)); + float g2 = safe_acosf(-dot(n2, n3)); + float g3 = safe_acosf(-dot(n3, n0)); + /* Compute predefined constants. */ + float b0 = n0.z; + float b1 = n2.z; + float b0sq = b0 * b0; + float k = M_2PI_F - g2 - g3; + /* Compute solid angle from internal angles. */ + float S = g0 + g1 - k; + + /* Compute cu. */ + float au = randu * S + k; + float fu = (cosf(au) * b0 - b1) / sinf(au); + float cu = 1.0f / sqrtf(fu * fu + b0sq) * (fu > 0.0f ? 1.0f : -1.0f); + cu = clamp(cu, -1.0f, 1.0f); + /* Compute xu. */ + float xu = -(cu * z0) / sqrtf(1.0f - cu * cu); + xu = clamp(xu, x0, x1); + /* Compute yv. */ + float d = sqrtf(xu * xu + z0sq); + float h0 = y0 / sqrtf(d * d + y0sq); + float h1 = y1 / sqrtf(d * d + y1sq); + float hv = h0 + randv * (h1 - h0), hv2 = hv * hv; + float yv = (hv2 < 1.0f - 1e-6f) ? (hv * d) / sqrtf(1.0f - hv2) : y1; + + if(S != 0.0f) + *pdf = 1.0f / S; + else + *pdf = 0.0f; + + /* Transform (xu, yv, z0) to world coords. */ + return P + xu * x + yv * y + z0 * z; +} - return axisu*randu + axisv*randv; +/* TODO(sergey): This is actually a duplicated code from above, but how to avoid + * this without having some nasty function with loads of parameters? + */ +ccl_device float area_light_pdf(float3 P, + float3 light_p, + float3 axisu, float3 axisv) +{ + /* In our name system we're using P for the center, + * which is o in the paper. + */ + + float3 corner = light_p - axisu * 0.5f - axisv * 0.5f; + float axisu_len, axisv_len; + /* Compute local reference system R. */ + float3 x = normalize_len(axisu, &axisu_len); + float3 y = normalize_len(axisv, &axisv_len); + float3 z = cross(x, y); + /* Compute rectangle coords in local reference system. */ + float3 dir = corner - P; + float z0 = dot(dir, z); + /* Flip 'z' to make it point against Q. */ + if(z0 > 0.0f) { + z *= -1.0f; + z0 *= -1.0f; + } + float x0 = dot(dir, x); + float y0 = dot(dir, y); + float x1 = x0 + axisu_len; + float y1 = y0 + axisv_len; + /* Create vectors to four vertices. */ + float3 v00 = make_float3(x0, y0, z0); + float3 v01 = make_float3(x0, y1, z0); + float3 v10 = make_float3(x1, y0, z0); + float3 v11 = make_float3(x1, y1, z0); + /* Compute normals to edges. */ + float3 n0 = normalize(cross(v00, v10)); + float3 n1 = normalize(cross(v10, v11)); + float3 n2 = normalize(cross(v11, v01)); + float3 n3 = normalize(cross(v01, v00)); + /* Compute internal angles (gamma_i). */ + float g0 = safe_acosf(-dot(n0, n1)); + float g1 = safe_acosf(-dot(n1, n2)); + float g2 = safe_acosf(-dot(n2, n3)); + float g3 = safe_acosf(-dot(n3, n0)); + /* Compute predefined constants. */ + float k = M_2PI_F - g2 - g3; + /* Compute solid angle from internal angles. */ + float S = g0 + g1 - k; + if(S != 0.0f) + return 1.0f / S; + else + return 0.0f; } ccl_device float spot_light_attenuation(float4 data1, float4 data2, LightSample *ls) @@ -276,6 +407,7 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp, float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2); ls->eval_fac *= spot_light_attenuation(data1, data2, ls); } + ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); } else { /* area light */ @@ -286,18 +418,22 @@ ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp, float3 axisv = make_float3(data2.y, data2.z, data2.w); float3 D = make_float3(data3.y, data3.z, data3.w); - ls->P += area_light_sample(axisu, axisv, randu, randv); + ls->P = area_light_sample(P, ls->P, + axisu, axisv, + randu, randv, + &ls->pdf); + ls->Ng = D; ls->D = normalize_len(ls->P - P, &ls->t); float invarea = data2.x; - ls->eval_fac = 0.25f*invarea; - ls->pdf = invarea; + + if(dot(ls->D, D) > 0.0f) + ls->pdf = 0.0f; } ls->eval_fac *= kernel_data.integrator.inv_pdf_lights; - ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); } } @@ -355,6 +491,7 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, ls->D = D; ls->t = FLT_MAX; + /* compute pdf */ float invarea = data1.w; ls->pdf = invarea/(costheta*costheta*costheta); ls->eval_fac = ls->pdf; @@ -386,6 +523,10 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, if(ls->eval_fac == 0.0f) return false; } + + /* compute pdf */ + if(ls->t != FLT_MAX) + ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); } else if(type == LIGHT_AREA) { /* area light */ @@ -412,16 +553,12 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, ls->D = D; ls->Ng = Ng; - ls->pdf = invarea; - ls->eval_fac = 0.25f*ls->pdf; + ls->pdf = area_light_pdf(P, ls->P, axisu, axisv); + ls->eval_fac = 0.25f*invarea; } else return false; - /* compute pdf */ - if(ls->t != FLT_MAX) - ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); - return true; } @@ -514,7 +651,13 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt) /* Generic Light */ -ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls) +ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce) +{ + float4 data4 = kernel_tex_fetch(__light_data, index*LIGHT_SIZE + 4); + return (bounce > __float_as_int(data4.x)); +} + +ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, int bounce, LightSample *ls) { /* sample index */ int index = light_distribution_sample(kg, randt); @@ -536,6 +679,12 @@ ccl_device void light_sample(KernelGlobals *kg, float randt, float randu, float } else { int lamp = -prim-1; + + if(UNLIKELY(light_select_reached_max_bounces(kg, lamp, bounce))) { + ls->pdf = 0.0f; + return; + } + lamp_light_sample(kg, lamp, randu, randv, P, ls); } } @@ -546,22 +695,5 @@ ccl_device int light_select_num_samples(KernelGlobals *kg, int index) return __float_as_int(data3.x); } -ccl_device int lamp_light_eval_sample(KernelGlobals *kg, float randt) -{ - /* sample index */ - int index = light_distribution_sample(kg, randt); - - /* fetch light data */ - float4 l = kernel_tex_fetch(__light_distribution, index); - int prim = __float_as_int(l.y); - - if(prim < 0) { - int lamp = -prim-1; - return lamp; - } - else - return LAMP_NONE; -} - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index 9553c2da0df..e5ba1f41c47 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -38,6 +38,9 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN if(sample_all_lights) { /* lamp sampling */ for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { + if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) + continue; + int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i)); float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); @@ -82,7 +85,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN light_t = 0.5f*light_t; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ @@ -103,7 +106,7 @@ ccl_device void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RN path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); /* sample random light */ if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { @@ -200,7 +203,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG #endif LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(direct_emission(kg, sd, &ls, &light_ray, &L_light, &is_lamp, state->bounce, state->transparent_bounce)) { /* trace shadow ray */ diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index da2d5e6eca8..11d3d94657b 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -40,7 +40,7 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng, light_ray.time = sd->time; #endif - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) return; @@ -56,7 +56,12 @@ ccl_device void kernel_path_volume_connect_light(KernelGlobals *kg, RNG *rng, #endif } -ccl_device bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng, +#ifdef __KERNEL_GPU__ +ccl_device_noinline +#else +ccl_device +#endif +bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng, ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) { /* sample phase function */ @@ -119,6 +124,9 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG if(sample_all_lights) { /* lamp sampling */ for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { + if(UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) + continue; + int num_samples = ceil_to_int(num_samples_adjust*light_select_num_samples(kg, i)); float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); RNG lamp_rng = cmj_hash(*rng, i); @@ -183,7 +191,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG light_t = 0.5f*light_t; LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -198,7 +206,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG kernel_assert(result == VOLUME_PATH_SCATTERED); /* todo: split up light_sample so we don't have to call it again with new position */ - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) continue; @@ -222,7 +230,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); LightSample ls; - light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls); float3 tp = throughput; @@ -237,7 +245,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG kernel_assert(result == VOLUME_PATH_SCATTERED); /* todo: split up light_sample so we don't have to call it again with new position */ - light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls); + light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls); if(ls.pdf == 0.0f) return; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index db08c328d7e..65089740ef9 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -681,7 +681,7 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd) for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_BSSRDF(sc->type)) + if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type)) eval += sc->weight; } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index ca1210f2d80..460ca7b68eb 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -29,7 +29,7 @@ CCL_NAMESPACE_BEGIN /* constants */ #define OBJECT_SIZE 11 #define OBJECT_VECTOR_SIZE 6 -#define LIGHT_SIZE 4 +#define LIGHT_SIZE 5 #define FILTER_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256 #define PARTICLE_SIZE 5 @@ -291,34 +291,34 @@ typedef enum ClosureLabel { typedef enum PassType { PASS_NONE = 0, - PASS_COMBINED = 1, - PASS_DEPTH = 2, - PASS_NORMAL = 4, - PASS_UV = 8, - PASS_OBJECT_ID = 16, - PASS_MATERIAL_ID = 32, - PASS_DIFFUSE_COLOR = 64, - PASS_GLOSSY_COLOR = 128, - PASS_TRANSMISSION_COLOR = 256, - PASS_DIFFUSE_INDIRECT = 512, - PASS_GLOSSY_INDIRECT = 1024, - PASS_TRANSMISSION_INDIRECT = 2048, - PASS_DIFFUSE_DIRECT = 4096, - PASS_GLOSSY_DIRECT = 8192, - PASS_TRANSMISSION_DIRECT = 16384, - PASS_EMISSION = 32768, - PASS_BACKGROUND = 65536, - PASS_AO = 131072, - PASS_SHADOW = 262144, - PASS_MOTION = 524288, - PASS_MOTION_WEIGHT = 1048576, - PASS_MIST = 2097152, - PASS_SUBSURFACE_DIRECT = 4194304, - PASS_SUBSURFACE_INDIRECT = 8388608, - PASS_SUBSURFACE_COLOR = 16777216, - PASS_LIGHT = 33554432, /* no real pass, used to force use_light_pass */ + PASS_COMBINED = (1 << 0), + PASS_DEPTH = (1 << 1), + PASS_NORMAL = (1 << 2), + PASS_UV = (1 << 3), + PASS_OBJECT_ID = (1 << 4), + PASS_MATERIAL_ID = (1 << 5), + PASS_DIFFUSE_COLOR = (1 << 6), + PASS_GLOSSY_COLOR = (1 << 7), + PASS_TRANSMISSION_COLOR = (1 << 8), + PASS_DIFFUSE_INDIRECT = (1 << 9), + PASS_GLOSSY_INDIRECT = (1 << 10), + PASS_TRANSMISSION_INDIRECT = (1 << 11), + PASS_DIFFUSE_DIRECT = (1 << 12), + PASS_GLOSSY_DIRECT = (1 << 13), + PASS_TRANSMISSION_DIRECT = (1 << 14), + PASS_EMISSION = (1 << 15), + PASS_BACKGROUND = (1 << 16), + PASS_AO = (1 << 17), + PASS_SHADOW = (1 << 18), + PASS_MOTION = (1 << 19), + PASS_MOTION_WEIGHT = (1 << 20), + PASS_MIST = (1 << 21), + PASS_SUBSURFACE_DIRECT = (1 << 22), + PASS_SUBSURFACE_INDIRECT = (1 << 23), + PASS_SUBSURFACE_COLOR = (1 << 24), + PASS_LIGHT = (1 << 25), /* no real pass, used to force use_light_pass */ #ifdef __KERNEL_DEBUG__ - PASS_BVH_TRAVERSAL_STEPS = 67108864, + PASS_BVH_TRAVERSAL_STEPS = (1 << 26), #endif } PassType; @@ -539,34 +539,25 @@ typedef enum AttributeStandard { #define MAX_CLOSURE 1 #endif -/* TODO(sergey): This is rather nasty bug happening in here, which - * could be simply a compilers bug for which we can't find a generic - * platform independent workaround. Also even if it's a compiler - * issue, it's not so simple to upgrade the compiler in the release - * environment for linux and doing it so closer to the release is - * rather a risky business. - * - * For this release it's probably safer to stick with such a rather - * dirty solution, and look for a cleaner fix during the next release - * cycle. +/* This struct is to be 16 bytes aligned, we also keep some extra precautions: + * - All the float3 members are in the beginning of the struct, so compiler + * does not put own padding trying to align this members. + * - We make sure OSL pointer is also 16 bytes aligned. */ typedef struct ShaderClosure { - ClosureType type; float3 weight; -#ifndef __APPLE__ + float3 N; + float3 T; + + ClosureType type; float sample_weight; -#endif float data0; float data1; float data2; + int pad1, pad2, pad3; - float3 N; - float3 T; -#ifdef __APPLE__ - float sample_weight; -#endif #ifdef __OSL__ - void *prim; + void *prim, *pad4; #endif } ShaderClosure; @@ -591,43 +582,46 @@ typedef enum ShaderContext { enum ShaderDataFlag { /* runtime flags */ - SD_BACKFACING = 1, /* backside of surface? */ - SD_EMISSION = 2, /* have emissive closure? */ - SD_BSDF = 4, /* have bsdf closure? */ - SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */ - SD_PHASE_HAS_EVAL = 8, /* have non-singular phase closure? */ - SD_BSDF_GLOSSY = 16, /* have glossy bsdf */ - SD_BSSRDF = 32, /* have bssrdf */ - SD_HOLDOUT = 64, /* have holdout closure? */ - SD_ABSORPTION = 128, /* have volume absorption closure? */ - SD_SCATTER = 256, /* have volume phase closure? */ - SD_AO = 512, /* have ao 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_BACKFACING = (1 << 0), /* backside of surface? */ + SD_EMISSION = (1 << 1), /* have emissive closure? */ + SD_BSDF = (1 << 2), /* have bsdf closure? */ + SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */ + SD_PHASE_HAS_EVAL = (1 << 3), /* have non-singular phase closure? */ + SD_BSSRDF = (1 << 4), /* have bssrdf */ + SD_HOLDOUT = (1 << 5), /* have holdout closure? */ + SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */ + SD_SCATTER = (1 << 7), /* have volume phase closure? */ + SD_AO = (1 << 8), /* have ao closure? */ + SD_TRANSPARENT = (1 << 9), /* have transparent closure? */ + + SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF| + SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO), /* shader flags */ - SD_USE_MIS = 2048, /* direct light sample */ - SD_HAS_TRANSPARENT_SHADOW = 4096, /* has transparent shadow */ - SD_HAS_VOLUME = 8192, /* has volume shader */ - SD_HAS_ONLY_VOLUME = 16384, /* has only volume shader, no surface */ - SD_HETEROGENEOUS_VOLUME = 32768, /* has heterogeneous volume */ - 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_USE_MIS = (1 << 10), /* direct light sample */ + SD_HAS_TRANSPARENT_SHADOW = (1 << 11), /* has transparent shadow */ + SD_HAS_VOLUME = (1 << 12), /* has volume shader */ + SD_HAS_ONLY_VOLUME = (1 << 13), /* has only volume shader, no surface */ + SD_HETEROGENEOUS_VOLUME = (1 << 14), /* has heterogeneous volume */ + SD_HAS_BSSRDF_BUMP = (1 << 15), /* bssrdf normal uses bump */ + SD_VOLUME_EQUIANGULAR = (1 << 16), /* use equiangular sampling */ + SD_VOLUME_MIS = (1 << 17), /* use multiple importance sampling */ + SD_VOLUME_CUBIC = (1 << 18), /* use cubic interpolation for voxels */ + SD_HAS_BUMP = (1 << 19), /* has data connected to the displacement input */ 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), + SD_HAS_BSSRDF_BUMP|SD_VOLUME_EQUIANGULAR|SD_VOLUME_MIS| + SD_VOLUME_CUBIC|SD_HAS_BUMP), /* object flags */ - SD_HOLDOUT_MASK = 524288, /* holdout for camera rays */ - SD_OBJECT_MOTION = 1048576, /* has object motion blur */ - SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */ - SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */ - SD_OBJECT_HAS_VOLUME = 8388608, /* object has a volume shader */ - SD_OBJECT_INTERSECTS_VOLUME = 16777216, /* object intersects AABB of an object with volume shader */ + SD_HOLDOUT_MASK = (1 << 20), /* holdout for camera rays */ + SD_OBJECT_MOTION = (1 << 21), /* has object motion blur */ + SD_TRANSFORM_APPLIED = (1 << 22), /* vertices have transform applied */ + SD_NEGATIVE_SCALE_APPLIED = (1 << 23), /* vertices have negative scale applied */ + SD_OBJECT_HAS_VOLUME = (1 << 24), /* object has a volume shader */ + SD_OBJECT_INTERSECTS_VOLUME = (1 << 25), /* object intersects AABB of an object with volume shader */ + SD_OBJECT_HAS_VERTEX_MOTION = (1 << 21), /* has position for motion vertices */ SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED| SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME| @@ -994,7 +988,7 @@ typedef struct KernelData { #ifdef __KERNEL_DEBUG__ typedef struct DebugData { - // Total number of BVH node travesal steps and primitives intersections + // Total number of BVH node traversal steps and primitives intersections // for the camera rays. int num_bvh_traversal_steps; } DebugData; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 93cb4c120ea..6a39ba928f0 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -581,7 +581,8 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals * through a volume. This can then latter be used for decoupled sampling as in: * "Importance Sampling Techniques for Path Tracing in Participating Media" * - * On the GPU this is only supported for homogeneous volumes (1 step), due to + * On the GPU this is only supported (but currently not enabled) + * for homogeneous volumes (1 step), due to * no support for malloc/free and too much stack usage with a fix size array. */ typedef struct VolumeStep { @@ -595,6 +596,7 @@ typedef struct VolumeStep { } VolumeStep; typedef struct VolumeSegment { + VolumeStep stack_step; /* stack storage for homogeneous step, to avoid malloc */ VolumeStep *steps; /* recorded steps */ int numsteps; /* number of steps */ int closure_flag; /* accumulated closure flags from all steps */ @@ -627,11 +629,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta /* compute exact steps in advance for malloc */ max_steps = max((int)ceilf(ray->t/step_size), 1); + segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); } else { max_steps = 1; step_size = ray->t; random_jitter_offset = 0.0f; + segment->steps = &segment->stack_step; } /* init accumulation variables */ @@ -640,10 +644,8 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta float3 cdf_distance = make_float3(0.0f, 0.0f, 0.0f); float t = 0.0f; - segment->closure_flag = 0; segment->numsteps = 0; - - segment->steps = (VolumeStep*)malloc(sizeof(VolumeStep)*max_steps); + segment->closure_flag = 0; VolumeStep *step = segment->steps; @@ -729,16 +731,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta ccl_device void kernel_volume_decoupled_free(KernelGlobals *kg, VolumeSegment *segment) { - free(segment->steps); + if(segment->steps != &segment->stack_step) + free(segment->steps); } /* scattering for homogeneous and heterogeneous volumes, using decoupled ray - * marching. unlike the non-decoupled functions, these do not do probalistic - * scattering, they always scatter if there is any non-zero scattering - * coefficient. + * marching. this function does not do emission or modify throughput. * - * these also do not do emission or modify throughput. - * * function is expected to return VOLUME_PATH_SCATTERED when probalistic_scatter is false */ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter( KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd, @@ -958,7 +957,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, Ray *ray, VolumeStack *stack) { - /* NULL ray happens in the baker, does it need proper initializetion of + /* NULL ray happens in the baker, does it need proper initialization of * camera in volume? */ if(!kernel_data.cam.is_inside_volume || ray == NULL) { @@ -992,31 +991,29 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &volume_ray, 0, 0); - if(sd.flag & SD_HAS_VOLUME) { - if(sd.flag & SD_BACKFACING) { - /* If ray exited the volume and never entered to that volume - * it means that camera is inside such a volume. - */ - bool is_enclosed = false; - for(int i = 0; i < enclosed_index; ++i) { - if(enclosed_volumes[i] == sd.object) { - is_enclosed = true; - break; - } - } - if(is_enclosed == false) { - stack[stack_index].object = sd.object; - stack[stack_index].shader = sd.shader; - ++stack_index; + if(sd.flag & SD_BACKFACING) { + /* If ray exited the volume and never entered to that volume + * it means that camera is inside such a volume. + */ + bool is_enclosed = false; + for(int i = 0; i < enclosed_index; ++i) { + if(enclosed_volumes[i] == sd.object) { + is_enclosed = true; + break; } } - else { - /* If ray from camera enters the volume, this volume shouldn't - * be added to the stak on exit. - */ - enclosed_volumes[enclosed_index++] = sd.object; + if(is_enclosed == false) { + stack[stack_index].object = sd.object; + stack[stack_index].shader = sd.shader; + ++stack_index; } } + else { + /* If ray from camera enters the volume, this volume shouldn't + * be added to the stack on exit. + */ + enclosed_volumes[enclosed_index++] = sd.object; + } /* Move ray forward. */ volume_ray.P = ray_offset(sd.P, -sd.Ng); diff --git a/intern/cycles/kernel/osl/SConscript b/intern/cycles/kernel/osl/SConscript index d721edbaf6e..0a21d3e6819 100644 --- a/intern/cycles/kernel/osl/SConscript +++ b/intern/cycles/kernel/osl/SConscript @@ -38,6 +38,7 @@ incs.append(env['BF_OIIO_INC']) incs.append(env['BF_BOOST_INC']) incs.append(env['BF_OSL_INC']) incs.append(env['BF_OPENEXR_INC'].split()) +incs.append('#/intern/atomic') defs.append('CCL_NAMESPACE_BEGIN=namespace ccl {') defs.append('CCL_NAMESPACE_END=}') @@ -46,6 +47,16 @@ defs.append('WITH_OSL') if env['WITH_BF_CYCLES_DEBUG']: defs.append('WITH_CYCLES_DEBUG') +if env['WITH_BF_CYCLES_LOGGING']: + defs.append('WITH_CYCLES_LOGGING') + defs.append('GOOGLE_GLOG_DLL_DECL=') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + incs.append('#extern/libmv/third_party/glog/src/windows') + incs.append('#extern/libmv/third_party/gflags') + else: + incs.append('#extern/libmv/third_party/glog/src') + incs.append('#extern/libmv/third_party/gflags') + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): cxxflags.append('-DBOOST_NO_RTTI -DBOOST_NO_TYPEID /fp:fast'.split()) incs.append(env['BF_PTHREADS_INC']) diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index cc9942b024e..1d99f1d2682 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -189,11 +189,7 @@ static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, O /* optimization: it's possible to not use a prepare function at all and * only initialize the actual class when accessing the closure component * data, but then we need to map the id to the class somehow */ -#ifdef CLOSURE_PREPARE - ss->register_closure(name, id, params, prepare, NULL, NULL); -#else - ss->register_closure(name, id, params, prepare, NULL); -#endif + ss->register_closure(name, id, params, prepare, NULL, 16); } void OSLShader::register_closures(OSLShadingSystem *ss_) diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index a9694651e14..7a93aa05222 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -834,7 +834,7 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, OSL::ShaderGlo bool OSLRenderServices::texture(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, float s, float t, float dsdx, float dtdx, - float dsdy, float dtdy, float *result) + float dsdy, float dtdy, int nchannels, float *result) { OSL::TextureSystem *ts = osl_ts; ShaderData *sd = (ShaderData *)(sg->renderstate); @@ -869,9 +869,9 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, PtexFilter::Options opts(PtexFilter::f_bicubic, mipmaplerp, sharpness); PtexPtr<PtexFilter> f(PtexFilter::getFilter(r, opts)); - f->eval(result, options.firstchannel, options.nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy); + f->eval(result, options.firstchannel, nchannels, faceid, u, v, dudx, dvdx, dudy, dvdy); - for(int c = r->numChannels(); c < options.nchannels; c++) + for(int c = r->numChannels(); c < nchannels; c++) result[c] = result[0]; return true; @@ -880,15 +880,15 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, bool status; if(filename[0] == '@' && filename.find('.') == -1) { - int slot = atoi(filename.c_str() + 1); + int slot = atoi(filename.c_str() + 1); float4 rgba = kernel_tex_image_interp(slot, s, 1.0f - t); result[0] = rgba[0]; - if(options.nchannels > 1) + if(nchannels > 1) result[1] = rgba[1]; - if(options.nchannels > 2) + if(nchannels > 2) result[2] = rgba[2]; - if(options.nchannels > 3) + if(nchannels > 3) result[3] = rgba[3]; status = true; } @@ -898,17 +898,24 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); +#if OIIO_VERSION < 10500 status = ts->texture(th, thread_info, - options, s, t, dsdx, dtdx, dsdy, dtdy, result); + options, s, t, dsdx, dtdx, dsdy, dtdy, + result); +#else + status = ts->texture(th, thread_info, + options, s, t, dsdx, dtdx, dsdy, dtdy, + nchannels, result); +#endif } if(!status) { - if(options.nchannels == 3 || options.nchannels == 4) { + if(nchannels == 3 || nchannels == 4) { result[0] = 1.0f; result[1] = 0.0f; result[2] = 1.0f; - if(options.nchannels == 4) + if(nchannels == 4) result[3] = 1.0f; } } @@ -919,7 +926,7 @@ bool OSLRenderServices::texture(ustring filename, TextureOpt &options, bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &P, const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, - const OSL::Vec3 &dPdz, float *result) + const OSL::Vec3 &dPdz, int nchannels, float *result) { OSL::TextureSystem *ts = osl_ts; ShaderData *sd = (ShaderData *)(sg->renderstate); @@ -929,16 +936,22 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); +#if OIIO_VERSION < 10500 bool status = ts->texture3d(th, thread_info, options, P, dPdx, dPdy, dPdz, result); +#else + bool status = ts->texture3d(th, thread_info, + options, P, dPdx, dPdy, dPdz, + nchannels, result); +#endif if(!status) { - if(options.nchannels == 3 || options.nchannels == 4) { + if(nchannels == 3 || nchannels == 4) { result[0] = 1.0f; result[1] = 0.0f; result[2] = 1.0f; - if(options.nchannels == 4) + if(nchannels == 4) result[3] = 1.0f; } @@ -949,7 +962,8 @@ bool OSLRenderServices::texture3d(ustring filename, TextureOpt &options, bool OSLRenderServices::environment(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &R, - const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result) + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, + int nchannels, float *result) { OSL::TextureSystem *ts = osl_ts; ShaderData *sd = (ShaderData *)(sg->renderstate); @@ -958,16 +972,23 @@ bool OSLRenderServices::environment(ustring filename, TextureOpt &options, OIIO::TextureSystem::Perthread *thread_info = tdata->oiio_thread_info; OIIO::TextureSystem::TextureHandle *th = ts->get_texture_handle(filename, thread_info); + +#if OIIO_VERSION < 10500 bool status = ts->environment(th, thread_info, options, R, dRdx, dRdy, result); +#else + bool status = ts->environment(th, thread_info, + options, R, dRdx, dRdy, + nchannels, result); +#endif if(!status) { - if(options.nchannels == 3 || options.nchannels == 4) { + if(nchannels == 3 || nchannels == 4) { result[0] = 1.0f; result[1] = 0.0f; result[2] = 1.0f; - if(options.nchannels == 4) + if(nchannels == 4) result[3] = 1.0f; } } diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 6f928a0d103..e9026d95f34 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -97,16 +97,17 @@ public: bool texture(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, float s, float t, float dsdx, float dtdx, - float dsdy, float dtdy, float *result); + float dsdy, float dtdy, int nchannels, float *result); bool texture3d(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &P, const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, - const OSL::Vec3 &dPdz, float *result); + const OSL::Vec3 &dPdz, int nchannels, float *result); bool environment(ustring filename, TextureOpt &options, OSL::ShaderGlobals *sg, const OSL::Vec3 &R, - const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, float *result); + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, + int nchannels, float *result); bool get_texture_info(OSL::ShaderGlobals *sg, ustring filename, int subimage, ustring dataname, TypeDesc datatype, void *data); @@ -159,70 +160,37 @@ public: static ustring u_v; static ustring u_empty; -#if OSL_LIBRARY_VERSION_CODE < 10500 - bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) { - return get_matrix(NULL, result, xform, time); - } - - bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time) { - return get_inverse_matrix(NULL, result, xform, time); - } - - bool get_matrix(OSL::Matrix44 &result, ustring from, float time) { - return get_matrix(NULL, result, from, time); - } - - bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time) { - return get_inverse_matrix(NULL, result, to, time); - } - - bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) { - return get_matrix(NULL, result, xform); - } - - bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform) { - return get_inverse_matrix(NULL, result, xform); - } + /* Code to make OSL versions transition smooth. */ - bool get_matrix(OSL::Matrix44 &result, ustring from) { - return get_matrix(NULL, result, from); +#if OSL_LIBRARY_VERSION_CODE < 10600 + inline bool texture(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, + float s, float t, float dsdx, float dtdx, + float dsdy, float dtdy, float *result) + { + return texture(filename, options, sg, s, t, dsdx, dtdx, dsdy, dtdy, + options.nchannels, result); } - bool get_inverse_matrix(OSL::Matrix44 &result, ustring to) { - return get_inverse_matrix(NULL, result, to); + inline bool texture3d(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &P, + const OSL::Vec3 &dPdx, const OSL::Vec3 &dPdy, + const OSL::Vec3 &dPdz, float *result) + { + return texture3d(filename, options, sg, P, dPdx, dPdy, dPdz, + options.nchannels, result); } - bool get_array_attribute(void *renderstate, bool derivatives, - ustring object, TypeDesc type, ustring name, - int index, void *val) { - OSL::ShaderGlobals sg; - sg.renderstate = renderstate; - return get_array_attribute(&sg, derivatives, - object, type, name, - index, val); - } - - bool get_attribute(void *renderstate, bool derivatives, ustring object_name, - TypeDesc type, ustring name, void *val) { - OSL::ShaderGlobals sg; - sg.renderstate = renderstate; - return get_attribute(&sg, derivatives, object_name, type, name, val); - } - - bool has_userdata(ustring name, TypeDesc type, void *renderstate) { - return has_userdata(name, type, (OSL::ShaderGlobals *) renderstate); - } - - bool get_userdata(bool derivatives, ustring name, TypeDesc type, - void *renderstate, void *val) { - return get_userdata(derivatives, name, type, (OSL::ShaderGlobals *) renderstate, val); - } - - bool get_texture_info(ustring filename, int subimage, - ustring dataname, TypeDesc datatype, void *data) { - return get_texture_info(NULL, filename, subimage, dataname, datatype, data); + inline bool environment(ustring filename, TextureOpt &options, + OSL::ShaderGlobals *sg, const OSL::Vec3 &R, + const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy, + float *result) + { + return environment(filename, options, sg, R, dRdx, dRdy, + options.nchannels, result); } #endif + private: KernelGlobals *kernel_globals; OSL::TextureSystem *osl_ts; diff --git a/intern/cycles/kernel/shaders/node_combine_hsv.osl b/intern/cycles/kernel/shaders/node_combine_hsv.osl index 010773acc5c..574bad30b14 100644 --- a/intern/cycles/kernel/shaders/node_combine_hsv.osl +++ b/intern/cycles/kernel/shaders/node_combine_hsv.osl @@ -15,6 +15,7 @@ */ #include "stdosl.h" +#include "node_color.h" shader node_combine_hsv( float H = 0.0, @@ -22,6 +23,6 @@ shader node_combine_hsv( float V = 0.0, output color Color = 0.8) { - Color = color("hsv", H, S, V); + Color = color_srgb_to_scene_linear(color("hsv", H, S, V)); } diff --git a/intern/cycles/kernel/shaders/node_hsv.osl b/intern/cycles/kernel/shaders/node_hsv.osl index 4722bde4cd7..5f4300ee31d 100644 --- a/intern/cycles/kernel/shaders/node_hsv.osl +++ b/intern/cycles/kernel/shaders/node_hsv.osl @@ -35,6 +35,11 @@ shader node_hsv( Color = hsv_to_rgb(Color); + // Clamp color to prevent negative values cauzed by oversaturation. + Color[0] = max(Color[0], 0.0); + Color[1] = max(Color[1], 0.0); + Color[2] = max(Color[2], 0.0); + ColorOut = mix(ColorIn, Color, Fac); } diff --git a/intern/cycles/kernel/shaders/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl index 14af044e0c0..002eddb574c 100644 --- a/intern/cycles/kernel/shaders/node_normal.osl +++ b/intern/cycles/kernel/shaders/node_normal.osl @@ -23,6 +23,6 @@ shader node_normal( output float Dot = 1.0) { NormalOut = normalize(Direction); - Dot = dot(NormalOut, NormalIn); + Dot = dot(NormalOut, normalize(NormalIn)); } diff --git a/intern/cycles/kernel/shaders/node_separate_hsv.osl b/intern/cycles/kernel/shaders/node_separate_hsv.osl index 94fc5de9122..8bfb04aea1c 100644 --- a/intern/cycles/kernel/shaders/node_separate_hsv.osl +++ b/intern/cycles/kernel/shaders/node_separate_hsv.osl @@ -23,7 +23,7 @@ shader node_separate_hsv( output float S = 0.0, output float V = 0.0) { - color col = rgb_to_hsv(Color); + color col = rgb_to_hsv(color_scene_linear_to_srgb(Color)); H = col[0]; S = col[1]; diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index 1ff8f363b49..6babe98717c 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -505,6 +505,47 @@ closure color hair_transmission(normal N, float roughnessu, float roughnessv, ve closure color henyey_greenstein(float g) BUILTIN; closure color absorption() BUILTIN; +// OSL 1.5 Microfacet functions +closure color microfacet(string distribution, normal N, vector U, float xalpha, float yalpha, float eta, int refract) { + /* GGX */ + if (distribution == "ggx" || distribution == "default") { + if (!refract) { + if (xalpha == yalpha) { + /* Isotropic */ + return microfacet_ggx(N, xalpha); + } + else { + /* Anisotropic */ + return microfacet_ggx_aniso(N, U, xalpha, yalpha); + } + } + else { + return microfacet_ggx_refraction(N, xalpha, eta); + } + } + /* Beckmann */ + else { + if (!refract) { + if (xalpha == yalpha) { + /* Isotropic */ + return microfacet_beckmann(N, xalpha); + } + else { + /* Anisotropic */ + return microfacet_beckmann_aniso(N, U, xalpha, yalpha); + } + } + else { + return microfacet_beckmann_refraction(N, xalpha, eta); + } + } +} + +closure color microfacet (string distribution, normal N, float alpha, float eta, int refract) { + return microfacet(distribution, N, vector(0), alpha, alpha, eta, refract); +} + + // Renderer state int backfacing () BUILTIN; int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index c13eae813d6..5acfbbf972b 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -164,6 +164,7 @@ CCL_NAMESPACE_END #include "svm_mapping.h" #include "svm_normal.h" #include "svm_wave.h" +#include "svm_math_util.h" #include "svm_math.h" #include "svm_mix.h" #include "svm_ramp.h" diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index 11dfc4f096b..a02d853be1a 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -46,6 +46,11 @@ ccl_device void svm_node_hsv(KernelGlobals *kg, ShaderData *sd, float *stack, ui color.y = fac*color.y + (1.0f - fac)*in_color.y; color.z = fac*color.z + (1.0f - fac)*in_color.z; + /* Clamp color to prevent negative values cauzed by oversaturation. */ + color.x = max(color.x, 0.0f); + color.y = max(color.y, 0.0f); + color.z = max(color.z, 0.0f); + if (stack_valid(out_color_offset)) stack_store_float3(stack, out_color_offset, color); } diff --git a/intern/cycles/kernel/svm/svm_math.h b/intern/cycles/kernel/svm/svm_math.h index 1ce9386e40e..e3d8c1f3242 100644 --- a/intern/cycles/kernel/svm/svm_math.h +++ b/intern/cycles/kernel/svm/svm_math.h @@ -16,56 +16,6 @@ CCL_NAMESPACE_BEGIN -ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) -{ - float Fac; - - if(type == NODE_MATH_ADD) - Fac = Fac1 + Fac2; - else if(type == NODE_MATH_SUBTRACT) - Fac = Fac1 - Fac2; - else if(type == NODE_MATH_MULTIPLY) - Fac = Fac1*Fac2; - else if(type == NODE_MATH_DIVIDE) - Fac = safe_divide(Fac1, Fac2); - else if(type == NODE_MATH_SINE) - Fac = sinf(Fac1); - else if(type == NODE_MATH_COSINE) - Fac = cosf(Fac1); - else if(type == NODE_MATH_TANGENT) - Fac = tanf(Fac1); - else if(type == NODE_MATH_ARCSINE) - Fac = safe_asinf(Fac1); - else if(type == NODE_MATH_ARCCOSINE) - Fac = safe_acosf(Fac1); - else if(type == NODE_MATH_ARCTANGENT) - Fac = atanf(Fac1); - else if(type == NODE_MATH_POWER) - Fac = safe_powf(Fac1, Fac2); - else if(type == NODE_MATH_LOGARITHM) - Fac = safe_logf(Fac1, Fac2); - else if(type == NODE_MATH_MINIMUM) - Fac = fminf(Fac1, Fac2); - else if(type == NODE_MATH_MAXIMUM) - Fac = fmaxf(Fac1, Fac2); - else if(type == NODE_MATH_ROUND) - Fac = floorf(Fac1 + 0.5f); - else if(type == NODE_MATH_LESS_THAN) - Fac = Fac1 < Fac2; - else if(type == NODE_MATH_GREATER_THAN) - Fac = Fac1 > Fac2; - else if(type == NODE_MATH_MODULO) - Fac = safe_modulo(Fac1, Fac2); - else if(type == NODE_MATH_ABSOLUTE) - Fac = fabsf(Fac1); - else if(type == NODE_MATH_CLAMP) - Fac = clamp(Fac1, 0.0f, 1.0f); - else - Fac = 0.0f; - - return Fac; -} - ccl_device float average_fac(float3 v) { return (fabsf(v.x) + fabsf(v.y) + fabsf(v.z))/3.0f; diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h new file mode 100644 index 00000000000..b813bf531dc --- /dev/null +++ b/intern/cycles/kernel/svm/svm_math_util.h @@ -0,0 +1,70 @@ +/* + * Copyright 2011-2014 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +CCL_NAMESPACE_BEGIN + +ccl_device float svm_math(NodeMath type, float Fac1, float Fac2) +{ + float Fac; + + if(type == NODE_MATH_ADD) + Fac = Fac1 + Fac2; + else if(type == NODE_MATH_SUBTRACT) + Fac = Fac1 - Fac2; + else if(type == NODE_MATH_MULTIPLY) + Fac = Fac1*Fac2; + else if(type == NODE_MATH_DIVIDE) + Fac = safe_divide(Fac1, Fac2); + else if(type == NODE_MATH_SINE) + Fac = sinf(Fac1); + else if(type == NODE_MATH_COSINE) + Fac = cosf(Fac1); + else if(type == NODE_MATH_TANGENT) + Fac = tanf(Fac1); + else if(type == NODE_MATH_ARCSINE) + Fac = safe_asinf(Fac1); + else if(type == NODE_MATH_ARCCOSINE) + Fac = safe_acosf(Fac1); + else if(type == NODE_MATH_ARCTANGENT) + Fac = atanf(Fac1); + else if(type == NODE_MATH_POWER) + Fac = safe_powf(Fac1, Fac2); + else if(type == NODE_MATH_LOGARITHM) + Fac = safe_logf(Fac1, Fac2); + else if(type == NODE_MATH_MINIMUM) + Fac = fminf(Fac1, Fac2); + else if(type == NODE_MATH_MAXIMUM) + Fac = fmaxf(Fac1, Fac2); + else if(type == NODE_MATH_ROUND) + Fac = floorf(Fac1 + 0.5f); + else if(type == NODE_MATH_LESS_THAN) + Fac = Fac1 < Fac2; + else if(type == NODE_MATH_GREATER_THAN) + Fac = Fac1 > Fac2; + else if(type == NODE_MATH_MODULO) + Fac = safe_modulo(Fac1, Fac2); + else if(type == NODE_MATH_ABSOLUTE) + Fac = fabsf(Fac1); + else if(type == NODE_MATH_CLAMP) + Fac = clamp(Fac1, 0.0f, 1.0f); + else + Fac = 0.0f; + + return Fac; +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h index 111d5d47988..abf75b62bd5 100644 --- a/intern/cycles/kernel/svm/svm_sepcomb_hsv.h +++ b/intern/cycles/kernel/svm/svm_sepcomb_hsv.h @@ -26,7 +26,8 @@ ccl_device void svm_node_combine_hsv(KernelGlobals *kg, ShaderData *sd, float *s float value = stack_load_float(stack, value_in); /* Combine, and convert back to RGB */ - float3 color = hsv_to_rgb(make_float3(hue, saturation, value)); + float3 color = color_srgb_to_scene_linear( + hsv_to_rgb(make_float3(hue, saturation, value))); if (stack_valid(color_out)) stack_store_float3(stack, color_out, color); @@ -40,7 +41,7 @@ ccl_device void svm_node_separate_hsv(KernelGlobals *kg, ShaderData *sd, float * float3 color = stack_load_float3(stack, color_in); /* Convert to HSV */ - color = rgb_to_hsv(color); + color = rgb_to_hsv(color_scene_linear_to_srgb(color)); if (stack_valid(hue_out)) stack_store_float(stack, hue_out, color.x); |