Cycles: restore Particle Info Index for now, keep it next to Random.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 14 Feb 2018 16:02:28 +0000 (17:02 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 14 Feb 2018 20:45:57 +0000 (21:45 +0100)
It seems to be useful still in cases where the particle are distributed in
a particular order or pattern, to colorize them along with that. This isn't
really well defined, but might as well avoid breaking backwards compatibility
for now.

15 files changed:
intern/cycles/kernel/geom/geom_object.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/osl/osl_services.h
intern/cycles/kernel/shaders/node_particle_info.osl
intern/cycles/kernel/svm/svm_geometry.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/render/particles.cpp
source/blender/gpu/GPU_material.h
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/nodes/shader/nodes/node_shader_particle_info.c
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/source/renderdatabase.c

index a63d180d450d01fde34602b42f238eb0e0a9f8b2..32aa2007f5d977675d658db98aad6919dd49a3c3 100644 (file)
@@ -352,11 +352,11 @@ ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
 
 /* Particle data from which object was instanced */
 
-ccl_device_inline float particle_random(KernelGlobals *kg, int particle)
+ccl_device_inline uint particle_index(KernelGlobals *kg, int particle)
 {
        int offset = particle*PARTICLE_SIZE;
        float4 f = kernel_tex_fetch(__particles, offset + 0);
-       return f.x;
+       return __float_as_uint(f.x);
 }
 
 ccl_device float particle_age(KernelGlobals *kg, int particle)
index c4128e84f5c3eedd0a7aba83022d392a1afead68..ae4c521659c7c17c781e79d67fe79f16a436a843 100644 (file)
@@ -82,6 +82,7 @@ ustring OSLRenderServices::u_geom_dupli_generated("geom:dupli_generated");
 ustring OSLRenderServices::u_geom_dupli_uv("geom:dupli_uv");
 ustring OSLRenderServices::u_material_index("material:index");
 ustring OSLRenderServices::u_object_random("object:random");
+ustring OSLRenderServices::u_particle_index("particle:index");
 ustring OSLRenderServices::u_particle_random("particle:random");
 ustring OSLRenderServices::u_particle_age("particle:age");
 ustring OSLRenderServices::u_particle_lifetime("particle:lifetime");
@@ -652,11 +653,17 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
        }
 
        /* Particle Attributes */
+       else if(name == u_particle_index) {
+               int particle_id = object_particle_id(kg, sd->object);
+               float f = particle_index(kg, particle_id);
+               return set_attribute_float(f, type, derivatives, val);
+       }
        else if(name == u_particle_random) {
                int particle_id = object_particle_id(kg, sd->object);
-               float f = particle_random(kg, particle_id);
+               float f = hash_int_01(particle_index(kg, particle_id));
                return set_attribute_float(f, type, derivatives, val);
        }
