Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2015-07-18 23:36:09 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2015-07-18 23:49:10 +0300
commit9b406162490d9ee93e9786350432cdc1563b7bf6 (patch)
treecf573ef92132c45c7daac221296bfc76bf327628
parent7d10798af22f683a8f55a8c361ad5676bd4160d2 (diff)
Cycles: Point density texture support
This commit implements point density texture for Cycles shading nodes. It's done via creating voxel texture at shader compilation time, Not totally memory efficient, but avoids adding sampling code to kernel (which keeps render time as low as possible), In the future this will be compensated by using OpenVDB for more efficient storage of sparse volume data. Sampling of the voxel texture is happening at blender side and the same code is used as for Blender Internal's renderer. This texture is controlled by only object, particle system and radius. Linear falloff is used and there's no turbulence. This is because falloff is expected to happen using Curve Mapping node. Turbulence will be done as a distortion on the input coordinate. It's already possible to fake it using nose textures and in the future we can add more proper turbulence distortion node, which then could also be used for 2D texture mapping. Particle color support is done by Lukas, thanks!
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/ui.py3
-rw-r--r--intern/cycles/blender/blender_session.cpp23
-rw-r--r--intern/cycles/blender/blender_shader.cpp29
-rw-r--r--intern/cycles/blender/blender_texture.cpp116
-rw-r--r--intern/cycles/blender/blender_texture.h31
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/BKE_texture.h1
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/texture.c10
-rw-r--r--source/blender/editors/space_node/drawnode.c26
-rw-r--r--source/blender/makesdna/DNA_node_types.h29
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c184
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c76
-rw-r--r--source/blender/render/intern/source/pointdensity.c34
19 files changed, 551 insertions, 19 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index fff9ed20bba..c6a2b919486 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -31,10 +31,12 @@ set(SRC
blender_session.cpp
blender_shader.cpp
blender_sync.cpp
+ blender_texture.cpp
CCL_api.h
blender_sync.h
blender_session.h
+ blender_texture.h
blender_util.h
)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 8bb086df06a..fdb2afdb5e9 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1236,7 +1236,8 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
node = context.texture_node
- return node and CyclesButtonsPanel.poll(context)
+ # TODO(sergey): perform a faster/nicer check?
+ return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 7342ed3b4f1..e1d5e1310d5 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1016,6 +1016,18 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti
is_float = true;
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ channels = 4;
+ width = height = depth = b_point_density_node.resolution();
+ is_float = true;
+ }
+ }
}
bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels)
@@ -1158,6 +1170,17 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ int length;
+ b_point_density_node.calc_point_density(b_scene, &length, &pixels);
+ }
+ }
return false;
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 2b0e8acae38..6c54149164d 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -22,6 +22,7 @@
#include "scene.h"
#include "shader.h"
+#include "blender_texture.h"
#include "blender_sync.h"
#include "blender_util.h"
@@ -736,6 +737,34 @@ static ShaderNode *add_node(Scene *scene,
uvm->from_dupli = b_uvmap_node.from_dupli();
node = uvm;
}
+ else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ PointDensityTextureNode *point_density = new PointDensityTextureNode();
+ point_density->filename = b_point_density_node.name();
+ point_density->space =
+ PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
+ point_density->interpolation =
+ (InterpolationType)b_point_density_node.interpolation();
+ point_density->builtin_data = b_point_density_node.ptr.data;
+
+ /* Transformation form world space to texture space. */
+ BL::Object b_ob(b_point_density_node.object());
+ if(b_ob) {
+ float3 loc, size;
+ point_density_texture_space(b_point_density_node, loc, size);
+ point_density->tfm =
+ transform_translate(-loc) * transform_scale(size) *
+ transform_inverse(get_transform(b_ob.matrix_world()));
+ }
+
+ /* TODO(sergey): Use more proper update flag. */
+ if(true) {
+ scene->image_manager->tag_reload_image(point_density->filename,
+ point_density->builtin_data,
+ point_density->interpolation);
+ }
+ node = point_density;
+ }
if(node)
graph->add(node);
diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp
new file mode 100644
index 00000000000..cb4dd1792d0
--- /dev/null
+++ b/intern/cycles/blender/blender_texture.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "blender_texture.h"
+
+CCL_NAMESPACE_BEGIN
+
+namespace {
+
+/* Point density helpers. */
+
+static 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);
+}
+
+static void density_object_texture_space(BL::Object b_ob,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_ob.type() == BL::Object::type_MESH) {
+ BL::Mesh b_mesh(b_ob.data());
+ loc = get_float3(b_mesh.texspace_location());
+ size = get_float3(b_mesh.texspace_size());
+ }
+ else {
+ /* TODO(sergey): Not supported currently. */
+ }
+ /* Adjust texture space to include density points on the boundaries. */
+ size = size + make_float3(radius, radius, radius);
+ density_texture_space_invert(loc, size);
+}
+
+static void density_particle_system_texture_space(
+ BL::Object b_ob,
+ BL::ParticleSystem b_particle_system,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_particle_system.settings().type() == BL::ParticleSettings::type_HAIR) {
+ /* TODO(sergey): Not supported currently. */
+ return;
+ }
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_inverse(tfm);
+ float3 min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ float3 particle_size = make_float3(radius, radius, radius);
+ for(int i = 0; i < b_particle_system.particles.length(); ++i) {
+ BL::Particle particle = b_particle_system.particles[i];
+ float3 location = get_float3(particle.location());
+ location = transform_point(&itfm, location);
+ min = ccl::min(min, location - particle_size);
+ max = ccl::max(max, location + particle_size);
+ }
+ /* Calculate texture space from the particle bounds. */
+ loc = (min + max) * 0.5f;
+ size = (max - min) * 0.5f;
+ density_texture_space_invert(loc, size);
+}
+
+} /* namespace */
+
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size)
+{
+ /* Fallback values. */
+ loc = make_float3(0.0f, 0.0f, 0.0f);
+ size = make_float3(0.0f, 0.0f, 0.0f);
+ BL::Object b_ob(b_point_density_node.object());
+ if(!b_ob) {
+ return;
+ }
+ if(b_point_density_node.point_source() ==
+ BL::ShaderNodeTexPointDensity::point_source_PARTICLE_SYSTEM)
+ {
+ BL::ParticleSystem b_particle_system(
+ b_point_density_node.particle_system());
+ if(b_particle_system) {
+ density_particle_system_texture_space(b_ob,
+ b_particle_system,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+ }
+ else {
+ density_object_texture_space(b_ob,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h
new file mode 100644
index 00000000000..74fbca02a9e
--- /dev/null
+++ b/intern/cycles/blender/blender_texture.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BLENDER_TEXTURE_H__
+#define __BLENDER_TEXTURE_H__
+
+#include <stdlib.h>
+#include "blender_sync.h"
+
+CCL_NAMESPACE_BEGIN
+
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size);
+
+CCL_NAMESPACE_END
+
+#endif /* __BLENDER_TEXTURE_H__ */
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index cada125c6c2..c3def14787d 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -237,6 +237,7 @@ shader_node_categories = [
NodeItem("ShaderNodeTexMagic"),
NodeItem("ShaderNodeTexChecker"),
NodeItem("ShaderNodeTexBrick"),
+ NodeItem("ShaderNodeTexPointDensity"),
]),
ShaderNewNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4deaf26e2f5..0a6c21c2c60 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -782,6 +782,7 @@ struct ShadeResult;
#define SH_NODE_COMBXYZ 189
#define SH_NODE_OUTPUT_LINESTYLE 190
#define SH_NODE_UVALONGSTROKE 191
+#define SH_NODE_TEX_POINTDENSITY 192
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 4e5214bc364..95918b9ca0b 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -115,6 +115,7 @@ void BKE_texture_envmap_free(struct EnvMap *env);
struct EnvMap *BKE_texture_envmap_add(void);
struct EnvMap *BKE_texture_envmap_copy(struct EnvMap *env);
+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);
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 8ac0a8a31f6..8ea0a9df5f2 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3591,6 +3591,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_magic();
register_node_type_sh_tex_checker();
register_node_type_sh_tex_brick();
+ register_node_type_sh_tex_pointdensity();
}
static void registerTextureNodes(void)
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 2ea903247b2..88a412d5e95 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -1470,11 +1470,8 @@ void BKE_texture_envmap_free(EnvMap *env)
/* ------------------------------------------------------------------------- */
-PointDensity *BKE_texture_pointdensity_add(void)
+void BKE_texture_pointdensity_init_data(PointDensity *pd)
{
- PointDensity *pd;
-
- pd = MEM_callocN(sizeof(PointDensity), "pointdensity");
pd->flag = 0;
pd->radius = 0.3f;
pd->falloff_type = TEX_PD_FALLOFF_STD;
@@ -1498,7 +1495,12 @@ PointDensity *BKE_texture_pointdensity_add(void)
pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, CURVEMAP_SLOPE_POSITIVE);
curvemapping_changed(pd->falloff_curve, false);
+}
+PointDensity *BKE_texture_pointdensity_add(void)
+{
+ PointDensity *pd = MEM_callocN(sizeof(PointDensity), "pointdensity");
+ BKE_texture_pointdensity_init_data(pd);
return pd;
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 7f35884cb65..fe0e959e976 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -937,6 +937,29 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
}
+static void node_shader_buts_tex_pointdensity(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+
+ uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+
+ if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ PointerRNA dataptr;
+ RNA_id_pointer_create((ID *)node->id, &dataptr);
+ uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE);
+ }
+
+ uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "radius", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE);
+ if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) {
+ uiItemR(layout, ptr, "color_source", 0, NULL, ICON_NONE);
+ }
+}
+
static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "object", 0, NULL, 0);
@@ -1170,6 +1193,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_VORONOI:
ntype->draw_buttons = node_shader_buts_tex_voronoi;
break;
+ case SH_NODE_TEX_POINTDENSITY:
+ ntype->draw_buttons = node_shader_buts_tex_pointdensity;
+ break;
case SH_NODE_TEX_COORD:
ntype->draw_buttons = node_shader_buts_tex_coord;
break;
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index f17bf5af434..727c7b2117a 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -790,6 +790,17 @@ typedef struct NodeShaderVectTransform {
int pad;
} NodeShaderVectTransform;
+typedef struct NodeShaderTexPointDensity {
+ short point_source, pad;
+ int particle_system;
+ float radius;
+ int resolution;
+ short space;
+ short interpolation;
+ short color_source;
+ short pad2;
+} NodeShaderTexPointDensity;
+
/* TEX_output */
typedef struct TexNodeOutput {
char name[64];
@@ -1090,4 +1101,22 @@ enum {
#define CMP_NODE_PLANETRACKDEFORM_MBLUR_SAMPLES_MAX 64
+/* 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,
+};
+
#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 4df954b062b..068fb029182 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -38,6 +38,8 @@
#include "DNA_mesh_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
#include "DNA_text_types.h"
#include "DNA_texture_types.h"
@@ -61,6 +63,8 @@
#include "MEM_guardedalloc.h"
+#include "RE_render_ext.h"
+
EnumPropertyItem node_socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "Input", "" },
{ SOCK_OUT, "OUT", 0, "Output", "" },
@@ -2966,6 +2970,89 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA
rna_Node_update(bmain, scene, ptr);
}
+static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object*)node->id;
+ ParticleSystem *psys = NULL;
+ PointerRNA value;
+
+ if (ob && shader_point_density->particle_system) {
+ psys = BLI_findlink(&ob->particlesystem, shader_point_density->particle_system - 1);
+ }
+
+ RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &value);
+ return value;
+}
+
+static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr, PointerRNA value)
+{
+ bNode *node = ptr->data;
+ NodeShaderTexPointDensity *shader_point_density = node->storage;
+ Object *ob = (Object*)node->id;
+
+ if (ob && value.id.data == ob) {
+ shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1;
+ }
+ else {
+ shader_point_density->particle_system = 0;
+ }
+}
+
+static int point_density_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(!"Unknown color source");
+ return TEX_PD_COLOR_CONSTANT;
+ }
+}
+
+/* TODO(sergey): This functio nassumes allocated array was passed,
+ * works fine with Cycles via C++ RNA, but fails with call from python.
+ */
+void rna_ShaderNodePointDensity_density_calc(bNode *self, Scene *scene, int *length, float **values)
+{
+ NodeShaderTexPointDensity *shader_point_density = self->storage;
+ PointDensity pd;
+
+ *length = 4 * shader_point_density->resolution *
+ shader_point_density->resolution *
+ shader_point_density->resolution;
+
+ if (*values == NULL) {
+ *values = MEM_mallocN(sizeof(float) * (*length), "point density dynamic array");
+ }
+
+ /* Create PointDensity structure from node for sampling. */
+ BKE_texture_pointdensity_init_data(&pd);
+ pd.object = (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;
+ }
+ 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.color_source = point_density_color_source_from_shader(shader_point_density);
+
+ /* Single-threaded sampling of the voxel domain. */
+ RE_sample_point_density(scene, &pd,
+ shader_point_density->resolution,
+ *values);
+
+ /* We're done, time to clean up. */
+ BKE_texture_pointdensity_free_data(&pd);
+}
+
#else
static EnumPropertyItem prop_image_layer_items[] = {
@@ -3792,6 +3879,103 @@ static void def_sh_tex_wireframe(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_sh_tex_pointdensity(StructRNA *srna)
+{
+ PropertyRNA *prop;
+ FunctionRNA *func;
+
+ static 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, NULL, 0, NULL, NULL}
+ };
+
+ 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 (CPU only)"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem space_items[] = {
+ {SHD_POINTDENSITY_SPACE_OBJECT, "OBJECT", 0, "Object Space", ""},
+ {SHD_POINTDENSITY_SPACE_WORLD, "WORLD", 0, "World Space", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem color_source_items[] = {
+ {SHD_POINTDENSITY_COLOR_PARTAGE, "PARTICLE_AGE", 0, "Particle Age",
+ "Lifetime mapped as 0.0 - 1.0 intensity"},
+ {SHD_POINTDENSITY_COLOR_PARTSPEED, "PARTICLE_SPEED", 0, "Particle Speed",
+ "Particle speed (absolute magnitude of velocity) mapped as 0.0-1.0 intensity"},
+ {SHD_POINTDENSITY_COLOR_PARTVEL, "PARTICLE_VELOCITY", 0, "Particle Velocity",
+ "XYZ velocity mapped to RGB colors"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ 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", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ 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, NULL, "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, "color_source", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "color_source");
+ RNA_def_property_enum_items(prop, 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");
+
+ 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, "scene", "Scene", "", "");
+ /* TODO, See how array size of 0 works, this shouldnt be used. */
+ prop = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_function_output(func, prop);
+}
+
static void def_glossy(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index c95daffe557..3fd1241f3fa 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -200,6 +200,7 @@ set(SRC
shader/nodes/node_shader_tex_magic.c
shader/nodes/node_shader_tex_musgrave.c
shader/nodes/node_shader_tex_noise.c
+ shader/nodes/node_shader_tex_pointdensity.c
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 595a3b12bc6..4c0047f1d58 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -75,6 +75,7 @@ void register_node_type_sh_sepxyz(void);
void register_node_type_sh_combxyz(void);
void register_node_type_sh_hue_sat(void);
void register_node_type_sh_tex_brick(void);
+void register_node_type_sh_tex_pointdensity(void);
void register_node_type_sh_attribute(void);
void register_node_type_sh_geometry(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index b33bec51c2c..9e1a0c926fa 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -116,6 +116,7 @@ DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TE
DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" )
+DefNode( ShaderNode, SH_NODE_TEX_POINTDENSITY, def_sh_tex_pointdensity,"TEX_POINTDENSITY", TexPointDensity, "Point Density", "" )
DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode( ShaderNode, SH_NODE_VECT_TRANSFORM, def_sh_vect_transform, "VECT_TRANSFORM", VectorTransform, "Vector Transform", "" )
DefNode( ShaderNode, SH_NODE_SEPHSV, 0, "SEPHSV", SeparateHSV, "Separate HSV", "" )
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
new file mode 100644
index 00000000000..6205b0fa11f
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_pointdensity.c
@@ -0,0 +1,76 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_tex_pointdensity_in[] = {
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ {-1, 0, ""}
+};
+
+static bNodeSocketTemplate sh_node_tex_pointdensity_out[] = {
+ {SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {SOCK_FLOAT, 0, N_("Density"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f},
+ {-1, 0, ""}
+};
+
+static void node_shader_init_tex_pointdensity(bNodeTree *UNUSED(ntree),
+ bNode *node)
+{
+ NodeShaderTexPointDensity *point_density =
+ MEM_callocN(sizeof(NodeShaderTexPointDensity), "new pd node");
+ 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;
+}
+
+/* node type definition */
+void register_node_type_sh_tex_pointdensity(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype,
+ SH_NODE_TEX_POINTDENSITY,
+ "Point Density",
+ NODE_CLASS_TEXTURE,
+ 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype,
+ sh_node_tex_pointdensity_in,
+ sh_node_tex_pointdensity_out);
+ node_type_init(&ntype, node_shader_init_tex_pointdensity);
+ node_type_storage(&ntype,
+ "NodeShaderTexPointDensity",
+ node_free_standard_storage,
+ node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index a99cc3c72a2..d2ec5d80c91 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -152,6 +152,7 @@ static void pointdensity_cache_psys(Scene *scene,
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
/* in case ob->imat isn't up-to-date */
invert_m4_m4(ob->imat, ob->obmat);
@@ -530,6 +531,7 @@ static int pointdensity(PointDensity *pd,
mul_v3_fl(vec, 1.0f / num);
}
+ texres->tin = density;
if (r_age != NULL) {
*r_age = age;
}
@@ -537,24 +539,14 @@ static int pointdensity(PointDensity *pd,
copy_v3_v3(r_vec, vec);
}
- texres->tin = density;
-
return retval;
}
-int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+static int pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3])
{
- PointDensity *pd = tex->pd;
- float age = 0.0f;
- float vec[3] = {0.0f, 0.0f, 0.0f};
- int retval = pointdensity(pd, texvec, texres, &age, vec);
+ int retval = 0;
float col[4];
- BRICONT;
-
- if (pd->color_source == TEX_PD_COLOR_CONSTANT)
- return retval;
-
retval |= TEX_RGB;
switch (pd->color_source) {
@@ -584,8 +576,7 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
}
case TEX_PD_COLOR_PARTVEL:
texres->talpha = true;
- mul_v3_fl(vec, pd->speed_scale);
- copy_v3_v3(&texres->tr, vec);
+ mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
texres->ta = texres->tin;
break;
case TEX_PD_COLOR_CONSTANT:
@@ -593,6 +584,20 @@ int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
break;
}
+
+ return retval;
+}
+
+int pointdensitytex(Tex *tex, const float texvec[3], TexResult *texres)
+{
+ PointDensity *pd = tex->pd;
+ float age = 0.0f;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ int retval = pointdensity(pd, texvec, texres, &age, vec);
+
+ BRICONT;
+
+ retval |= pointdensity_color(pd, texres, age, vec);
BRICONTRGB;
return retval;
@@ -698,6 +703,7 @@ void RE_sample_point_density(Scene *scene, PointDensity *pd,
texvec[2] += dim[2] * (float)z / (float)resolution;
pointdensity(pd, texvec, &texres, &age, vec);
+ pointdensity_color(pd, &texres, age, vec);
copy_v3_v3(&values[index*4 + 0], &texres.tr);
values[index*4 + 3] = texres.tin;