157 lines
4.9 KiB
C
157 lines
4.9 KiB
C
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#pragma once
|
|
|
|
#include "kernel/svm/node_types.h"
|
|
#include "kernel/svm/util.h"
|
|
|
|
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(KernelGlobals kg, const int offset)
|
|
{
|
|
return __uint_as_float(kernel_data_fetch(svm_nodes, offset));
|
|
}
|
|
|
|
ccl_device_inline float float_ramp_lookup(KernelGlobals kg,
|
|
const int offset,
|
|
float f,
|
|
bool interpolate,
|
|
bool extrapolate,
|
|
const int table_size)
|
|
{
|
|
if ((f < 0.0f || f > 1.0f) && extrapolate) {
|
|
float t0;
|
|
float 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 = saturatef(f) * (table_size - 1);
|
|
|
|
/* clamp int as well in case of NaN */
|
|
const int i = clamp(float_to_int(f), 0, table_size - 1);
|
|
const 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(KernelGlobals kg,
|
|
const int offset,
|
|
float f,
|
|
bool interpolate,
|
|
bool extrapolate,
|
|
const int table_size)
|
|
{
|
|
if ((f < 0.0f || f > 1.0f) && extrapolate) {
|
|
float4 t0;
|
|
float4 dy;
|
|
if (f < 0.0f) {
|
|
t0 = svm_node_get_data_float4(kg, offset);
|
|
dy = t0 - svm_node_get_data_float4(kg, offset + 4);
|
|
f = -f;
|
|
}
|
|
else {
|
|
t0 = svm_node_get_data_float4(kg, offset + (table_size - 1) * 4);
|
|
dy = t0 - svm_node_get_data_float4(kg, offset + (table_size - 2) * 4);
|
|
f = f - 1.0f;
|
|
}
|
|
return t0 + dy * f * (table_size - 1);
|
|
}
|
|
|
|
f = saturatef(f) * (table_size - 1);
|
|
|
|
/* clamp int as well in case of NaN */
|
|
const int i = clamp(float_to_int(f), 0, table_size - 1);
|
|
const float t = f - (float)i;
|
|
|
|
float4 a = svm_node_get_data_float4(kg, offset + i * 4);
|
|
|
|
if (interpolate && t > 0.0f) {
|
|
a = (1.0f - t) * a + t * svm_node_get_data_float4(kg, offset + (i + 1) * 4);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
ccl_device_noinline int svm_node_rgb_ramp(KernelGlobals kg,
|
|
ccl_private float *stack,
|
|
const ccl_global SVMNodeRGBRamp &node,
|
|
int offset)
|
|
{
|
|
const float fac = stack_load(stack, node.fac);
|
|
const float4 color = rgb_ramp_lookup(kg, offset, fac, node.interpolate, false, node.table_size);
|
|
|
|
if (stack_valid(node.color_offset)) {
|
|
stack_store_float3(stack, node.color_offset, make_float3(color));
|
|
}
|
|
if (stack_valid(node.alpha_offset)) {
|
|
stack_store_float(stack, node.alpha_offset, color.w);
|
|
}
|
|
|
|
offset += node.table_size * 4;
|
|
return offset;
|
|
}
|
|
|
|
ccl_device_noinline int svm_node_curves(KernelGlobals kg,
|
|
ccl_private float *stack,
|
|
const ccl_global SVMNodeCurves &node,
|
|
int offset)
|
|
{
|
|
const float fac = stack_load(stack, node.fac);
|
|
float3 color = stack_load(stack, node.color);
|
|
|
|
const float range_x = node.max_x - node.min_x;
|
|
const float3 relpos = (color - make_float3(node.min_x, node.min_x, node.min_x)) / range_x;
|
|
|
|
const float r = rgb_ramp_lookup(kg, offset, relpos.x, true, node.extrapolate, node.table_size).x;
|
|
const float g = rgb_ramp_lookup(kg, offset, relpos.y, true, node.extrapolate, node.table_size).y;
|
|
const float b = rgb_ramp_lookup(kg, offset, relpos.z, true, node.extrapolate, node.table_size).z;
|
|
|
|
color = (1.0f - fac) * color + fac * make_float3(r, g, b);
|
|
stack_store_float3(stack, node.out_offset, color);
|
|
|
|
offset += node.table_size * 4;
|
|
return offset;
|
|
}
|
|
|
|
ccl_device_noinline int svm_node_curve(KernelGlobals kg,
|
|
ccl_private float *stack,
|
|
const ccl_global SVMNodeFloatCurve &node,
|
|
int offset)
|
|
{
|
|
const float fac = stack_load(stack, node.fac);
|
|
float in = stack_load(stack, node.value_in);
|
|
|
|
const float range = node.max_x - node.min_x;
|
|
const float relpos = (in - node.min_x) / range;
|
|
|
|
const float v = float_ramp_lookup(kg, offset, relpos, true, node.extrapolate, node.table_size);
|
|
|
|
in = (1.0f - fac) * in + fac * v;
|
|
stack_store_float(stack, node.out_offset, in);
|
|
|
|
offset += node.table_size;
|
|
return offset;
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|