+
        else if(name == u_particle_age) {
                int particle_id = object_particle_id(kg, sd->object);
                float f = particle_age(kg, particle_id);
index 2f2dc124a9872fa303eaaaf62e81dea9e5aa4581..d96048e26f29d561d700e1904dfa53b1bd0bb543 100644 (file)
@@ -146,6 +146,7 @@ public:
        static ustring u_geom_dupli_uv;
        static ustring u_material_index;
        static ustring u_object_random;
+       static ustring u_particle_index;
        static ustring u_particle_random;
        static ustring u_particle_age;
        static ustring u_particle_lifetime;
index 05358400bf8087c80027460e5f22b9eb9598c5cb..2a0252d5e45fea67e10422aaea5b9d30f0c78c26 100644 (file)
@@ -17,6 +17,7 @@
 #include "stdosl.h"
 
 shader node_particle_info(
+    output float Index = 0.0,
     output float Random = 0.0,
     output float Age = 0.0,
     output float Lifetime = 0.0,
@@ -25,6 +26,7 @@ shader node_particle_info(
     output vector Velocity = point(0.0, 0.0, 0.0),
     output vector AngularVelocity = point(0.0, 0.0, 0.0))
 {
+       getattribute("particle:index", Index);
        getattribute("particle:random", Random);
        getattribute("particle:age", Age);
        getattribute("particle:lifetime", Lifetime);
index 2f85a80111230978331aaead03d3b8d25eb63c9a..81308d6f12bf23d2dadf95358047166111b8df76 100644 (file)
@@ -114,9 +114,15 @@ ccl_device void svm_node_particle_info(KernelGlobals *kg,
                                        uint out_offset)
 {
        switch(type) {
+               case NODE_INFO_PAR_INDEX: {
+                       int particle_id = object_particle_id(kg, sd->object);
+                       stack_store_float(stack, out_offset, particle_index(kg, particle_id));
+                       break;
+               }
                case NODE_INFO_PAR_RANDOM: {
                        int particle_id = object_particle_id(kg, sd->object);
-                       stack_store_float(stack, out_offset, particle_random(kg, particle_id));
+                       float random = hash_int_01(particle_index(kg, particle_id));
+                       stack_store_float(stack, out_offset, random);
                        break;
                }
                case NODE_INFO_PAR_AGE: {
index 9e19ab4444d7fa4ac2993d646b79fbd930496286..390d325568442b7a58e5c69ac974d4bb7cd625ea 100644 (file)
@@ -160,6 +160,7 @@ typedef enum NodeObjectInfo {
 } NodeObjectInfo;
 
 typedef enum NodeParticleInfo {
+       NODE_INFO_PAR_INDEX,
        NODE_INFO_PAR_RANDOM,
        NODE_INFO_PAR_AGE,
        NODE_INFO_PAR_LIFETIME,
index 44c807065e4699fdf539fb99f744ea0ebc8fdec7..48613a9324cbbbdc10d9788c970cedfdc5c1b3a0 100644 (file)
@@ -3463,6 +3463,7 @@ NODE_DEFINE(ParticleInfoNode)
 {
        NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER);
 
+       SOCKET_OUT_FLOAT(random, "Index");
        SOCKET_OUT_FLOAT(random, "Random");
        SOCKET_OUT_FLOAT(age, "Age");
        SOCKET_OUT_FLOAT(lifetime, "Lifetime");
@@ -3484,6 +3485,8 @@ ParticleInfoNode::ParticleInfoNode()
 
 void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
 {
+       if(!output("Index")->links.empty())
+               attributes->add(ATTR_STD_PARTICLE);
        if(!output("Random")->links.empty())
                attributes->add(ATTR_STD_PARTICLE);
        if(!output("Age")->links.empty())
@@ -3510,6 +3513,11 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
 {
        ShaderOutput *out;
        
+       out = output("Index");
+       if(!out->links.empty()) {
+               compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
+       }
+
        out = output("Random");
        if(!out->links.empty()) {
                compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
index 07e246a092ae60ac06ec0896dc89b1ecac3cb029..3ee620c9d0120672c8626edf04138a2ef4cb5857 100644 (file)
@@ -80,8 +80,7 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen
                        Particle& pa = psys->particles[k];
                        int offset = i*PARTICLE_SIZE;
                        
-                       float random = hash_int_01(pa.index);
-                       particles[offset] = make_float4(random, pa.age, pa.lifetime, pa.size);
+                       particles[offset] = make_float4(__uint_as_float(pa.index), pa.age, pa.lifetime, pa.size);
                        particles[offset+1] = pa.rotation;
                        particles[offset+2] = make_float4(pa.location.x, pa.location.y, pa.location.z, pa.velocity.x);
                        particles[offset+3] = make_float4(pa.velocity.y, pa.velocity.z, pa.angular_velocity.x, pa.angular_velocity.y);
index dbfcd4d1ea40001a3f3f33b033a9a664107096cf..e229afd3323b78b39281dbcb57b4d718b148db6b 100644 (file)
@@ -344,10 +344,9 @@ void GPU_zenith_update_color(float color[3]);
 struct GPUParticleInfo
 {
        float scalprops[4];
-       float location[3];
+       float location[4];
        float velocity[3];
        float angular_velocity[3];
-       int random_id;
 };
 
 #ifdef WITH_OPENSUBDIV
index d7e744951c483e94c3b6bf8f383e1c08be2ed6f1..61d57dee092c5eec89a37f718f4044fc35cfe2d4 100644 (file)
@@ -1884,12 +1884,14 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
                if (ind >= 0) {
                        ParticleData *p = &dob->particle_system->particles[ind];
 
-                       pi->scalprops[0] = BLI_hash_int_01(ind);
+                       pi->scalprops[0] = ind;
                        pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
                        pi->scalprops[2] = p->lifetime;
                        pi->scalprops[3] = p->size;
 
                        copy_v3_v3(pi->location, p->state.co);
+                       pi->location[3] = BLI_hash_int_01(ind);
+
                        copy_v3_v3(pi->velocity, p->state.vel);
                        copy_v3_v3(pi->angular_velocity, p->state.ave);
                        return 1;
index 33eac16dadfe2f87728618710e26d0d444b58308..edb6c9a29f9c5a0cddc2e4aee8f0cc4f5fb698ea 100644 (file)
@@ -452,7 +452,7 @@ void GPU_material_bind_uniforms(
                        GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
                }
                if (material->builtins & GPU_PARTICLE_LOCATION) {
-                       GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
+                       GPU_shader_uniform_vector(shader, material->partcoloc, 4, 1, pi->location);
                }
                if (material->builtins & GPU_PARTICLE_VELOCITY) {
                        GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
index 5fe14e76a90fb215f622f359f1cc859f18b12855..1f5ffbdcc7e25df60f0e3147bd85b02876dc04c5 100644 (file)
@@ -189,16 +189,18 @@ void geom(
 }
 
 void particle_info(
-        vec4 sprops, vec3 loc, vec3 vel, vec3 avel,
-        out float random, out float age, out float life_time, out vec3 location,
+        vec4 sprops, vec4 loc, vec3 vel, vec3 avel,
+        out float index, out float random, out float age,
+        out float life_time, out vec3 location,
         out float size, out vec3 velocity, out vec3 angular_velocity)
 {
-       random = sprops.x;
+       index = sprops.x;
+       random = loc.w;
        age = sprops.y;
        life_time = sprops.z;
        size = sprops.w;
 
-       location = loc;
+       location = loc.xyz;
        velocity = vel;
        angular_velocity = avel;
 }
index 721d470b467f1c5ad257140eea5d8c4e8079dcde..3dbe5c81c570f126e461e1045dc5d33b8600b931 100644 (file)
@@ -29,6 +29,7 @@
 #include "RE_shader_ext.h"
 
 static bNodeSocketTemplate outputs[] = {
+       { SOCK_FLOAT,  0, "Index" },
        { SOCK_FLOAT,  0, "Random" },
        { SOCK_FLOAT,  0, "Age" },
        { SOCK_FLOAT,  0, "Lifetime" },
@@ -45,7 +46,7 @@ static void node_shader_exec_particle_info(void *data, int UNUSED(thread), bNode
 {
        ShadeInput *shi = ((ShaderCallData *)data)->shi;
 
-       RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec);
+       RE_instance_get_particle_info(shi->obi, out[0]->vec, out[1]->vec, out[2]->vec, out[3]->vec, out[4]->vec, out[5]->vec, out[6]->vec, out[7]->vec);
 }
 
 static int gpu_shader_particle_info(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
index b64c0c8fc5253c8aa079a72ff9ce25ed2e931450..e1cb922f6a5d11d518596798ffdc712985746d6f 100644 (file)
@@ -217,7 +217,7 @@ int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3],
                    const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex,
                    struct ImagePool *pool);
 float RE_lamp_get_data(struct ShadeInput *shi, struct Object *lamp_obj, float col[4], float lv[3], float *dist, float shadow[4]);
-void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]);
 
 float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta);
 
index 199322795f322ffd00a5d049f5cb2657e1f87741..2fbfcc64c8fe434b102f9e35c8d4c3f5ca5291f1 100644 (file)
@@ -1482,9 +1482,10 @@ ObjectInstanceRen *RE_addRenderInstance(
        return obi;
 }
 
-void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
+void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *random, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3])
 {
        *index = obi->part_index;
+       *random = BLI_hash_int_01(obi->part_index);
        *age = obi->part_age;
        *lifetime = obi->part_lifetime;
        copy_v3_v3(co, obi->part_co);