Shaders: Remove point density texture node

This is replaced by geometry nodes, where volumes can now be generated from
point clouds and meshes with more control, and more efficient rendering as a
sparse volume.

No backwareds compatibility is provided, as this would be complicated, and
probably this feature was not used much in the past few years.

This node was supported in Cycles only, not by EEVEE.

Pull Request: https://projects.blender.org/blender/blender/pulls/140292
This commit is contained in:
Brecht Van Lommel
2025-06-12 17:07:53 +02:00
parent 8530e7c39b
commit b920f6f1a7
63 changed files with 1 additions and 2227 deletions

View File

@@ -33,7 +33,6 @@ set(SRC
session.cpp
shader.cpp
sync.cpp
texture.cpp
viewport.cpp
volume.cpp
@@ -48,7 +47,6 @@ set(SRC
output_driver.h
sync.h
session.h
texture.h
util.h
viewport.h
)

View File

@@ -260,35 +260,6 @@ int BlenderImageLoader::get_tile_number() const
return b_iuser.tile;
}
/* Point Density */
BlenderPointDensityLoader::BlenderPointDensityLoader(BL::Depsgraph b_depsgraph,
BL::ShaderNodeTexPointDensity b_node)
: b_depsgraph(b_depsgraph), b_node(b_node)
{
}
bool BlenderPointDensityLoader::load_metadata(const ImageDeviceFeatures & /*features*/,
ImageMetaData &metadata)
{
metadata.channels = 4;
metadata.width = b_node.resolution();
metadata.height = metadata.width;
metadata.depth = metadata.width;
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
return true;
}
bool BlenderPointDensityLoader::load_pixels(const ImageMetaData & /*metadata*/,
void *pixels,
const size_t /*pixels_size*/,
const bool /*associate_alpha*/)
{
int length;
b_node.calc_point_density(b_depsgraph, &length, (float **)&pixels);
return true;
}
void BlenderSession::builtin_images_load()
{
/* Force builtin images to be loaded along with Blender data sync. This
@@ -304,15 +275,4 @@ void BlenderSession::builtin_images_load()
manager->device_load_builtin(device, session->scene.get(), session->progress);
}
string BlenderPointDensityLoader::name() const
{
return BL::ShaderNodeTexPointDensity(b_node).name();
}
bool BlenderPointDensityLoader::equals(const ImageLoader &other) const
{
const BlenderPointDensityLoader &other_loader = (const BlenderPointDensityLoader &)other;
return b_node == other_loader.b_node && b_depsgraph == other_loader.b_depsgraph;
}
CCL_NAMESPACE_END

View File

@@ -38,20 +38,4 @@ class BlenderImageLoader : public ImageLoader {
bool free_cache;
};
class BlenderPointDensityLoader : public ImageLoader {
public:
BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node);
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
bool load_pixels(const ImageMetaData &metadata,
void *pixels,
const size_t pixels_size,
const bool associate_alpha) override;
string name() const override;
bool equals(const ImageLoader &other) const override;
BL::Depsgraph b_depsgraph;
BL::ShaderNodeTexPointDensity b_node;
};
CCL_NAMESPACE_END

View File

@@ -13,7 +13,6 @@
#include "blender/image.h"
#include "blender/sync.h"
#include "blender/texture.h"
#include "blender/util.h"
#include "util/set.h"
@@ -1106,32 +1105,6 @@ static ShaderNode *add_node(Scene *scene,
uvm->set_from_dupli(b_uvmap_node.from_instancer());
node = uvm;
}
else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
PointDensityTextureNode *point_density = graph->create_node<PointDensityTextureNode>();
point_density->set_space((NodeTexVoxelSpace)b_point_density_node.space());
point_density->set_interpolation(get_image_interpolation(b_point_density_node));
point_density->handle = scene->image_manager->add_image(
make_unique<BlenderPointDensityLoader>(b_depsgraph, b_point_density_node),
point_density->image_params());
b_point_density_node.cache_point_density(b_depsgraph);
node = point_density;
/* Transformation form world space to texture space.
*
* NOTE: Do this after the texture is cached, this is because getting
* min/max will need to access this cache.
*/
BL::Object b_ob(b_point_density_node.object());
if (b_ob) {
float3 loc;
float3 size;
point_density_texture_space(b_depsgraph, b_point_density_node, loc, size);
point_density->set_tfm(transform_translate(-loc) * transform_scale(size) *
transform_inverse(get_transform(b_ob.matrix_world())));
}
}
else if (b_node.is_a(&RNA_ShaderNodeBevel)) {
BL::ShaderNodeBevel b_bevel_node(b_node);
BevelNode *bevel = graph->create_node<BevelNode>();

View File

@@ -1,51 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "blender/texture.h"
#include "util/math.h"
CCL_NAMESPACE_BEGIN
namespace {
/* Point density helpers. */
void density_texture_space_invert(float3 &loc, float3 &size)
{
if (size.x != 0.0f) {
size.x = 0.5f / size.x;
}
if (size.y != 0.0f) {
size.y = 0.5f / size.y;
}
if (size.z != 0.0f) {
size.z = 0.5f / size.z;
}
loc = loc * size - make_float3(0.5f, 0.5f, 0.5f);
}
} /* namespace */
void point_density_texture_space(BL::Depsgraph &b_depsgraph,
BL::ShaderNodeTexPointDensity &b_point_density_node,
float3 &loc,
float3 &size)
{
BL::Object b_ob(b_point_density_node.object());
if (!b_ob) {
loc = zero_float3();
size = zero_float3();
return;
}
float3 min;
float3 max;
b_point_density_node.calc_point_density_minmax(b_depsgraph, &min[0], &max[0]);
loc = (min + max) * 0.5f;
size = (max - min) * 0.5f;
density_texture_space_invert(loc, size);
}
CCL_NAMESPACE_END

View File

@@ -1,18 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "RNA_blender_cpp.hh"
#include "util/types.h"
CCL_NAMESPACE_BEGIN
void point_density_texture_space(BL::Depsgraph &b_depsgraph,
BL::ShaderNodeTexPointDensity &b_point_density_node,
float3 &loc,
float3 &size);
CCL_NAMESPACE_END

View File

@@ -221,7 +221,6 @@ set(SRC_KERNEL_SVM_HEADERS
svm/vector_rotate.h
svm/vector_transform.h
svm/voronoi.h
svm/voxel.h
svm/wave.h
svm/white_noise.h
svm/vertex_color.h

View File

@@ -97,8 +97,6 @@ set(SRC_OSL
node_vector_transform.osl
node_vertex_color.osl
node_voronoi_texture.osl
node_voxel_texture.osl
node_voxel_texture_zero.osl
node_wavelength.osl
node_blackbody.osl
node_wave_texture.osl

View File

@@ -1,33 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "stdcycles.h"
shader node_voxel_texture(string filename = "",
string interpolation = "linear",
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
point Vector = P,
output float Density = 0,
output color Color = 0)
{
point p = Vector;
if (use_mapping) {
p = transform(mapping, p);
}
else {
p = transform("object", Vector);
matrix tfm;
if (getattribute("geom:generated_transform", tfm))
p = transform(tfm, p);
}
if (p[0] < 0.0 || p[1] < 0.0 || p[2] < 0.0 || p[0] > 1.0 || p[1] > 1.0 || p[2] > 1.0) {
Density = 0;
Color = color(0, 0, 0);
}
else {
Color = (color)texture3d(
filename, p, "wrap", "periodic", "interp", interpolation, "alpha", Density);
}
}

View File

@@ -1,18 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2024 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#include "stdcycles.h"
shader node_voxel_texture_zero(
string filename = "",
string interpolation = "linear",
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
point Vector = P,
output float Density = 0,
output color Color = 0)
{
Density = 0;
Color = color(0, 0, 0);
}

View File

@@ -100,7 +100,6 @@ SHADER_NODE_TYPE(NODE_VECTOR_MAP_RANGE)
SHADER_NODE_TYPE(NODE_CLAMP)
SHADER_NODE_TYPE(NODE_BEVEL)
SHADER_NODE_TYPE(NODE_AMBIENT_OCCLUSION)
SHADER_NODE_TYPE(NODE_TEX_VOXEL)
SHADER_NODE_TYPE(NODE_AOV_START)
SHADER_NODE_TYPE(NODE_AOV_COLOR)
SHADER_NODE_TYPE(NODE_AOV_VALUE)

View File

@@ -73,7 +73,6 @@
#include "kernel/svm/vector_transform.h"
#include "kernel/svm/vertex_color.h"
#include "kernel/svm/voronoi.h"
#include "kernel/svm/voxel.h"
#include "kernel/svm/wave.h"
#include "kernel/svm/wavelength.h"
#include "kernel/svm/white_noise.h"
@@ -463,9 +462,6 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
break;
#endif
SVM_CASE(NODE_TEX_VOXEL)
offset = svm_node_tex_voxel<node_feature_mask>(kg, sd, stack, node, offset);
break;
SVM_CASE(NODE_AOV_START)
if (!svm_node_aov_check(path_flag, render_buffer)) {
return;

View File

@@ -372,11 +372,6 @@ enum NodeBumpOffset {
NODE_BUMP_OFFSET_DY,
};
enum NodeTexVoxelSpace {
NODE_TEX_VOXEL_SPACE_OBJECT = 0,
NODE_TEX_VOXEL_SPACE_WORLD = 1,
};
enum NodeAO {
NODE_AO_ONLY_LOCAL = (1 << 0),
NODE_AO_INSIDE = (1 << 1),

View File

@@ -1,67 +0,0 @@
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
*
* SPDX-License-Identifier: Apache-2.0 */
#pragma once
#include "kernel/geom/volume.h"
#include "kernel/svm/util.h"
CCL_NAMESPACE_BEGIN
/* TODO(sergey): Think of making it more generic volume-type attribute
* sampler.
*/
template<uint node_feature_mask>
ccl_device_noinline int svm_node_tex_voxel(KernelGlobals kg,
ccl_private ShaderData *sd,
ccl_private float *stack,
const uint4 node,
int offset)
{
uint co_offset;
uint density_out_offset;
uint color_out_offset;
uint space;
svm_unpack_node_uchar4(node.z, &co_offset, &density_out_offset, &color_out_offset, &space);
float4 r = zero_float4();
#ifdef __VOLUME__
IF_KERNEL_NODES_FEATURE(VOLUME)
{
const int id = node.y;
float3 co = stack_load_float3(stack, co_offset);
if (space == NODE_TEX_VOXEL_SPACE_OBJECT) {
co = volume_normalized_position(kg, sd, co);
}
else {
kernel_assert(space == NODE_TEX_VOXEL_SPACE_WORLD);
Transform tfm;
tfm.x = read_node_float(kg, &offset);
tfm.y = read_node_float(kg, &offset);
tfm.z = read_node_float(kg, &offset);
co = transform_point(&tfm, co);
}
r = kernel_tex_image_interp_3d(kg, id, co, INTERPOLATION_NONE);
}
else
#endif /* __VOLUME__ */
if (space != NODE_TEX_VOXEL_SPACE_OBJECT)
{
read_node_float(kg, &offset);
read_node_float(kg, &offset);
read_node_float(kg, &offset);
}
if (stack_valid(density_out_offset)) {
stack_store_float(stack, density_out_offset, r.w);
}
if (stack_valid(color_out_offset)) {
stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
}
return offset;
}
CCL_NAMESPACE_END

View File

@@ -1856,156 +1856,6 @@ void BrickTextureNode::compile(OSLCompiler &compiler)
compiler.add(this, "node_brick_texture");
}
/* Point Density Texture */
NODE_DEFINE(PointDensityTextureNode)
{
NodeType *type = NodeType::add("point_density_texture", create, NodeType::SHADER);
SOCKET_STRING(filename, "Filename", ustring());
static NodeEnum space_enum;
space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
static NodeEnum interpolation_enum;
interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
interpolation_enum.insert("smart", INTERPOLATION_SMART);
SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
SOCKET_IN_POINT(vector, "Vector", zero_float3(), SocketType::LINK_POSITION);
SOCKET_OUT_FLOAT(density, "Density");
SOCKET_OUT_COLOR(color, "Color");
return type;
}
PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(get_node_type()) {}
PointDensityTextureNode::~PointDensityTextureNode() = default;
ShaderNode *PointDensityTextureNode::clone(ShaderGraph *graph) const
{
/* Increase image user count for new node. We need to ensure to not call
* add_image again, to work around access of freed data on the Blender
* side. A better solution should be found to avoid this. */
PointDensityTextureNode *node = graph->create_node<PointDensityTextureNode>(*this);
node->handle = handle; /* TODO: not needed? */
return node;
}
void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if (shader->has_volume) {
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
}
ShaderNode::attributes(shader, attributes);
}
ImageParams PointDensityTextureNode::image_params() const
{
ImageParams params;
params.interpolation = interpolation;
return params;
}
void PointDensityTextureNode::compile(SVMCompiler &compiler)
{
ShaderInput *vector_in = input("Vector");
ShaderOutput *density_out = output("Density");
ShaderOutput *color_out = output("Color");
const bool use_density = !density_out->links.empty();
const bool use_color = !color_out->links.empty();
if (!(use_density || use_color)) {
return;
}
/* Point Density is only supported for volume shaders. */
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
if (use_density) {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(density_out));
}
if (use_color) {
compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
compiler.add_node(NODE_VALUE_V, zero_float3());
}
return;
}
if (handle.empty()) {
ImageManager *image_manager = compiler.scene->image_manager.get();
handle = image_manager->add_image(filename.string(), image_params());
}
const int slot = handle.svm_slot();
if (slot != -1) {
compiler.stack_assign(vector_in);
compiler.add_node(NODE_TEX_VOXEL,
slot,
compiler.encode_uchar4(compiler.stack_assign(vector_in),
compiler.stack_assign_if_linked(density_out),
compiler.stack_assign_if_linked(color_out),
space));
if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.add_node(tfm.x);
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
}
}
else {
if (use_density) {
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(density_out));
}
if (use_color) {
compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
compiler.add_node(
NODE_VALUE_V,
make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
}
}
}
void PointDensityTextureNode::compile(OSLCompiler &compiler)
{
ShaderOutput *density_out = output("Density");
ShaderOutput *color_out = output("Color");
const bool use_density = !density_out->links.empty();
const bool use_color = !color_out->links.empty();
if (!(use_density || use_color)) {
return;
}
/* Point Density is only supported for volume shaders. */
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
compiler.add(this, "node_voxel_texture_zero");
return;
}
if (handle.empty()) {
ImageManager *image_manager = compiler.scene->image_manager.get();
handle = image_manager->add_image(filename.string(), image_params());
}
compiler.parameter_texture("filename", handle);
if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.parameter("mapping", tfm);
compiler.parameter("use_mapping", 1);
}
compiler.parameter(this, "interpolation");
compiler.add(this, "node_voxel_texture");
}
/* Normal */
NODE_DEFINE(NormalNode)

