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:
authorLukas Toenne <lukas.toenne@googlemail.com>2012-06-08 20:17:57 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2012-06-08 20:17:57 +0400
commit5e1bbde01d0a77c7b032197cff860305462a9cb2 (patch)
treef751a45ac32c7d210b5e54b5d0a9efab61e16d24 /intern/cycles/render
parent82d3d9f2ba47bbf2f868b5a970d1fe149eba13e2 (diff)
Particle Info node for Cycles. This can be used to access particle information in material shaders for dupli objects. For now only the particle Age and individual Lifetime (in frames) are supported, more attributes can be added when needed.
The particle data is stored in a separate texture if any of the dupli objects uses particle info nodes in shaders. To map dupli objects onto particles the store an additional particle_index value, which is different from the simple dupli object index (only visible particles, also works for particle dupli groups mode). Some simple use cases on the code.blender.org blog: http://code.blender.org/index.php/2012/05/particle-info-node/
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/nodes.cpp41
-rw-r--r--intern/cycles/render/nodes.h6
-rw-r--r--intern/cycles/render/object.cpp44
-rw-r--r--intern/cycles/render/object.h9
-rw-r--r--intern/cycles/render/scene.h3
5 files changed, 102 insertions, 1 deletions
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 16c6b07261a..1c9eeacddbe 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1789,6 +1789,47 @@ void ObjectInfoNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_object_info");
}
+/* Particle Info */
+
+ParticleInfoNode::ParticleInfoNode()
+: ShaderNode("particle_info")
+{
+ add_output("Age", SHADER_SOCKET_FLOAT);
+ add_output("Lifetime", SHADER_SOCKET_FLOAT);
+}
+
+void ParticleInfoNode::attributes(AttributeRequestSet *attributes)
+{
+ if(!output("Age")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if(!output("Lifetime")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+
+ ShaderNode::attributes(attributes);
+}
+
+void ParticleInfoNode::compile(SVMCompiler& compiler)
+{
+ ShaderOutput *out;
+
+ out = output("Age");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, out->stack_offset);
+ }
+
+ out = output("Lifetime");
+ if(!out->links.empty()) {
+ compiler.stack_assign(out);
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, out->stack_offset);
+ }
+}
+
+void ParticleInfoNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_particle_info");
+}
+
/* Value */
ValueNode::ValueNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 2d0d58d1e94..650758a6113 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -290,6 +290,12 @@ public:
SHADER_NODE_CLASS(ObjectInfoNode)
};
+class ParticleInfoNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(ParticleInfoNode)
+ void attributes(AttributeRequestSet *attributes);
+};
+
class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 5c7e48a38eb..259a0d25bcc 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -25,6 +25,7 @@
#include "util_foreach.h"
#include "util_map.h"
#include "util_progress.h"
+#include "util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -38,6 +39,7 @@ Object::Object()
visibility = ~0;
random_id = 0;
pass_id = 0;
+ particle_id = 0;
bounds = BoundBox::empty;
motion.pre = transform_identity();
motion.post = transform_identity();
@@ -200,7 +202,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
memcpy(&objects[offset], &tfm, sizeof(float4)*3);
memcpy(&objects[offset+3], &itfm, sizeof(float4)*3);
- objects[offset+6] = make_float4(surface_area, pass_id, random_number, 0.0f);
+ objects[offset+6] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
if(need_motion == Scene::MOTION_PASS) {
/* motion transformations, is world/object space depending if mesh
@@ -246,6 +248,38 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
device->tex_alloc("__object_flag", dscene->object_flag);
}
+void ObjectManager::device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+{
+ /* count particles.
+ * adds one dummy particle at the beginning to avoid invalid lookups,
+ * in case a shader uses particle info without actual particle data.
+ */
+ int num_particles = 1;
+ foreach(Object *ob, scene->objects)
+ num_particles += ob->particles.size();
+
+ float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles);
+
+ /* dummy particle */
+ particles[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ int i = 1;
+ foreach(Object *ob, scene->objects) {
+ foreach(Particle &pa, ob->particles) {
+ /* pack in texture */
+ int offset = i*PARTICLE_SIZE;
+
+ particles[offset] = make_float4(pa.age, pa.lifetime, 0.0f, 0.0f);
+
+ i++;
+
+ if(progress.get_cancel()) return;
+ }
+ }
+
+ device->tex_alloc("__particles", dscene->particles);
+}
+
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
if(!need_update)
@@ -271,6 +305,11 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc
if(progress.get_cancel()) return;
+ progress.set_status("Updating Objects", "Copying Particles to device");
+ device_update_particles(device, dscene, scene, progress);
+
+ if(progress.get_cancel()) return;
+
need_update = false;
}
@@ -281,6 +320,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->object_flag);
dscene->object_flag.clear();
+
+ device->tex_free(dscene->particles);
+ dscene->particles.clear();
}
void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index a3bd748a8a4..6d674731b07 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -35,6 +35,11 @@ struct Transform;
/* Object */
+struct Particle {
+ float age;
+ float lifetime;
+};
+
class Object {
public:
Mesh *mesh;
@@ -49,6 +54,9 @@ public:
bool use_motion;
bool use_holdout;
+ int particle_id;
+ vector<Particle> particles;
+
Object();
~Object();
@@ -69,6 +77,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene);
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 90bc47d5c8e..8b9944cb76e 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -82,6 +82,9 @@ public:
device_vector<float2> light_background_marginal_cdf;
device_vector<float2> light_background_conditional_cdf;
+ /* particles */
+ device_vector<float4> particles;
+
/* shaders */
device_vector<uint4> svm_nodes;
device_vector<uint> shader_flag;