blender/intern/cycles/kernel/geom/volume.h
Patrick Mours ef7c9e793e Cycles: Remove separate OSL attribute map and instead always use SVM attribute map
The SVM attribute map is always generated and uses a simple
linear search to lookup by an opaque ID, so can reuse that for OSL
as well and simply use the attribute name hash as ID instead of
generating a unique value separately. This works for both object
and geometry attributes since the SVM attribute map already
stores both. Simplifies code somewhat and reduces memory
usage slightly.

This patch was split from D15902.

Differential Revision: https://developer.blender.org/D15918
2022-09-09 15:35:44 +02:00

85 lines
2.7 KiB
C

/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
/* Volume Primitive
*
* Volumes are just regions inside meshes with the mesh surface as boundaries.
* There isn't as much data to access as for surfaces, there is only a position
* to do lookups in 3D voxel or procedural textures.
*
* 3D voxel textures can be assigned as attributes per mesh, which means the
* same shader can be used for volume objects with different densities, etc. */
#pragma once
CCL_NAMESPACE_BEGIN
#ifdef __VOLUME__
/* Return position normalized to 0..1 in mesh bounds */
ccl_device_inline float3 volume_normalized_position(KernelGlobals kg,
ccl_private const ShaderData *sd,
float3 P)
{
/* todo: optimize this so it's just a single matrix multiplication when
* possible (not motion blur), or perhaps even just translation + scale */
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED_TRANSFORM);
object_inverse_position_transform(kg, sd, &P);
if (desc.offset != ATTR_STD_NOT_FOUND) {
Transform tfm = primitive_attribute_matrix(kg, desc);
P = transform_point(&tfm, P);
}
return P;
}
ccl_device float volume_attribute_value_to_float(const float4 value)
{
return average(float4_to_float3(value));
}
ccl_device float volume_attribute_value_to_alpha(const float4 value)
{
return value.w;
}
ccl_device float3 volume_attribute_value_to_float3(const float4 value)
{
if (value.w > 1e-6f && value.w != 1.0f) {
/* For RGBA colors, unpremultiply after interpolation. */
return float4_to_float3(value) / value.w;
}
else {
return float4_to_float3(value);
}
}
ccl_device float4 volume_attribute_float4(KernelGlobals kg,
ccl_private const ShaderData *sd,
const AttributeDescriptor desc)
{
if (desc.element & (ATTR_ELEMENT_OBJECT | ATTR_ELEMENT_MESH)) {
return kernel_data_fetch(attributes_float4, desc.offset);
}
else if (desc.element == ATTR_ELEMENT_VOXEL) {
/* todo: optimize this so we don't have to transform both here and in
* kernel_tex_image_interp_3d when possible. Also could optimize for the
* common case where transform is translation/scale only. */
float3 P = sd->P;
object_inverse_position_transform(kg, sd, &P);
InterpolationType interp = (sd->flag & SD_VOLUME_CUBIC) ? INTERPOLATION_CUBIC :
INTERPOLATION_NONE;
return kernel_tex_image_interp_3d(kg, desc.offset, P, interp);
}
else {
return zero_float4();
}
}
#endif
CCL_NAMESPACE_END