Cycles: change Index output of Hair and Particle Info to Random, in 0..1 range.

These are used for randomization, so it's convenient if the index is already
hashed and consistent with the Object Info node.
This commit is contained in:
Brecht Van Lommel 2018-02-14 14:32:38 +01:00
parent c8e661706f
commit f6107af4cf
Notes: blender-bot 2023-02-14 09:21:21 +01:00
Referenced by issue #54075, Align Objects fails with IndexError: bpy_prop_collection[-1]: out of range.
18 changed files with 54 additions and 56 deletions

View File

@ -25,6 +25,7 @@
#include "blender/blender_util.h"
#include "util/util_foreach.h"
#include "util/util_hash.h"
#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@ -565,12 +566,12 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
return;
Attribute *attr_intercept = NULL;
Attribute *attr_index = NULL;
Attribute *attr_random = NULL;
if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
if(mesh->need_attribute(scene, ATTR_STD_CURVE_INDEX))
attr_index = mesh->curve_attributes.add(ATTR_STD_CURVE_INDEX);
if(mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);
/* compute and reserve size of arrays */
for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
@ -615,8 +616,8 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
num_curve_keys++;
}
if(attr_index != NULL) {
attr_index->add(num_curves);
if(attr_random != NULL) {
attr_random->add(hash_int_01(num_curves));
}
mesh->add_curve(num_keys, CData->psys_shader[sys]);
@ -625,15 +626,6 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa
}
}
if(attr_index != NULL) {
/* Normalize index to 0..1 range. */
float *curve_index = attr_index->data_float();
const float norm_factor = 1.0f / (float)num_curves;
for(int i = 0; i < num_curves; ++i) {
curve_index[i] *= norm_factor;
}
}
/* check allocation */
if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";

View File

@ -352,7 +352,7 @@ ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
/* Particle data from which object was instanced */
ccl_device_inline float particle_index(KernelGlobals *kg, int particle)
ccl_device_inline float particle_random(KernelGlobals *kg, int particle)
{
int offset = particle*PARTICLE_SIZE;
float4 f = kernel_tex_fetch(__particles, offset + 0);

View File

@ -772,7 +772,7 @@ typedef enum AttributeStandard {
ATTR_STD_MOTION_VERTEX_NORMAL,
ATTR_STD_PARTICLE,
ATTR_STD_CURVE_INTERCEPT,
ATTR_STD_CURVE_INDEX,
ATTR_STD_CURVE_RANDOM,
ATTR_STD_PTEX_FACE_ID,
ATTR_STD_PTEX_UV,
ATTR_STD_VOLUME_DENSITY,

View File

@ -82,7 +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");
ustring OSLRenderServices::u_particle_location("particle:location");
@ -96,11 +96,10 @@ ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices");
ustring OSLRenderServices::u_geom_name("geom:name");
ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced");
ustring OSLRenderServices::u_is_smooth("geom:is_smooth");
#ifdef __HAIR__
ustring OSLRenderServices::u_is_curve("geom:is_curve");
ustring OSLRenderServices::u_curve_thickness("geom:curve_thickness");
ustring OSLRenderServices::u_curve_tangent_normal("geom:curve_tangent_normal");
#endif
ustring OSLRenderServices::u_curve_random("geom:curve_random");
ustring OSLRenderServices::u_path_ray_length("path:ray_length");
ustring OSLRenderServices::u_path_ray_depth("path:ray_depth");
ustring OSLRenderServices::u_path_diffuse_depth("path:diffuse_depth");
@ -653,9 +652,9 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
}
/* Particle Attributes */
else if(name == u_particle_index) {
else if(name == u_particle_random) {
int particle_id = object_particle_id(kg, sd->object);
float f = particle_index(kg, particle_id);
float f = particle_random(kg, particle_id);
return set_attribute_float(f, type, derivatives, val);
}
else if(name == u_particle_age) {
@ -701,11 +700,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
return set_attribute_int(3, type, derivatives, val);
}
else if((name == u_geom_trianglevertices || name == u_geom_polyvertices)
#ifdef __HAIR__
&& sd->type & PRIMITIVE_ALL_TRIANGLE)
#else
)
#endif
{
float3 P[3];
@ -730,7 +725,6 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0);
return set_attribute_float(f, type, derivatives, val);
}
#ifdef __HAIR__
/* Hair Attributes */
else if(name == u_is_curve) {
float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
@ -744,7 +738,6 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
float3 f = curve_tangent_normal(kg, sd);
return set_attribute_float3(f, type, derivatives, val);
}
#endif
else
return false;
}