View File

@@ -344,42 +344,6 @@ class BrickTextureNode : public TextureNode {
NODE_SOCKET_API(float3, vector)
};
class PointDensityTextureNode : public ShaderNode {
public:
SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
~PointDensityTextureNode() override;
ShaderNode *clone(ShaderGraph *graph) const override;
void attributes(Shader *shader, AttributeRequestSet *attributes) override;
bool has_attribute_dependency() override
{
return true;
}
bool has_spatial_varying() override
{
return true;
}
/* Parameters. */
NODE_SOCKET_API(ustring, filename)
NODE_SOCKET_API(NodeTexVoxelSpace, space)
NODE_SOCKET_API(InterpolationType, interpolation)
NODE_SOCKET_API(Transform, tfm)
NODE_SOCKET_API(float3, vector)
/* Runtime. */
ImageHandle handle;
ImageParams image_params() const;
bool equals(const ShaderNode &other) override
{
const PointDensityTextureNode &other_node = (const PointDensityTextureNode &)other;
return ShaderNode::equals(other) && handle == other_node.handle;
}
};
class IESLightNode : public TextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(IESLightNode)

View File

@@ -171,7 +171,6 @@ def get_texture_node_types():
"ShaderNodeTexMagic",
"ShaderNodeTexMusgrave",
"ShaderNodeTexNoise",
"ShaderNodeTexPointDensity",
"ShaderNodeTexSky",
"ShaderNodeTexVoronoi",
"ShaderNodeTexWave",

View File

