Files
workinf_Blender_Wasm/blender-5.2.0/intern/cycles/kernel/svm/attribute.h
2026-08-12 04:47:48 -04:00

225 lines
7.5 KiB
C++

/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/globals.h"
#include "kernel/geom/attribute.h"
#include "kernel/geom/object.h"
#include "kernel/geom/primitive.h"
#include "kernel/geom/volume.h"
#include "kernel/svm/node_types.h"
#include "kernel/svm/util.h"
CCL_NAMESPACE_BEGIN
/* Attribute Node */
ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg,
ccl_private ShaderData *sd,
const ccl_global SVMNodeAttr &ccl_restrict node,
ccl_private NodeAttributeOutputType *type)
{
*type = node.output_type;
AttributeDescriptor desc;
if (sd->object != OBJECT_NONE) {
desc = find_attribute(kg, sd, node.attr);
if (!is_attribute_found(desc)) {
desc = attribute_not_found();
desc.type = (NodeAttributeType)node.output_type;
}
}
else {
/* background */
desc = attribute_not_found();
desc.type = (NodeAttributeType)node.output_type;
}
return desc;
}
/* Store attribute to the stack. Float3Type is float3 or dual3. */
template<typename Float3Type>
ccl_device_inline void svm_node_attr_store(const NodeAttributeOutputType type,
ccl_private float *stack,
const uint out_offset,
const ccl_private Float3Type &f)
{
using FloatType = dual_scalar_t<Float3Type>;
if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store(stack, out_offset, f);
}
else {
stack_store(stack, out_offset, FloatType(average(f)));
}
}
/* Core surface attribute evaluation, returning Float3Type = float3 or dual3.
* Fetches the attribute, applies output type conversion (float3 or scalar-as-float3),
* and computes derivatives when Float3Type is a dual type. */
template<typename Float3Type>
ccl_device_inline Float3Type
svm_node_attr_surface_eval(KernelGlobals kg,
ccl_private ShaderData *sd,
const ccl_global SVMNodeAttr &ccl_restrict node,
const NodeAttributeOutputType type,
const AttributeDescriptor desc)
{
using FloatType = dual_scalar_t<Float3Type>;
if (sd->type == PRIMITIVE_LAMP && node.attr == ATTR_STD_UV) {
Float3Type uv(make_float3(1.0f - sd->u - sd->v, sd->u, 0.0f));
if constexpr (is_dual_v<Float3Type>) {
uv.dx = make_float3(-sd->du.dx - sd->dv.dx, sd->du.dx, 0.0f);
uv.dy = make_float3(-sd->du.dy - sd->dv.dy, sd->du.dy, 0.0f);
}
return uv;
}
if (node.attr == ATTR_STD_GENERATED && !is_attribute_found(desc)) {
Float3Type f = shading_position<Float3Type>(sd);
object_inverse_position_transform_if_object(kg, sd, &f);
return f;
}
/* Surface attribute fetch with output type conversion. */
if (desc.type == NODE_ATTR_FLOAT) {
FloatType f = primitive_surface_attribute<FloatType>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(FloatType(1.0f));
}
return make_float3(f, f, f);
}
if (desc.type == NODE_ATTR_FLOAT2) {
if constexpr (is_dual_v<Float3Type>) {
dual2 f = primitive_surface_attribute<dual2>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
return make_float3(f.x());
}
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(FloatType(1.0f));
}
return make_float3(f);
}
else {
float2 f = primitive_surface_attribute<float2>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
return make_float3(f.x);
}
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(FloatType(1.0f));
}
return make_float3(f);
}
}
if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
if constexpr (is_dual_v<Float3Type>) {
dual4 f = primitive_surface_attribute<dual4>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
return make_float3(average(make_float3(f)));
}
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(f.w());
}
return make_float3(f);
}
else {
float4 f = primitive_surface_attribute<float4>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
return make_float3(average(make_float3(f)));
}
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(f.w);
}
return make_float3(f);
}
}
Float3Type f = primitive_surface_attribute<Float3Type>(kg, sd, desc);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
return make_float3(average(f));
}
if (type == NODE_ATTR_OUTPUT_FLOAT_ALPHA) {
return make_float3(FloatType(1.0f));
}
return f;
}
/* Surface attribute node. */
ccl_device_noinline void svm_node_attr_surface(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *ccl_restrict stack,
const ccl_global SVMNodeAttr &ccl_restrict node)
{
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
float3 data = svm_node_attr_surface_eval<float3>(kg, sd, node, type, desc);
svm_node_attr_store(type, stack, node.out_offset, data);
}
/* Evaluate surface attributes with derivatives and optional bump offset.
* Used for derivative tracking and bump mapping. */
ccl_device_noinline void svm_node_attr_derivative(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *ccl_restrict stack,
const ccl_global SVMNodeAttr &ccl_restrict node)
{
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
dual3 data = svm_node_attr_surface_eval<dual3>(kg, sd, node, type, desc);
if (node.bump_offset == NODE_BUMP_OFFSET_DX) {
data.val += data.dx * node.bump_filter_width;
}
else if (node.bump_offset == NODE_BUMP_OFFSET_DY) {
data.val += data.dy * node.bump_filter_width;
}
if (node.store_derivatives) {
svm_node_attr_store(type, stack, node.out_offset, data);
}
else {
svm_node_attr_store(type, stack, node.out_offset, float3(data.val));
}
}
#ifdef __VOLUME__
/* Volume attribute node. Volumes have no derivatives or bump. */
ccl_device_noinline void svm_node_attr_volume(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *ccl_restrict stack,
const ccl_global SVMNodeAttr &ccl_restrict node)
{
kernel_assert(primitive_is_volume_attribute(sd));
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type);
const bool stochastic_sample = __float_as_uint(node.bump_filter_width);
const float4 value = volume_attribute_float4(kg, sd, desc, stochastic_sample);
if (type == NODE_ATTR_OUTPUT_FLOAT) {
stack_store_float(stack, node.out_offset, volume_attribute_value<float>(value));
}
else if (type == NODE_ATTR_OUTPUT_FLOAT3) {
stack_store_float3(stack, node.out_offset, volume_attribute_value<float3>(value));
}
else {
stack_store_float(stack, node.out_offset, volume_attribute_alpha(value));
}
}
#endif
CCL_NAMESPACE_END