View File

@ -146,7 +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;
static ustring u_particle_location;
@ -163,6 +163,7 @@ public:
static ustring u_is_curve;
static ustring u_curve_thickness;
static ustring u_curve_tangent_normal;
static ustring u_curve_random;
static ustring u_path_ray_length;
static ustring u_path_ray_depth;
static ustring u_path_diffuse_depth;

View File

@ -21,12 +21,12 @@ shader node_hair_info(
output float Intercept = 0.0,
output float Thickness = 0.0,
output normal TangentNormal = N,
output float Index = 0)
output float Random = 0)
{
getattribute("geom:is_curve", IsStrand);
getattribute("geom:curve_intercept", Intercept);
getattribute("geom:curve_thickness", Thickness);
getattribute("geom:curve_tangent_normal", TangentNormal);
getattribute("geom:curve_index", Index);
getattribute("geom:curve_random", Random);
}

View File

@ -17,7 +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,
output point Location = point(0.0, 0.0, 0.0),
@ -25,7 +25,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);
getattribute("particle:location", Location);

View File

@ -114,9 +114,9 @@ ccl_device void svm_node_particle_info(KernelGlobals *kg,
uint out_offset)
{
switch(type) {
case NODE_INFO_PAR_INDEX: {
case NODE_INFO_PAR_RANDOM: {
int particle_id = object_particle_id(kg, sd->object);
stack_store_float(stack, out_offset, particle_index(kg, particle_id));
stack_store_float(stack, out_offset, particle_random(kg, particle_id));
break;
}
case NODE_INFO_PAR_AGE: {
@ -180,7 +180,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg,
}
case NODE_INFO_CURVE_INTERCEPT:
break; /* handled as attribute */
case NODE_INFO_CURVE_INDEX:
case NODE_INFO_CURVE_RANDOM:
break; /* handled as attribute */
case NODE_INFO_CURVE_THICKNESS: {
data = curve_thickness(kg, sd);

View File

@ -160,7 +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,
NODE_INFO_PAR_LOCATION,
@ -177,7 +177,7 @@ typedef enum NodeHairInfo {
/*fade for minimum hair width transpency*/
/*NODE_INFO_CURVE_FADE,*/
NODE_INFO_CURVE_TANGENT_NORMAL,
NODE_INFO_CURVE_INDEX,
NODE_INFO_CURVE_RANDOM,
} NodeHairInfo;
typedef enum NodeLightPath {

View File

@ -267,8 +267,8 @@ const char *Attribute::standard_name(AttributeStandard std)
return "particle";
case ATTR_STD_CURVE_INTERCEPT:
return "curve_intercept";
case ATTR_STD_CURVE_INDEX:
return "curve_index";
case ATTR_STD_CURVE_RANDOM:
return "curve_random";
case ATTR_STD_PTEX_FACE_ID:
return "ptex_face_id";
case ATTR_STD_PTEX_UV:
@ -453,7 +453,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
case ATTR_STD_CURVE_INTERCEPT:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
break;
case ATTR_STD_CURVE_INDEX:
case ATTR_STD_CURVE_RANDOM:
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
break;
case ATTR_STD_GENERATED_TRANSFORM:

View File

@ -3463,7 +3463,7 @@ NODE_DEFINE(ParticleInfoNode)
{
NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER);
SOCKET_OUT_FLOAT(index, "Index");
SOCKET_OUT_FLOAT(random, "Random");
SOCKET_OUT_FLOAT(age, "Age");
SOCKET_OUT_FLOAT(lifetime, "Lifetime");
SOCKET_OUT_POINT(location, "Location");
@ -3484,7 +3484,7 @@ ParticleInfoNode::ParticleInfoNode()
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(!output("Index")->links.empty())
if(!output("Random")->links.empty())
attributes->add(ATTR_STD_PARTICLE);
if(!output("Age")->links.empty())
attributes->add(ATTR_STD_PARTICLE);
@ -3510,9 +3510,9 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
{
ShaderOutput *out;
out = output("Index");
out = output("Random");
if(!out->links.empty()) {
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
}
out = output("Age");
@ -3572,7 +3572,7 @@ NODE_DEFINE(HairInfoNode)
#if 0 /*output for minimum hair width transparency - deactivated */
SOCKET_OUT_FLOAT(fade, "Fade");
#endif
SOCKET_OUT_FLOAT(index, "Index");
SOCKET_OUT_FLOAT(index, "Random");
return type;
}
@ -3590,8 +3590,8 @@ void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
if(!intercept_out->links.empty())
attributes->add(ATTR_STD_CURVE_INTERCEPT);
if(!output("Index")->links.empty())
attributes->add(ATTR_STD_CURVE_INDEX);
if(!output("Random")->links.empty())
attributes->add(ATTR_STD_CURVE_RANDOM);
}
ShaderNode::attributes(shader, attributes);
@ -3627,9 +3627,9 @@ void HairInfoNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
}*/
out = output("Index");
out = output("Random");
if(!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_CURVE_INDEX);
int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
}
}

View File

@ -19,6 +19,7 @@
#include "render/scene.h"
#include "util/util_foreach.h"
#include "util/util_hash.h"
#include "util/util_logging.h"
#include "util/util_map.h"
#include "util/util_progress.h"
@ -79,7 +80,8 @@ void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscen
Particle& pa = psys->particles[k];
int offset = i*PARTICLE_SIZE;
particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size);
float random = hash_int_01(pa.index);
particles[offset] = make_float4(random, 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);

