diff options
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r-- | intern/cycles/kernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_textures.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_services.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_ies_light.osl | 42 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_ies.h | 110 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 1 |
9 files changed, 171 insertions, 3 deletions
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index 9b7f4e00084..457602ae4e7 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -178,6 +178,7 @@ set(SRC_SVM_HEADERS svm/svm_geometry.h svm/svm_gradient.h svm/svm_hsv.h + svm/svm_ies.h svm/svm_image.h svm/svm_invert.h svm/svm_light_path.h diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index efab69ee37d..ec7203d36eb 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -170,7 +170,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res); /* importance-sampled V direction */ - float dv = (randv - cdf_v.y) / (cdf_next_v.y - cdf_v.y); + float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv); float v = (index_v + dv) / res; /* this is basically std::lower_bound as used by pbrt */ @@ -196,7 +196,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res); /* importance-sampled U direction */ - float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y); + float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu); float u = (index_u + du) / res; /* compute pdf */ diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 9047b93a0b2..a7b8c492ee9 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -81,5 +81,8 @@ KERNEL_TEX(uint, __sobol_directions) /* image textures */ KERNEL_TEX(TextureInfo, __texture_info) +/* ies lights */ +KERNEL_TEX(float, __ies) + #undef KERNEL_TEX diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 0c5e5e30e47..32d86b7192a 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -956,9 +956,15 @@ bool OSLRenderServices::texture(ustring filename, status = true; } } + else if(filename[1] == 'l') { + /* IES light. */ + int slot = atoi(filename.c_str() + 2); + result[0] = kernel_ies_interp(kg, slot, s, t); + status = true; + } else { /* Packed texture. */ - int slot = atoi(filename.c_str() + 1); + int slot = atoi(filename.c_str() + 2); float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t); result[0] = rgba[0]; diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index 6ec651a96d8..b28d017c1c2 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC_OSL node_principled_volume.osl node_holdout.osl node_hsv.osl + node_ies_light.osl node_image_texture.osl node_invert.osl node_layer_weight.osl diff --git a/intern/cycles/kernel/shaders/node_ies_light.osl b/intern/cycles/kernel/shaders/node_ies_light.osl new file mode 100644 index 00000000000..a0954e3a444 --- /dev/null +++ b/intern/cycles/kernel/shaders/node_ies_light.osl @@ -0,0 +1,42 @@ +/* + * Copyright 2011-2015 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. + */ + +#include "stdosl.h" +#include "node_texture.h" + +/* IES Light */ + +shader node_ies_light( + int use_mapping = 0, + matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + int slot = 0, + float Strength = 1.0, + point Vector = I, + output float Fac = 0.0) +{ + point p = Vector; + + if (use_mapping) { + p = transform(mapping, p); + } + + p = normalize(p); + + float v_angle = acos(-p[2]); + float h_angle = atan2(p[0], p[1]) + M_PI; + + Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle); +} diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h index 39cd5da7b12..bfa146f2d93 100644 --- a/intern/cycles/kernel/svm/svm.h +++ b/intern/cycles/kernel/svm/svm.h @@ -157,6 +157,7 @@ CCL_NAMESPACE_END #include "kernel/svm/svm_camera.h" #include "kernel/svm/svm_geometry.h" #include "kernel/svm/svm_hsv.h" +#include "kernel/svm/svm_ies.h" #include "kernel/svm/svm_image.h" #include "kernel/svm/svm_gamma.h" #include "kernel/svm/svm_brightness.h" @@ -421,6 +422,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a case NODE_LIGHT_FALLOFF: svm_node_light_falloff(sd, stack, node); break; + case NODE_IES: + svm_node_ies(kg, sd, stack, node, &offset); + break; # endif /* __EXTRA_NODES__ */ #endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */ diff --git a/intern/cycles/kernel/svm/svm_ies.h b/intern/cycles/kernel/svm/svm_ies.h new file mode 100644 index 00000000000..6130c3348b0 --- /dev/null +++ b/intern/cycles/kernel/svm/svm_ies.h @@ -0,0 +1,110 @@ +/* + * Copyright 2011-2013 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 + +/* IES Light */ + +ccl_device_inline float interpolate_ies_vertical(KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h) +{ + /* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v + * (corresponding to the north pole) would result in artifacts. + * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole, + * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation. + * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take + * the corresponding value at the current horizontal coordinate. */ + +#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs+h*v_num+(v)) + /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */ + float a = IES_LOOKUP((v == 0)? 1 : v-1); + float b = IES_LOOKUP(v); + float c = IES_LOOKUP(v+1); + float d = IES_LOOKUP(min(v+2, v_num-1)); +#undef IES_LOOKUP + + return cubic_interp(a, b, c, d, v_frac); +} + +ccl_device_inline float kernel_ies_interp(KernelGlobals *kg, int slot, float h_angle, float v_angle) +{ + /* Find offset of the IES data in the table. */ + int ofs = __float_as_int(kernel_tex_fetch(__ies, slot)); + if(ofs == -1) { + return 100.0f; + } + + int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); + int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++)); + +#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs+(h)) +#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs+h_num+(v)) + + /* Check whether the angle is within the bounds of the IES texture. */ + if(v_angle >= IES_LOOKUP_ANGLE_V(v_num-1)) { + return 0.0f; + } + kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0)); + kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0)); + kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num-1)); + + /* Lookup the angles to find the table position. */ + int h_i, v_i; + /* TODO(lukas): Consider using bisection. Probably not worth it for the vast majority of IES files. */ + for(h_i = 0; IES_LOOKUP_ANGLE_H(h_i+1) < h_angle; h_i++); + for(v_i = 0; IES_LOOKUP_ANGLE_V(v_i+1) < v_angle; v_i++); + + float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i+1), h_angle); + float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i+1), v_angle); + +#undef IES_LOOKUP_ANGLE_H +#undef IES_LOOKUP_ANGLE_V + + /* Skip forward to the actual intensity data. */ + ofs += h_num+v_num; + + /* Perform cubic interpolation along the horizontal coordinate to get the intensity value. + * If h_i is zero, just wrap around since the horizontal angles always go over the full circle. + * However, the last entry (360°) equals the first one, so we need to wrap around to the one before that. */ + float a = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i == 0)? h_num-2 : h_i-1); + float b = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i); + float c = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i+1); + /* Same logic here, wrap around to the second element if necessary. */ + float d = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i+2 == h_num)? 1 : h_i+2); + + /* Cubic interpolation can result in negative values, so get rid of them. */ + return max(cubic_interp(a, b, c, d, h_frac), 0.0f); +} + +ccl_device void svm_node_ies(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) +{ + uint vector_offset, strength_offset, fac_offset, dummy, slot = node.z; + decode_node_uchar4(node.y, &strength_offset, &vector_offset, &fac_offset, &dummy); + + float3 vector = stack_load_float3(stack, vector_offset); + float strength = stack_load_float_default(stack, strength_offset, node.w); + + vector = normalize(vector); + float v_angle = safe_acosf(-vector.z); + float h_angle = atan2f(vector.x, vector.y) + M_PI_F; + + float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle); + + if(stack_valid(fac_offset)) { + stack_store_float(stack, fac_offset, fac); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index dc62e25b340..ac24d23ecd2 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -136,6 +136,7 @@ typedef enum ShaderNodeType { NODE_DISPLACEMENT, NODE_VECTOR_DISPLACEMENT, NODE_PRINCIPLED_VOLUME, + NODE_IES, } ShaderNodeType; typedef enum NodeAttributeType { |