@@ -2014,7 +2014,6 @@ url_manual_mapping = (
("bpy.types.shadernodebsdfanisotropic*", "render/shader_nodes/shader/glossy.html#bpy-types-shadernodebsdfanisotropic"),
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
("bpy.types.shadernodetexpointdensity*", "render/shader_nodes/textures/point_density.html#bpy-types-shadernodetexpointdensity"),
("bpy.types.shadernodevectortransform*", "render/shader_nodes/vector/transform.html#bpy-types-shadernodevectortransform"),
("bpy.types.softbodysettings.friction*", "physics/soft_body/settings/object.html#bpy-types-softbodysettings-friction"),
("bpy.types.softbodysettings.goal_max*", "physics/soft_body/settings/goal.html#bpy-types-softbodysettings-goal-max"),

View File

@@ -337,7 +337,6 @@ class NODE_MT_category_shader_texture(Menu):
node_add_menu.add_node_type(layout, "ShaderNodeTexImage")
node_add_menu.add_node_type(layout, "ShaderNodeTexMagic")
node_add_menu.add_node_type(layout, "ShaderNodeTexNoise")
node_add_menu.add_node_type(layout, "ShaderNodeTexPointDensity")
node_add_menu.add_node_type(layout, "ShaderNodeTexSky")
node_add_menu.add_node_type(layout, "ShaderNodeTexVoronoi")
node_add_menu.add_node_type(layout, "ShaderNodeTexWave")

View File

@@ -108,7 +108,7 @@
#define SH_NODE_COMBXYZ 189
#define SH_NODE_OUTPUT_LINESTYLE 190
#define SH_NODE_UVALONGSTROKE 191
#define SH_NODE_TEX_POINTDENSITY 192
// #define SH_NODE_TEX_POINTDENSITY 192
#define SH_NODE_BSDF_PRINCIPLED 193
#define SH_NODE_TEX_IES 194
#define SH_NODE_EEVEE_SPECULAR 195

View File

@@ -15,7 +15,6 @@ struct LibraryForeachIDData;
struct MTex;
struct Main;
struct ParticleSettings;
struct PointDensity;
struct Tex;
struct TexMapping;
struct TexResult;
@@ -59,12 +58,6 @@ void BKE_texture_mapping_init(struct TexMapping *texmap);
struct ColorMapping *BKE_texture_colormapping_add(void);
void BKE_texture_colormapping_default(struct ColorMapping *colormap);
void BKE_texture_pointdensity_init_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free_data(struct PointDensity *pd);
void BKE_texture_pointdensity_free(struct PointDensity *pd);
struct PointDensity *BKE_texture_pointdensity_add(void);
struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd, int flag);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
/**
* \returns true if this texture can use its #Texture.ima (even if its NULL).

View File

@@ -2082,11 +2082,6 @@ static void node_blend_read_data_storage(BlendDataReader *reader, bNodeTree *ntr
BLO_read_string(reader, &nss->bytecode);
break;
}
case SH_NODE_TEX_POINTDENSITY: {
NodeShaderTexPointDensity *npd = static_cast<NodeShaderTexPointDensity *>(node->storage);
npd->pd = dna::shallow_zero_initialize();
break;
}
case SH_NODE_TEX_IMAGE: {
NodeTexImage *tex = static_cast<NodeTexImage *>(node->storage);
tex->iuser.scene = nullptr;

View File

@@ -588,76 +588,6 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
/* ------------------------------------------------------------------------- */
void BKE_texture_pointdensity_init_data(PointDensity *pd)
{
pd->flag = 0;
pd->radius = 0.3f;
pd->falloff_type = TEX_PD_FALLOFF_STD;
pd->falloff_softness = 2.0;
pd->source = TEX_PD_PSYS;
pd->point_tree = nullptr;
pd->point_data = nullptr;
pd->noise_size = 0.5f;
pd->noise_depth = 1;
pd->noise_fac = 1.0f;
pd->noise_influence = TEX_PD_NOISE_STATIC;
pd->coba = BKE_colorband_add(true);
pd->speed_scale = 1.0f;
pd->totpoints = 0;
pd->object = nullptr;
pd->psys = 0;
pd->psys_cache_space = TEX_PD_WORLDSPACE;
pd->falloff_curve = BKE_curvemapping_add(1, 0, 0, 1, 1);
pd->falloff_curve->preset = CURVE_PRESET_LINE;
pd->falloff_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
BKE_curvemap_reset(pd->falloff_curve->cm,
&pd->falloff_curve->clipr,
pd->falloff_curve->preset,
CURVEMAP_SLOPE_POSITIVE);
BKE_curvemapping_changed(pd->falloff_curve, false);
}
PointDensity *BKE_texture_pointdensity_add()
{
PointDensity *pd = MEM_callocN<PointDensity>("pointdensity");
BKE_texture_pointdensity_init_data(pd);
return pd;
}
PointDensity *BKE_texture_pointdensity_copy(const PointDensity *pd, const int /*flag*/)
{
PointDensity *pdn;
pdn = static_cast<PointDensity *>(MEM_dupallocN(pd));
pdn->point_tree = nullptr;
pdn->point_data = nullptr;
if (pdn->coba) {
pdn->coba = static_cast<ColorBand *>(MEM_dupallocN(pdn->coba));
}
pdn->falloff_curve = BKE_curvemapping_copy(pdn->falloff_curve); /* can be nullptr */
return pdn;
}
void BKE_texture_pointdensity_free_data(PointDensity *pd)
{
if (pd->point_tree) {
BLI_bvhtree_free(static_cast<BVHTree *>(pd->point_tree));
pd->point_tree = nullptr;
}
MEM_SAFE_FREE(pd->point_data);
MEM_SAFE_FREE(pd->coba);
BKE_curvemapping_free(pd->falloff_curve); /* can be nullptr */
}
void BKE_texture_pointdensity_free(PointDensity *pd)
{
BKE_texture_pointdensity_free_data(pd);
MEM_freeN(pd);
}
/* ------------------------------------------------------------------------- */
bool BKE_texture_is_image_user(const Tex *tex)
{
switch (tex->type) {

View File

@@ -1527,24 +1527,6 @@ typedef struct NodeShaderVectTransform {
char _pad[4];
} NodeShaderVectTransform;
typedef struct NodeShaderTexPointDensity {
NodeTexBase base;
short point_source;
char _pad[2];
int particle_system;
float radius;
int resolution;
short space;
short interpolation;
short color_source;
short ob_color_source;
/** Used at runtime only by sampling RNA API. */
PointDensity pd;
int cached_resolution;
/** Vertex attribute layer for color source. */
char vertex_attribute_name[/*MAX_CUSTOMDATA_LAYER_NAME*/ 68];
} NodeShaderTexPointDensity;
typedef struct NodeShaderPrincipled {
char use_subsurface_auto_radius;
char _pad[3];
@@ -3113,30 +3095,6 @@ typedef enum CMPNodeRelativeToPixelReferenceDimension {
CMP_NODE_RELATIVE_TO_PIXEL_REFERENCE_DIMENSION_DIAGONAL = 5,
} CMPNodeRelativeToPixelReferenceDimension;
/* Point Density shader node */
enum {
SHD_POINTDENSITY_SOURCE_PSYS = 0,
SHD_POINTDENSITY_SOURCE_OBJECT = 1,
};
enum {
SHD_POINTDENSITY_SPACE_OBJECT = 0,
SHD_POINTDENSITY_SPACE_WORLD = 1,
};
enum {
SHD_POINTDENSITY_COLOR_PARTAGE = 1,
SHD_POINTDENSITY_COLOR_PARTSPEED = 2,
SHD_POINTDENSITY_COLOR_PARTVEL = 3,
};
enum {
SHD_POINTDENSITY_COLOR_VERTCOL = 0,
SHD_POINTDENSITY_COLOR_VERTWEIGHT = 1,
SHD_POINTDENSITY_COLOR_VERTNOR = 2,
};
/* Scattering phase functions */
enum {
SHD_PHASE_HENYEY_GREENSTEIN = 0,

View File

@@ -62,62 +62,6 @@ typedef struct MTex {
/** \} */
/* -------------------------------------------------------------------- */
/** \name #PointDensity
* \{ */
typedef struct PointDensity {
DNA_DEFINE_CXX_METHODS(PointDensity)
short flag;
short falloff_type;
float falloff_softness;
float radius;
short source;
char _pad0[2];
/** psys_color_source */
short color_source;
short ob_color_source;
int totpoints;
/** for 'Object' or 'Particle system' type - source object */
struct Object *object;
/** `index + 1` in ob.particle-system, non-ID pointer not allowed. */
int psys;
/** cache points in world-space, object space, ... ? */
short psys_cache_space;
/** cache points in world-space, object space, ... ? */
short ob_cache_space;
/** Vertex attribute layer for color source. */
char vertex_attribute_name[/*MAX_CUSTOMDATA_LAYER_NAME*/ 68];
char _pad1[4];
/** The acceleration tree containing points. */
void *point_tree;
/** Dynamically allocated extra for extra information, like particle age. */
float *point_data;
float noise_size;
short noise_depth;
short noise_influence;
short noise_basis;
char _pad2[6];
float noise_fac;
float speed_scale, falloff_speed_scale;
char _pad3[4];
/** For time -> color */
struct ColorBand *coba;
/** Falloff density curve. */
struct CurveMapping *falloff_curve;
} PointDensity;
/** \} */
/* -------------------------------------------------------------------- */
/** \name #Tex
* \{ */
@@ -493,61 +437,3 @@ enum {
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name #PointDensity Types
* \{ */
/** #PointDensity::source. */
enum {
TEX_PD_PSYS = 0,
TEX_PD_OBJECT = 1,
TEX_PD_FILE = 2,
};
/** #PointDensity::falloff_type. */
enum {
TEX_PD_FALLOFF_STD = 0,
TEX_PD_FALLOFF_SMOOTH = 1,
TEX_PD_FALLOFF_SOFT = 2,
TEX_PD_FALLOFF_CONSTANT = 3,
TEX_PD_FALLOFF_ROOT = 4,
TEX_PD_FALLOFF_PARTICLE_AGE = 5,
TEX_PD_FALLOFF_PARTICLE_VEL = 6,
};
/** #PointDensity::psys_cache_space. */
enum {
TEX_PD_OBJECTLOC = 0,
TEX_PD_OBJECTSPACE = 1,
TEX_PD_WORLDSPACE = 2,
};
/** #PointDensity::flag. */
enum {
TEX_PD_TURBULENCE = 1 << 0,
TEX_PD_FALLOFF_CURVE = 1 << 1,
};
/** #PointDensity::noise_influence. */
enum {
TEX_PD_NOISE_STATIC = 0,
// TEX_PD_NOISE_VEL = 1, /* Deprecated. */
// TEX_PD_NOISE_AGE = 2, /* Deprecated. */
// TEX_PD_NOISE_TIME = 3, /* Deprecated. */
};
/** #PointDensity::color_source. */
enum {
TEX_PD_COLOR_CONSTANT = 0,
/* color_source: particles */
TEX_PD_COLOR_PARTAGE = 1,
TEX_PD_COLOR_PARTSPEED = 2,
TEX_PD_COLOR_PARTVEL = 3,
/* color_source: vertices */
TEX_PD_COLOR_VERTCOL = 1,
TEX_PD_COLOR_VERTWEIGHT = 2,
TEX_PD_COLOR_VERTNOR = 3,
};
/** \} */

View File

@@ -4206,161 +4206,6 @@ static void rna_GroupOutput_is_active_output_set(PointerRNA *ptr, bool value)
}
}
static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
{
bNode *node = ptr->data_as<bNode>();
NodeShaderTexPointDensity *shader_point_density = static_cast<NodeShaderTexPointDensity *>(
node->storage);
Object *ob = reinterpret_cast<Object *>(node->id);
ParticleSystem *psys = nullptr;
if (ob && shader_point_density->particle_system) {
psys = static_cast<ParticleSystem *>(
BLI_findlink(&ob->particlesystem, shader_point_density->particle_system - 1));
}
PointerRNA value = RNA_pointer_create_discrete(&ob->id, &RNA_ParticleSystem, psys);
return value;
}
static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr,
PointerRNA value,
ReportList * /*reports*/)
{
bNode *node = ptr->data_as<bNode>();
NodeShaderTexPointDensity *shader_point_density = static_cast<NodeShaderTexPointDensity *>(
node->storage);
Object *ob = reinterpret_cast<Object *>(node->id);
if (ob && value.owner_id == &ob->id) {
shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1;
}
else {
shader_point_density->particle_system = 0;
}
}
static int point_density_particle_color_source_from_shader(
NodeShaderTexPointDensity *shader_point_density)
{
switch (shader_point_density->color_source) {
case SHD_POINTDENSITY_COLOR_PARTAGE:
return TEX_PD_COLOR_PARTAGE;
case SHD_POINTDENSITY_COLOR_PARTSPEED:
return TEX_PD_COLOR_PARTSPEED;
case SHD_POINTDENSITY_COLOR_PARTVEL:
return TEX_PD_COLOR_PARTVEL;
default:
BLI_assert_msg(0, "Unknown color source");
return TEX_PD_COLOR_CONSTANT;
}
}
static int point_density_vertex_color_source_from_shader(
NodeShaderTexPointDensity *shader_point_density)
{
switch (shader_point_density->ob_color_source) {
case SHD_POINTDENSITY_COLOR_VERTCOL:
return TEX_PD_COLOR_VERTCOL;
case SHD_POINTDENSITY_COLOR_VERTWEIGHT:
return TEX_PD_COLOR_VERTWEIGHT;
case SHD_POINTDENSITY_COLOR_VERTNOR:
return TEX_PD_COLOR_VERTNOR;
default:
BLI_assert_msg(0, "Unknown color source");
return TEX_PD_COLOR_CONSTANT;
}
}
void rna_ShaderNodePointDensity_density_cache(bNode *self, Depsgraph *depsgraph)
{
NodeShaderTexPointDensity *shader_point_density = static_cast<NodeShaderTexPointDensity *>(
self->storage);
PointDensity *pd = &shader_point_density->pd;
if (depsgraph == nullptr) {
return;
}
/* Make sure there's no cached data. */
BKE_texture_pointdensity_free_data(pd);
RE_point_density_free(pd);
/* Create PointDensity structure from node for sampling. */
BKE_texture_pointdensity_init_data(pd);
pd->object = reinterpret_cast<Object *>(self->id);
pd->radius = shader_point_density->radius;
if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
pd->source = TEX_PD_PSYS;
pd->psys = shader_point_density->particle_system;
pd->psys_cache_space = TEX_PD_OBJECTSPACE;
pd->color_source = point_density_particle_color_source_from_shader(shader_point_density);
}
else {
BLI_assert(shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_OBJECT);
pd->source = TEX_PD_OBJECT;
pd->ob_cache_space = TEX_PD_OBJECTSPACE;
pd->ob_color_source = point_density_vertex_color_source_from_shader(shader_point_density);
STRNCPY(pd->vertex_attribute_name, shader_point_density->vertex_attribute_name);
}
/* Store resolution, so it can be changed in the UI. */
shader_point_density->cached_resolution = shader_point_density->resolution;
/* Single-threaded sampling of the voxel domain. */
RE_point_density_cache(depsgraph, pd);
}
void rna_ShaderNodePointDensity_density_calc(bNode *self,
Depsgraph *depsgraph,
float **values,
int *values_num)
{
NodeShaderTexPointDensity *shader_point_density = static_cast<NodeShaderTexPointDensity *>(
self->storage);
PointDensity *pd = &shader_point_density->pd;
const int resolution = shader_point_density->cached_resolution;
if (depsgraph == nullptr) {
*values_num = 0;
return;
}
/* TODO(sergey): Will likely overflow, but how to pass size_t via RNA? */
*values_num = 4 * resolution * resolution * resolution;
if (*values == nullptr) {
*values = MEM_malloc_arrayN<float>(size_t(*values_num), "point density dynamic array");
}
/* Single-threaded sampling of the voxel domain. */
RE_point_density_sample(depsgraph, pd, resolution, *values);
/* We're done, time to clean up. */
BKE_texture_pointdensity_free_data(pd);
*pd = blender::dna::shallow_zero_initialize();
shader_point_density->cached_resolution = 0.0f;
}
void rna_ShaderNodePointDensity_density_minmax(bNode *self,
Depsgraph *depsgraph,
float r_min[3],
float r_max[3])
{
NodeShaderTexPointDensity *shader_point_density = static_cast<NodeShaderTexPointDensity *>(
self->storage);
PointDensity *pd = &shader_point_density->pd;
if (depsgraph == nullptr) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
RE_point_density_minmax(depsgraph, pd, r_min, r_max);
}
static int rna_NodeConvertColorSpace_from_color_space_get(PointerRNA *ptr)
{
bNode *node = ptr->data_as<bNode>();
@@ -5919,166 +5764,6 @@ static void def_sh_tex_wireframe(BlenderRNA * /*brna*/, StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_sh_tex_pointdensity(BlenderRNA * /*brna*/, StructRNA *srna)
{
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
static const EnumPropertyItem point_source_items[] = {
{SHD_POINTDENSITY_SOURCE_PSYS,
"PARTICLE_SYSTEM",
0,
"Particle System",
"Generate point density from a particle system"},
{SHD_POINTDENSITY_SOURCE_OBJECT,
"OBJECT",
0,
"Object Vertices",
"Generate point density from an object's vertices"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem prop_interpolation_items[] = {
{SHD_INTERP_CLOSEST, "Closest", 0, "Closest", "No interpolation (sample closest texel)"},
{SHD_INTERP_LINEAR, "Linear", 0, "Linear", "Linear interpolation"},
{SHD_INTERP_CUBIC, "Cubic", 0, "Cubic", "Cubic interpolation"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem space_items[] = {
{SHD_POINTDENSITY_SPACE_OBJECT, "OBJECT", 0, "Object Space", ""},
{SHD_POINTDENSITY_SPACE_WORLD, "WORLD", 0, "World Space", ""},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem particle_color_source_items[] = {
{SHD_POINTDENSITY_COLOR_PARTAGE,
"PARTICLE_AGE",
0,
"Particle Age",
"Lifetime mapped as 0.0 to 1.0 intensity"},
{SHD_POINTDENSITY_COLOR_PARTSPEED,
"PARTICLE_SPEED",
0,
"Particle Speed",
"Particle speed (absolute magnitude of velocity) mapped as 0.0 to 1.0 intensity"},
{SHD_POINTDENSITY_COLOR_PARTVEL,
"PARTICLE_VELOCITY",
0,
"Particle Velocity",
"XYZ velocity mapped to RGB colors"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem vertex_color_source_items[] = {
{SHD_POINTDENSITY_COLOR_VERTCOL, "VERTEX_COLOR", 0, "Vertex Color", "Vertex color layer"},
{SHD_POINTDENSITY_COLOR_VERTWEIGHT,
"VERTEX_WEIGHT",
0,
"Vertex Weight",
"Vertex group weight"},
{SHD_POINTDENSITY_COLOR_VERTNOR,
"VERTEX_NORMAL",
0,
"Vertex Normal",
"XYZ normal vector mapped to RGB colors"},
{0, nullptr, 0, nullptr, nullptr},
};
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, nullptr, "id");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object", "Object to take point data from");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "NodeShaderTexPointDensity", "storage");
prop = RNA_def_property(srna, "point_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, point_source_items);
RNA_def_property_ui_text(prop, "Point Source", "Point data to use as renderable point density");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Particle System", "Particle System to render as points");
RNA_def_property_struct_type(prop, "ParticleSystem");
RNA_def_property_pointer_funcs(prop,
"rna_ShaderNodePointDensity_psys_get",
"rna_ShaderNodePointDensity_psys_set",
nullptr,
nullptr);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 32768);
RNA_def_property_ui_text(
prop, "Resolution", "Resolution used by the texture holding the point density");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, nullptr, "radius");
RNA_def_property_range(prop, 0.001, FLT_MAX);
RNA_def_property_ui_text(
prop, "Radius", "Radius from the shaded sample to look for points within");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, space_items);
RNA_def_property_ui_text(prop, "Space", "Coordinate system to calculate voxels in");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_interpolation_items);
RNA_def_property_ui_text(prop, "Interpolation", "Texture interpolation");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "particle_color_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "color_source");
RNA_def_property_enum_items(prop, particle_color_source_items);
RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "vertex_color_source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "ob_color_source");
RNA_def_property_enum_items(prop, vertex_color_source_items);
RNA_def_property_ui_text(prop, "Color Source", "Data to derive color results from");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "vertex_attribute_name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Vertex Attribute Name", "Vertex attribute to use for color");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
func = RNA_def_function(srna, "cache_point_density", "rna_ShaderNodePointDensity_density_cache");
RNA_def_function_ui_description(func, "Cache point density data for later calculation");
RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
/* TODO: See how array size of 0 works, this shouldn't be used. */
parm = RNA_def_float_array(func, "rgba_values", 1, nullptr, 0, 0, "", "RGBA Values", 0, 0);
RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0));
RNA_def_function_output(func, parm);
func = RNA_def_function(
srna, "calc_point_density_minmax", "rna_ShaderNodePointDensity_density_minmax");
RNA_def_function_ui_description(func, "Calculate point density");
RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
parm = RNA_def_property(func, "min", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(parm, 3);
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
RNA_def_function_output(func, parm);
parm = RNA_def_property(func, "max", PROP_FLOAT, PROP_COORDS);
RNA_def_property_array(parm, 3);
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, ParameterFlag(0));
RNA_def_function_output(func, parm);
}
static void def_metallic(BlenderRNA * /*brna*/, StructRNA *srna)
{
PropertyRNA *prop;
@@ -10937,7 +10622,6 @@ static void rna_def_nodes(BlenderRNA *brna)
define("ShaderNode", "ShaderNodeTexImage", def_sh_tex_image);
define("ShaderNode", "ShaderNodeTexMagic", def_sh_tex_magic);
define("ShaderNode", "ShaderNodeTexNoise", def_sh_tex_noise);
define("ShaderNode", "ShaderNodeTexPointDensity", def_sh_tex_pointdensity);
define("ShaderNode", "ShaderNodeTexSky", def_sh_tex_sky);
define("ShaderNode", "ShaderNodeTexVoronoi", def_sh_tex_voronoi);
define("ShaderNode", "ShaderNodeTexWave", def_sh_tex_wave);

View File

@@ -93,7 +93,6 @@ set(SRC
nodes/node_shader_tex_image.cc
nodes/node_shader_tex_magic.cc
nodes/node_shader_tex_noise.cc
nodes/node_shader_tex_pointdensity.cc
nodes/node_shader_tex_sky.cc
nodes/node_shader_tex_voronoi.cc
nodes/node_shader_tex_wave.cc

View File

@@ -92,7 +92,6 @@ void register_shader_nodes()
register_node_type_sh_tex_image();
register_node_type_sh_tex_magic();
register_node_type_sh_tex_noise();
register_node_type_sh_tex_pointdensity();
register_node_type_sh_tex_sky();
register_node_type_sh_tex_voronoi();
register_node_type_sh_tex_wave();

View File

@@ -91,7 +91,6 @@ void register_node_type_sh_tex_ies();
void register_node_type_sh_tex_image();
void register_node_type_sh_tex_magic();
void register_node_type_sh_tex_noise();
void register_node_type_sh_tex_pointdensity();
void register_node_type_sh_tex_sky();
void register_node_type_sh_tex_voronoi();
void register_node_type_sh_tex_wave();

View File

@@ -1,127 +0,0 @@
/* SPDX-FileCopyrightText: 2015 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_shader_util.hh"
#include "BKE_texture.h"
#include "RE_texture.h"
#include "RNA_access.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
namespace blender::nodes::node_shader_tex_pointdensity_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Vector>("Vector").hide_value();
b.add_output<decl::Color>("Color");
b.add_output<decl::Float>("Density");
}
static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
bNode *node = (bNode *)ptr->data;
NodeShaderTexPointDensity *shader_point_density = (NodeShaderTexPointDensity *)node->storage;
Object *ob = (Object *)node->id;
PointerRNA ob_ptr = RNA_id_pointer_create((ID *)ob);
PointerRNA obdata_ptr = RNA_id_pointer_create(ob ? (ID *)ob->data : nullptr);
layout->prop(ptr, "point_source", UI_ITEM_R_EXPAND, std::nullopt, ICON_NONE);
layout->prop(ptr, "object", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
PointerRNA dataptr = RNA_id_pointer_create((ID *)node->id);
uiItemPointerR(
layout, ptr, "particle_system", &dataptr, "particle_systems", std::nullopt, ICON_NONE);
}
layout->prop(ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
layout->prop(ptr, "radius", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
layout->prop(ptr, "interpolation", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
layout->prop(ptr, "resolution", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
layout->prop(
ptr, "particle_color_source", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
}
else {
layout->prop(ptr, "vertex_color_source", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) {
if (ob_ptr.data) {
uiItemPointerR(
layout, ptr, "vertex_attribute_name", &ob_ptr, "vertex_groups", "", ICON_NONE);
}
}
if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTCOL) {
if (obdata_ptr.data) {
uiItemPointerR(layout,
ptr,
"vertex_attribute_name",
&obdata_ptr,
"color_attributes",
"",
ICON_GROUP_VCOL);
}
}
}
}
static void node_shader_init_tex_pointdensity(bNodeTree * /*ntree*/, bNode *node)
{
NodeShaderTexPointDensity *point_density = MEM_callocN<NodeShaderTexPointDensity>(__func__);
point_density->resolution = 100;
point_density->radius = 0.3f;
point_density->space = SHD_POINTDENSITY_SPACE_OBJECT;
point_density->color_source = SHD_POINTDENSITY_COLOR_PARTAGE;
node->storage = point_density;
}
static void node_shader_free_tex_pointdensity(bNode *node)
{
NodeShaderTexPointDensity *point_density = (NodeShaderTexPointDensity *)node->storage;
PointDensity *pd = &point_density->pd;
RE_point_density_free(pd);
BKE_texture_pointdensity_free_data(pd);
*pd = dna::shallow_zero_initialize();
MEM_freeN(point_density);
}
static void node_shader_copy_tex_pointdensity(bNodeTree * /*dst_ntree*/,
bNode *dest_node,
const bNode *src_node)
{
dest_node->storage = MEM_dupallocN(src_node->storage);
NodeShaderTexPointDensity *point_density = (NodeShaderTexPointDensity *)dest_node->storage;
PointDensity *pd = &point_density->pd;
*pd = dna::shallow_zero_initialize();
}
} // namespace blender::nodes::node_shader_tex_pointdensity_cc
/* node type definition */
void register_node_type_sh_tex_pointdensity()
{
namespace file_ns = blender::nodes::node_shader_tex_pointdensity_cc;
static blender::bke::bNodeType ntype;
sh_node_type_base(&ntype, "ShaderNodeTexPointDensity", SH_NODE_TEX_POINTDENSITY);
ntype.ui_name = "Point Density";
ntype.ui_description =
"Generate a volumetric point for each particle or vertex of another object";
ntype.enum_name_legacy = "TEX_POINTDENSITY";
ntype.nclass = NODE_CLASS_TEXTURE;
ntype.declare = file_ns::node_declare;
ntype.draw_buttons = file_ns::node_shader_buts_tex_pointdensity;
ntype.initfunc = file_ns::node_shader_init_tex_pointdensity;
blender::bke::node_type_storage(ntype,
"NodeShaderTexPointDensity",
file_ns::node_shader_free_tex_pointdensity,
file_ns::node_shader_copy_tex_pointdensity);
blender::bke::node_register_type(ntype);
}

View File

@@ -31,7 +31,6 @@ set(SRC
intern/render_types.cc
intern/texture_image.cc
intern/texture_margin.cc
intern/texture_pointdensity.cc
intern/texture_procedural.cc
intern/tile_highlight.cc
intern/zbuf.cc

View File

@@ -50,30 +50,6 @@ void RE_texture_rng_exit(void);
void ibuf_sample(struct ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]);
/* `texture_pointdensity.cc` */
struct PointDensity;
void RE_point_density_cache(struct Depsgraph *depsgraph, struct PointDensity *pd);
void RE_point_density_minmax(struct Depsgraph *depsgraph,
struct PointDensity *pd,
float r_min[3],
float r_max[3]);
/**
* \note Requires #RE_point_density_cache() to be called first.
* \note Frees point density structure after sampling.
*/
void RE_point_density_sample(struct Depsgraph *depsgraph,
struct PointDensity *pd,
int resolution,
float *values);
void RE_point_density_free(struct PointDensity *pd);
void RE_point_density_fix_linking(void);
/* `texture_procedural.cc` */
/**

View File

@@ -939,8 +939,6 @@ void RE_InitState(Render *re,
BLI_rw_mutex_unlock(&re->resultmutex);
RE_init_threadcount(re);
RE_point_density_fix_linking();
}
void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr))

View File

@@ -1,955 +0,0 @@
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup render
*/
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include "MEM_guardedalloc.h"
#include "BLI_color.hh"
#include "BLI_kdopbvh.hh"
#include "BLI_listbase.h"
#include "BLI_math_color.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_noise.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "BKE_attribute.hh"
#include "BKE_colorband.hh"
#include "BKE_colortools.hh"
#include "BKE_customdata.hh"
#include "BKE_deform.hh"
#include "BKE_mesh.hh"
#include "BKE_object.hh"
#include "BKE_particle.h"
#include "BKE_scene.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "RE_texture.h"
static blender::Mutex sample_mutex;
enum {
POINT_DATA_VEL = 1 << 0,
POINT_DATA_LIFE = 1 << 1,
POINT_DATA_COLOR = 1 << 2,
};
static int point_data_used(PointDensity *pd)
{
int pd_bitflag = 0;
if (pd->source == TEX_PD_PSYS) {
if ((pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) ||
(pd->color_source == TEX_PD_COLOR_PARTVEL) || (pd->color_source == TEX_PD_COLOR_PARTSPEED))
{
pd_bitflag |= POINT_DATA_VEL;
}
if ((pd->color_source == TEX_PD_COLOR_PARTAGE) ||
(pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE))
{
pd_bitflag |= POINT_DATA_LIFE;
}
}
else if (pd->source == TEX_PD_OBJECT) {
if (ELEM(pd->ob_color_source,
TEX_PD_COLOR_VERTCOL,
TEX_PD_COLOR_VERTWEIGHT,
TEX_PD_COLOR_VERTNOR))
{
pd_bitflag |= POINT_DATA_COLOR;
}
}
return pd_bitflag;
}
static void point_data_pointers(PointDensity *pd,
float **r_data_velocity,
float **r_data_life,
float **r_data_color)
{
const int data_used = point_data_used(pd);
const int totpoint = pd->totpoints;
float *data = pd->point_data;
int offset = 0;
if (data_used & POINT_DATA_VEL) {
if (r_data_velocity) {
*r_data_velocity = data + offset;
}
offset += 3 * totpoint;
}
else {
if (r_data_velocity) {
*r_data_velocity = nullptr;
}
}
if (data_used & POINT_DATA_LIFE) {
if (r_data_life) {
*r_data_life = data + offset;
}
offset += totpoint;
}
else {
if (r_data_life) {
*r_data_life = nullptr;
}
}
if (data_used & POINT_DATA_COLOR) {
if (r_data_color) {
*r_data_color = data + offset;
}
offset += 3 * totpoint;
}
else {
if (r_data_color) {
*r_data_color = nullptr;
}
}
}
/* additional data stored alongside the point density BVH,
* accessible by point index number to retrieve other information
* such as particle velocity or lifetime */
static void alloc_point_data(PointDensity *pd)
{
const int totpoints = pd->totpoints;
int data_used = point_data_used(pd);
int data_size = 0;
if (data_used & POINT_DATA_VEL) {
/* store 3 channels of velocity data */
data_size += 3;
}
if (data_used & POINT_DATA_LIFE) {
/* store 1 channel of lifetime data */
data_size += 1;
}
if (data_used & POINT_DATA_COLOR) {
/* store 3 channels of RGB data */
data_size += 3;
}
if (data_size) {
pd->point_data = MEM_calloc_arrayN<float>(size_t(data_size) * size_t(totpoints),
"particle point data");
}
}
static void pointdensity_cache_psys(
Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
{
ParticleKey state;
ParticleCacheKey *cache;
ParticleSimulationData sim = {nullptr};
ParticleData *pa = nullptr;
float cfra = BKE_scene_ctime_get(scene);
int i;
// int childexists = 0; /* UNUSED */
int total_particles;
int data_used;
float *data_vel, *data_life;
float partco[3];
const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
data_used = point_data_used(pd);
if (!psys_check_enabled(ob, psys, use_render_params)) {
return;
}
sim.depsgraph = depsgraph;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
sim.psmd = psys_get_modifier(ob, psys);
/* in case ob->world_to_object isn't up-to-date */
invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
total_particles = psys->totpart + psys->totchild;
psys_sim_data_init(&sim);
pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
pd->totpoints = total_particles;
alloc_point_data(pd);
point_data_pointers(pd, &data_vel, &data_life, nullptr);
#if 0 /* UNUSED */
if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) {
childexists = 1;
}
#endif
for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
if (psys->part->type == PART_HAIR) {
/* hair particles */
if (i < psys->totpart && psys->pathcache) {
cache = psys->pathcache[i];
}
else if (i >= psys->totpart && psys->childcache) {
cache = psys->childcache[i - psys->totpart];
}
else {
continue;
}
cache += cache->segments; /* use endpoint */
copy_v3_v3(state.co, cache->co);
zero_v3(state.vel);
state.time = 0.0f;
}
else {
/* emitter particles */
state.time = cfra;
if (!psys_get_particle_state(&sim, i, &state, false)) {
continue;
}
if (data_used & POINT_DATA_LIFE) {
if (i < psys->totpart) {
state.time = (cfra - pa->time) / pa->lifetime;
}
else {
ChildParticle *cpa = (psys->child + i) - psys->totpart;
float pa_birthtime, pa_dietime;
state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
}
}
}
copy_v3_v3(partco, state.co);
if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) {
mul_m4_v3(ob->world_to_object().ptr(), partco);
}
else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
sub_v3_v3(partco, ob->loc);
}
else {
/* TEX_PD_WORLDSPACE */
}
BLI_bvhtree_insert(static_cast<BVHTree *>(pd->point_tree), i, partco, 1);
if (data_vel) {
data_vel[i * 3 + 0] = state.vel[0];
data_vel[i * 3 + 1] = state.vel[1];
data_vel[i * 3 + 2] = state.vel[2];
}
if (data_life) {
data_life[i] = state.time;
}
}
BLI_bvhtree_balance(static_cast<BVHTree *>(pd->point_tree));
psys_sim_data_free(&sim);
}
static void pointdensity_cache_vertex_color(PointDensity *pd,
Object * /*ob*/,
Mesh *mesh,
float *data_color)
{
using namespace blender;
const blender::Span<int> corner_verts = mesh->corner_verts();
const int totloop = mesh->corners_num;
int i;
BLI_assert(data_color);
const bke::AttributeAccessor attributes = mesh->attributes();
const StringRef name = attributes.contains(pd->vertex_attribute_name) ?
pd->vertex_attribute_name :
(mesh->active_color_attribute ? mesh->active_color_attribute : "");
const VArray mcol = *attributes.lookup<ColorGeometry4b>(name, bke::AttrDomain::Corner);
if (!mcol) {
return;
}
/* Stores the number of MLoops using the same vertex, so we can normalize colors. */
int *mcorners = MEM_calloc_arrayN<int>(pd->totpoints, "point density corner count");
for (i = 0; i < totloop; i++) {
int v = corner_verts[i];
if (mcorners[v] == 0) {
rgb_uchar_to_float(&data_color[v * 3], mcol[i]);
}
else {
float col[3];
rgb_uchar_to_float(col, mcol[i]);
add_v3_v3(&data_color[v * 3], col);
}
++mcorners[v];
}
/* Normalize colors by averaging over mcorners.
* All the corners share the same vertex, ie. occupy the same point in space.
*/
for (i = 0; i < pd->totpoints; i++) {
if (mcorners[i] > 0) {
mul_v3_fl(&data_color[i * 3], 1.0f / mcorners[i]);
}
}
MEM_freeN(mcorners);
}
static void pointdensity_cache_vertex_weight(PointDensity *pd,
Object *ob,
Mesh *mesh,
float *data_color)
{
const int totvert = mesh->verts_num;
int mdef_index;
int i;
BLI_assert(data_color);
const MDeformVert *mdef = static_cast<const MDeformVert *>(
CustomData_get_layer(&mesh->vert_data, CD_MDEFORMVERT));
if (!mdef) {
return;
}
mdef_index = BKE_id_defgroup_name_index(&mesh->id, pd->vertex_attribute_name);
if (mdef_index < 0) {
mdef_index = BKE_object_defgroup_active_index_get(ob) - 1;
}
if (mdef_index < 0) {
return;
}
const MDeformVert *dv;
for (i = 0, dv = mdef; i < totvert; i++, dv++, data_color += 3) {
MDeformWeight *dw;
int j;
for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
if (dw->def_nr == mdef_index) {
copy_v3_fl(data_color, dw->weight);
break;
}
}
}
}
static void pointdensity_cache_vertex_normal(Mesh *mesh, float *data_color)
{
BLI_assert(data_color);
const blender::Span<blender::float3> normals = mesh->vert_normals();
memcpy(data_color, normals.data(), sizeof(float[3]) * mesh->verts_num);
}
static void pointdensity_cache_object(PointDensity *pd, Object *ob)
{
float *data_color;
int i;
Mesh *mesh = static_cast<Mesh *>(ob->data);
#if 0 /* UNUSED */
CustomData_MeshMasks mask = CD_MASK_BAREMESH;
mask.fmask |= CD_MASK_MTFACE | CD_MASK_MCOL;
switch (pd->ob_color_source) {
case TEX_PD_COLOR_VERTCOL:
mask.lmask |= CD_MASK_PROP_BYTE_COLOR;
break;
case TEX_PD_COLOR_VERTWEIGHT:
mask.vmask |= CD_MASK_MDEFORMVERT;
break;
}
#endif
const blender::Span<blender::float3> positions = mesh->vert_positions(); /* local object space */
pd->totpoints = mesh->verts_num;
if (pd->totpoints == 0) {
return;
}
pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
alloc_point_data(pd);
point_data_pointers(pd, nullptr, nullptr, &data_color);
for (i = 0; i < pd->totpoints; i++) {
float co[3];
copy_v3_v3(co, positions[i]);
switch (pd->ob_cache_space) {
case TEX_PD_OBJECTSPACE:
break;
case TEX_PD_OBJECTLOC:
mul_m4_v3(ob->object_to_world().ptr(), co);
sub_v3_v3(co, ob->loc);
break;
case TEX_PD_WORLDSPACE:
default:
mul_m4_v3(ob->object_to_world().ptr(), co);
break;
}
BLI_bvhtree_insert(static_cast<BVHTree *>(pd->point_tree), i, co, 1);
}
switch (pd->ob_color_source) {
case TEX_PD_COLOR_VERTCOL:
pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
break;
case TEX_PD_COLOR_VERTWEIGHT:
pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
break;
case TEX_PD_COLOR_VERTNOR:
pointdensity_cache_vertex_normal(mesh, data_color);
break;
}
BLI_bvhtree_balance(static_cast<BVHTree *>(pd->point_tree));
}
static void cache_pointdensity(Depsgraph *depsgraph, Scene *scene, PointDensity *pd)
{
if (pd == nullptr) {
return;
}
if (pd->point_tree) {
BLI_bvhtree_free(static_cast<BVHTree *>(pd->point_tree));
pd->point_tree = nullptr;
}
if (pd->source == TEX_PD_PSYS) {
Object *ob = pd->object;
ParticleSystem *psys;
if (!ob || !pd->psys) {
return;
}
psys = static_cast<ParticleSystem *>(BLI_findlink(&ob->particlesystem, pd->psys - 1));
if (!psys) {
return;
}
pointdensity_cache_psys(depsgraph, scene, pd, ob, psys);
}
else if (pd->source == TEX_PD_OBJECT) {
Object *ob = pd->object;
if (ob && ob->type == OB_MESH) {
pointdensity_cache_object(pd, ob);
}
}
}
static void free_pointdensity(PointDensity *pd)
{
if (pd == nullptr) {
return;
}
if (pd->point_tree) {
BLI_bvhtree_free(static_cast<BVHTree *>(pd->point_tree));
pd->point_tree = nullptr;
}
MEM_SAFE_FREE(pd->point_data);
pd->totpoints = 0;
}
struct PointDensityRangeData {
float *density;
float squared_radius;
float *point_data_life;
float *point_data_velocity;
float *point_data_color;
float *vec;
float *col;
float softness;
short falloff_type;
short noise_influence;
float *age;
CurveMapping *density_curve;
float velscale;
};
static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
{
const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
float density = 0.0f;
switch (pdr->falloff_type) {
case TEX_PD_FALLOFF_STD:
density = dist;
break;
case TEX_PD_FALLOFF_SMOOTH:
density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
break;
case TEX_PD_FALLOFF_SOFT:
density = pow(dist, pdr->softness);
break;
case TEX_PD_FALLOFF_CONSTANT:
density = pdr->squared_radius;
break;
case TEX_PD_FALLOFF_ROOT:
density = sqrtf(dist);
break;
case TEX_PD_FALLOFF_PARTICLE_AGE:
if (pdr->point_data_life) {
density = dist * std::min(pdr->point_data_life[index], 1.0f);
}
else {
density = dist;
}
break;
case TEX_PD_FALLOFF_PARTICLE_VEL:
if (pdr->point_data_velocity) {
density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
}
else {
density = dist;
}
break;
}
if (pdr->density_curve && dist != 0.0f) {
BKE_curvemapping_init(pdr->density_curve);
density = BKE_curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
}
return density;
}
static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
{
PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
float density = 0.0f;
UNUSED_VARS(co);
if (pdr->point_data_velocity) {
pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0]; // * density;
pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1]; // * density;
pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2]; // * density;
}
if (pdr->point_data_life) {
*pdr->age += pdr->point_data_life[index]; // * density;
}
if (pdr->point_data_color) {
add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]); // * density;
}
density = density_falloff(pdr, index, squared_dist);
*pdr->density += density;
}
static void init_pointdensityrangedata(PointDensity *pd,
PointDensityRangeData *pdr,
float *density,
float *vec,
float *age,
float *col,
CurveMapping *density_curve,
float velscale)
{
pdr->squared_radius = pd->radius * pd->radius;
pdr->density = density;
pdr->falloff_type = pd->falloff_type;
pdr->vec = vec;
pdr->age = age;
pdr->col = col;
pdr->softness = pd->falloff_softness;
pdr->noise_influence = pd->noise_influence;
point_data_pointers(
pd, &pdr->point_data_velocity, &pdr->point_data_life, &pdr->point_data_color);
pdr->density_curve = density_curve;
pdr->velscale = velscale;
}
static int pointdensity(PointDensity *pd,
const float texvec[3],
TexResult *texres,
float r_vec[3],
float *r_age,
float r_col[3])
{
int retval = TEX_INT;
PointDensityRangeData pdr;
float density = 0.0f, age = 0.0f;
float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
float turb, noise_fac;
int num = 0;
texres->tin = 0.0f;
init_pointdensityrangedata(pd,
&pdr,
&density,
vec,
&age,
col,
(pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : nullptr),
pd->falloff_speed_scale * 0.001f);
noise_fac = pd->noise_fac * 0.5f; /* better default */
copy_v3_v3(co, texvec);
if (point_data_used(pd)) {
/* does a BVH lookup to find accumulated density and additional point data *
* stores particle velocity vector in 'vec', and particle lifetime in 'time' */
num = BLI_bvhtree_range_query(
static_cast<const BVHTree *>(pd->point_tree), co, pd->radius, accum_density, &pdr);
if (num > 0) {
age /= num;
mul_v3_fl(vec, 1.0f / num);
mul_v3_fl(col, 1.0f / num);
}
/* reset */
density = 0.0f;
zero_v3(vec);
zero_v3(col);
}
if (pd->flag & TEX_PD_TURBULENCE) {
turb = BLI_noise_generic_turbulence(pd->noise_size,
texvec[0] + vec[0],
texvec[1] + vec[1],
texvec[2] + vec[2],
pd->noise_depth,
false,
pd->noise_basis);
turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
/* now we have an offset coordinate to use for the density lookup */
co[0] = texvec[0] + noise_fac * turb;
co[1] = texvec[1] + noise_fac * turb;
co[2] = texvec[2] + noise_fac * turb;
}
/* BVH query with the potentially perturbed coordinates */
num = BLI_bvhtree_range_query(
static_cast<const BVHTree *>(pd->point_tree), co, pd->radius, accum_density, &pdr);
if (num > 0) {
age /= num;
mul_v3_fl(vec, 1.0f / num);
mul_v3_fl(col, 1.0f / num);
}
texres->tin = density;
if (r_age != nullptr) {
*r_age = age;
}
if (r_vec != nullptr) {
copy_v3_v3(r_vec, vec);
}
if (r_col != nullptr) {
copy_v3_v3(r_col, col);
}
return retval;
}
static void pointdensity_color(
PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
{
copy_v4_fl(texres->trgba, 1.0f);
if (pd->source == TEX_PD_PSYS) {
float rgba[4];
switch (pd->color_source) {
case TEX_PD_COLOR_PARTAGE:
if (pd->coba) {
if (BKE_colorband_evaluate(pd->coba, age, rgba)) {
texres->talpha = true;
copy_v3_v3(texres->trgba, rgba);
texres->tin *= rgba[3];
texres->trgba[3] = texres->tin;
}
}
break;
case TEX_PD_COLOR_PARTSPEED: {
float speed = len_v3(vec) * pd->speed_scale;
if (pd->coba) {
if (BKE_colorband_evaluate(pd->coba, speed, rgba)) {
texres->talpha = true;
copy_v3_v3(texres->trgba, rgba);
texres->tin *= rgba[3];
texres->trgba[3] = texres->tin;
}
}
break;
}
case TEX_PD_COLOR_PARTVEL:
texres->talpha = true;
mul_v3_v3fl(texres->trgba, vec, pd->speed_scale);
texres->trgba[3] = texres->tin;
break;
case TEX_PD_COLOR_CONSTANT:
default:
break;
}
}
else {
float rgba[4];
switch (pd->ob_color_source) {
case TEX_PD_COLOR_VERTCOL:
texres->talpha = true;
copy_v3_v3(texres->trgba, col);
texres->trgba[3] = texres->tin;
break;
case TEX_PD_COLOR_VERTWEIGHT:
texres->talpha = true;
if (pd->coba && BKE_colorband_evaluate(pd->coba, col[0], rgba)) {
copy_v3_v3(texres->trgba, rgba);
texres->tin *= rgba[3];
}
else {
copy_v3_v3(texres->trgba, col);
}
texres->trgba[3] = texres->tin;
break;
case TEX_PD_COLOR_VERTNOR:
texres->talpha = true;
copy_v3_v3(texres->trgba, col);
texres->trgba[3] = texres->tin;
break;
case TEX_PD_COLOR_CONSTANT:
default:
break;
}
}
}
static void sample_dummy_point_density(int resolution, float *values)
{
memset(values, 0, sizeof(float[4]) * resolution * resolution * resolution);
}
static void particle_system_minmax(Depsgraph *depsgraph,
Scene *scene,
Object *object,
ParticleSystem *psys,
float radius,
float min[3],
float max[3])
{
const float size[3] = {radius, radius, radius};
const float cfra = BKE_scene_ctime_get(scene);
ParticleSettings *part = psys->part;
ParticleSimulationData sim = {nullptr};
ParticleData *pa = nullptr;
int i;
int total_particles;
float mat[4][4], imat[4][4];
INIT_MINMAX(min, max);
if (part->type == PART_HAIR) {
/* TODO(sergey): Not supported currently. */
return;
}
unit_m4(mat);
sim.depsgraph = depsgraph;
sim.scene = scene;
sim.ob = object;
sim.psys = psys;
sim.psmd = psys_get_modifier(object, psys);
invert_m4_m4(imat, object->object_to_world().ptr());
total_particles = psys->totpart + psys->totchild;
psys_sim_data_init(&sim);
for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
float co_object[3], co_min[3], co_max[3];
ParticleKey state;
state.time = cfra;
if (!psys_get_particle_state(&sim, i, &state, false)) {
continue;
}
mul_v3_m4v3(co_object, imat, state.co);
sub_v3_v3v3(co_min, co_object, size);
add_v3_v3v3(co_max, co_object, size);
minmax_v3v3_v3(min, max, co_min);
minmax_v3v3_v3(min, max, co_max);
}
psys_sim_data_free(&sim);
}
void RE_point_density_cache(Depsgraph *depsgraph, PointDensity *pd)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
/* Same matrices/resolution as dupli_render_particle_set(). */
std::scoped_lock lock(sample_mutex);
cache_pointdensity(depsgraph, scene, pd);
}
void RE_point_density_minmax(Depsgraph *depsgraph,
PointDensity *pd,
float r_min[3],
float r_max[3])
{
using namespace blender;
Scene *scene = DEG_get_evaluated_scene(depsgraph);
Object *object = pd->object;
if (object == nullptr) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
if (pd->source == TEX_PD_PSYS) {
ParticleSystem *psys;
if (pd->psys == 0) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
psys = static_cast<ParticleSystem *>(BLI_findlink(&object->particlesystem, pd->psys - 1));
if (psys == nullptr) {
zero_v3(r_min);
zero_v3(r_max);
return;
}
particle_system_minmax(depsgraph, scene, object, psys, pd->radius, r_min, r_max);
}
else {
const float radius[3] = {pd->radius, pd->radius, pd->radius};
if (const std::optional<Bounds<float3>> bb = BKE_object_boundbox_get(object)) {
copy_v3_v3(r_min, bb->min);
copy_v3_v3(r_max, bb->max);
/* Adjust texture space to include density points on the boundaries. */
sub_v3_v3(r_min, radius);
add_v3_v3(r_max, radius);
}
else {
zero_v3(r_min);
zero_v3(r_max);
}
}
}
struct SampleCallbackData {
PointDensity *pd;
int resolution;
float *min, *dim;
float *values;
};
static void point_density_sample_func(void *__restrict data_v,
const int iter,
const TaskParallelTLS *__restrict /*tls*/)
{
SampleCallbackData *data = (SampleCallbackData *)data_v;
const int resolution = data->resolution;
const int resolution2 = resolution * resolution;
const float *min = data->min, *dim = data->dim;
PointDensity *pd = data->pd;
float *values = data->values;
if (!pd || !pd->point_tree) {
return;
}
size_t z = size_t(iter);
for (size_t y = 0; y < resolution; y++) {
for (size_t x = 0; x < resolution; x++) {
size_t index = z * resolution2 + y * resolution + x;
float texvec[3];
float age, vec[3], col[3];
TexResult texres;
copy_v3_v3(texvec, min);
texvec[0] += dim[0] * float(x) / float(resolution);
texvec[1] += dim[1] * float(y) / float(resolution);
texvec[2] += dim[2] * float(z) / float(resolution);
pointdensity(pd, texvec, &texres, vec, &age, col);
pointdensity_color(pd, &texres, age, vec, col);
copy_v3_v3(&values[index * 4 + 0], texres.trgba);
values[index * 4 + 3] = texres.tin;
}
}
}
void RE_point_density_sample(Depsgraph *depsgraph,
PointDensity *pd,
const int resolution,
float *values)
{
Object *object = pd->object;
float min[3], max[3], dim[3];
/* TODO(sergey): Implement some sort of assert() that point density
* was cached already.
*/
if (object == nullptr) {
sample_dummy_point_density(resolution, values);
return;
}
{
std::scoped_lock lock(sample_mutex);
RE_point_density_minmax(depsgraph, pd, min, max);
}
sub_v3_v3v3(dim, max, min);
if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
sample_dummy_point_density(resolution, values);
return;
}
SampleCallbackData data;
data.pd = pd;
data.resolution = resolution;
data.min = min;
data.dim = dim;
data.values = values;
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = (resolution > 32);
BLI_task_parallel_range(0, resolution, &data, point_density_sample_func, &settings);
free_pointdensity(pd);
}
void RE_point_density_free(PointDensity *pd)
{
free_pointdensity(pd);
}
void RE_point_density_fix_linking() {}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -79,8 +79,6 @@ BLOCKLIST_OPTIX_OSL_ALL = BLOCKLIST_OPTIX_OSL_LIMITED + [
'bake_bevel.blend',
'bevel.blend',
'principled_bsdf_bevel_emission_137420.blend',
# The 3D texture doesn't have the right mappings
'point_density_.*_object.blend',
# Dicing tests use wireframe node which doesn't appear to be supported with OptiX OSL
'dicing_camera.blend',
'offscreen_dicing.blend',