View File

@ -61,6 +61,11 @@ static inline uint hash_string(const char *str)
}
#endif
ccl_device_inline float hash_int_01(uint k)
{
return (float)hash_int(k) * (1.0f/(float)0xFFFFFFFF);
}
CCL_NAMESPACE_END
#endif /* __UTIL_HASH_H__ */

View File

@ -63,4 +63,9 @@ BLI_INLINE unsigned int BLI_hash_int(unsigned int k)
return BLI_hash_int_2d(k, 0);
}
BLI_INLINE float BLI_hash_int_01(unsigned int k)
{
return (float)BLI_hash_int(k) * (1.0f/(float)0xFFFFFFFF);
}
#endif // __BLI_HASH_H__

View File

@ -41,11 +41,11 @@
#include "GPU_glew.h"
#include "BLI_blenlib.h"
#include "BLI_hash.h"
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
#include "BLI_hash.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
@ -1884,7 +1884,7 @@ static int gpu_get_particle_info(GPUParticleInfo *pi)
if (ind >= 0) {
ParticleData *p = &dob->particle_system->particles[ind];
pi->scalprops[0] = ind;
pi->scalprops[0] = BLI_hash_int_01(ind);
pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
pi->scalprops[2] = p->lifetime;
pi->scalprops[3] = p->size;

View File

@ -190,10 +190,10 @@ void geom(
void particle_info(
vec4 sprops, vec3 loc, vec3 vel, vec3 avel,
out float index, out float age, out float life_time, out vec3 location,
out float random, out float age, out float life_time, out vec3 location,
out float size, out vec3 velocity, out vec3 angular_velocity)
{
index = sprops.x;
random = sprops.x;
age = sprops.y;
life_time = sprops.z;
size = sprops.w;

View File

@ -33,7 +33,7 @@ static bNodeSocketTemplate outputs[] = {
{ SOCK_FLOAT, 0, N_("Thickness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_VECTOR, 0, N_("Tangent Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
/*{ SOCK_FLOAT, 0, N_("Fade"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},*/
{ SOCK_FLOAT, 0, "Index" },
{ SOCK_FLOAT, 0, N_("Random") },
{ -1, 0, "" }
};

View File

@ -29,7 +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" },
{ SOCK_VECTOR, 0, "Location" },