diff options
Diffstat (limited to 'intern/cycles/kernel/svm/svm_ramp.h')
-rw-r--r-- | intern/cycles/kernel/svm/svm_ramp.h | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h index e92df3c093c..563e5bcb5e4 100644 --- a/intern/cycles/kernel/svm/svm_ramp.h +++ b/intern/cycles/kernel/svm/svm_ramp.h @@ -21,6 +21,48 @@ CCL_NAMESPACE_BEGIN /* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */ +ccl_device_inline float fetch_float(const KernelGlobals *kg, int offset) +{ + uint4 node = kernel_tex_fetch(__svm_nodes, offset); + return __uint_as_float(node.x); +} + +ccl_device_inline float float_ramp_lookup(const KernelGlobals *kg, + int offset, + float f, + bool interpolate, + bool extrapolate, + int table_size) +{ + if ((f < 0.0f || f > 1.0f) && extrapolate) { + float t0, dy; + if (f < 0.0f) { + t0 = fetch_float(kg, offset); + dy = t0 - fetch_float(kg, offset + 1); + f = -f; + } + else { + t0 = fetch_float(kg, offset + table_size - 1); + dy = t0 - fetch_float(kg, offset + table_size - 2); + f = f - 1.0f; + } + return t0 + dy * f * (table_size - 1); + } + + f = saturate(f) * (table_size - 1); + + /* clamp int as well in case of NaN */ + int i = clamp(float_to_int(f), 0, table_size - 1); + float t = f - (float)i; + + float a = fetch_float(kg, offset + i); + + if (interpolate && t > 0.0f) + a = (1.0f - t) * a + t * fetch_float(kg, offset + i + 1); + + return a; +} + ccl_device_inline float4 rgb_ramp_lookup(const KernelGlobals *kg, int offset, float f, @@ -105,6 +147,30 @@ ccl_device_noinline int svm_node_curves( return offset; } +ccl_device_noinline int svm_node_curve( + const KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int offset) +{ + uint fac_offset, value_in_offset, out_offset; + svm_unpack_node_uchar3(node.y, &fac_offset, &value_in_offset, &out_offset); + + uint table_size = read_node(kg, &offset).x; + + float fac = stack_load_float(stack, fac_offset); + float in = stack_load_float(stack, value_in_offset); + + const float min = __int_as_float(node.z), max = __int_as_float(node.w); + const float range = max - min; + const float relpos = (in - min) / range; + + float v = float_ramp_lookup(kg, offset, relpos, true, true, table_size); + + in = (1.0f - fac) * in + fac * v; + stack_store_float(stack, out_offset, in); + + offset += table_size; + return offset; +} + CCL_NAMESPACE_END #endif /* __SVM_RAMP_H__ */ |