Cycles code refactor: changes to make adding new primitive types easier.

This commit is contained in:
Brecht Van Lommel 2014-03-29 13:03:46 +01:00
parent 24ad7e0bea
commit 0509553b5e
24 changed files with 191 additions and 189 deletions

View File

@ -97,7 +97,7 @@ bool BVH::cache_read(CacheData& key)
value.read(pack.nodes);
value.read(pack.object_node);
value.read(pack.tri_woop);
value.read(pack.prim_segment);
value.read(pack.prim_type);
value.read(pack.prim_visibility);
value.read(pack.prim_index);
value.read(pack.prim_object);
@ -119,7 +119,7 @@ void BVH::cache_write(CacheData& key)
value.add(pack.nodes);
value.add(pack.object_node);
value.add(pack.tri_woop);
value.add(pack.prim_segment);
value.add(pack.prim_type);
value.add(pack.prim_visibility);
value.add(pack.prim_index);
value.add(pack.prim_object);
@ -165,11 +165,11 @@ void BVH::build(Progress& progress)
}
/* build nodes */
vector<int> prim_segment;
vector<int> prim_type;
vector<int> prim_index;
vector<int> prim_object;
BVHBuild bvh_build(objects, prim_segment, prim_index, prim_object, params, progress);
BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress);
BVHNode *root = bvh_build.run();
if(progress.get_cancel()) {
@ -178,7 +178,7 @@ void BVH::build(Progress& progress)
}
/* todo: get rid of this copy */
pack.prim_segment = prim_segment;
pack.prim_type = prim_type;
pack.prim_index = prim_index;
pack.prim_object = prim_object;
@ -280,7 +280,7 @@ void BVH::pack_curve_segment(int idx, float4 woop[3])
int tob = pack.prim_object[idx];
const Mesh *mesh = objects[tob]->mesh;
int tidx = pack.prim_index[idx];
int segment = pack.prim_segment[idx];
int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]);
int k0 = mesh->curves[tidx].first_key + segment;
int k1 = mesh->curves[tidx].first_key + segment + 1;
float3 v0 = mesh->curve_keys[k0].co;
@ -324,7 +324,7 @@ void BVH::pack_primitives()
if(pack.prim_index[i] != -1) {
float4 woop[3];
if(pack.prim_segment[i] != ~0)
if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack_curve_segment(i, woop);
else
pack_triangle(i, woop);
@ -335,7 +335,7 @@ void BVH::pack_primitives()
Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility;
if(pack.prim_segment[i] != ~0)
if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack.prim_visibility[i] |= PATH_RAY_CURVE;
}
else {
@ -359,7 +359,7 @@ void BVH::pack_instances(size_t nodes_size)
* meshes with transform applied and already in the top level BVH */
for(size_t i = 0; i < pack.prim_index.size(); i++)
if(pack.prim_index[i] != -1) {
if(pack.prim_segment[i] != ~0)
if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->curve_offset;
else
pack.prim_index[i] += objects[pack.prim_object[i]]->mesh->tri_offset;
@ -401,7 +401,7 @@ void BVH::pack_instances(size_t nodes_size)
mesh_map.clear();
pack.prim_index.resize(prim_index_size);
pack.prim_segment.resize(prim_index_size);
pack.prim_type.resize(prim_index_size);
pack.prim_object.resize(prim_index_size);
pack.prim_visibility.resize(prim_index_size);
pack.tri_woop.resize(tri_woop_size);
@ -409,7 +409,7 @@ void BVH::pack_instances(size_t nodes_size)
pack.object_node.resize(objects.size());
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
int *pack_prim_segment = (pack.prim_segment.size())? &pack.prim_segment[0]: NULL;
int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL;
float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL;
@ -454,16 +454,16 @@ void BVH::pack_instances(size_t nodes_size)
if(bvh->pack.prim_index.size()) {
size_t bvh_prim_index_size = bvh->pack.prim_index.size();
int *bvh_prim_index = &bvh->pack.prim_index[0];
int *bvh_prim_segment = &bvh->pack.prim_segment[0];
int *bvh_prim_type = &bvh->pack.prim_type[0];
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
for(size_t i = 0; i < bvh_prim_index_size; i++) {
if(bvh->pack.prim_segment[i] != ~0)
if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
else
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_tri_offset;
pack_prim_segment[pack_prim_index_offset] = bvh_prim_segment[i];
pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
pack_prim_index_offset++;
@ -629,10 +629,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
/* primitives */
const Mesh *mesh = ob->mesh;
if(pack.prim_segment[prim] != ~0) {
if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* curves */
int str_offset = (params.top_level)? mesh->curve_offset: 0;
int k0 = mesh->curves[pidx - str_offset].first_key + pack.prim_segment[prim]; // XXX!
int k0 = mesh->curves[pidx - str_offset].first_key + PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
int k1 = k0 + 1;
float3 p[4];

View File

@ -52,8 +52,8 @@ struct PackedBVH {
array<int> object_node;
/* precomputed triangle intersection data, one triangle is 4x float4 */
array<float4> tri_woop;
/* primitive type - triangle or strand (should be moved to flag?) */
array<int> prim_segment;
/* primitive type - triangle or strand */
array<int> prim_type;
/* visibility visibilitys for primitives */
array<uint> prim_visibility;
/* mapping from BVH primitive index to true primitive index, as primitives

View File

@ -49,10 +49,10 @@ public:
/* Constructor / Destructor */
BVHBuild::BVHBuild(const vector<Object*>& objects_,
vector<int>& prim_segment_, vector<int>& prim_index_, vector<int>& prim_object_,
vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_,
const BVHParams& params_, Progress& progress_)
: objects(objects_),
prim_segment(prim_segment_),
prim_type(prim_type_),
prim_index(prim_index_),
prim_object(prim_object_),
params(params_),
@ -73,6 +73,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
for(uint j = 0; j < mesh->triangles.size(); j++) {
Mesh::Triangle t = mesh->triangles[j];
BoundBox bounds = BoundBox::empty;
PrimitiveType type = PRIMITIVE_TRIANGLE;
for(int k = 0; k < 3; k++) {
float3 co = mesh->verts[t.v[k]];
@ -80,7 +81,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
}
if(bounds.valid()) {
references.push_back(BVHReference(bounds, j, i, ~0));
references.push_back(BVHReference(bounds, j, i, type));
root.grow(bounds);
center.grow(bounds.center2());
}
@ -88,6 +89,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
for(uint j = 0; j < mesh->curves.size(); j++) {
Mesh::Curve curve = mesh->curves[j];
PrimitiveType type = PRIMITIVE_CURVE;
for(int k = 0; k < curve.num_keys - 1; k++) {
BoundBox bounds = BoundBox::empty;
@ -108,7 +110,9 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
bounds.grow(upper, mr);
if(bounds.valid()) {
references.push_back(BVHReference(bounds, j, i, k));
int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
root.grow(bounds);
center.grow(bounds.center2());
}
@ -118,7 +122,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
{
references.push_back(BVHReference(ob->bounds, -1, i, false));
references.push_back(BVHReference(ob->bounds, -1, i, 0));
root.grow(ob->bounds);
center.grow(ob->bounds.center2());
}
@ -207,7 +211,7 @@ BVHNode* BVHBuild::run()
progress_total = references.size();
progress_original_total = progress_total;
prim_segment.resize(references.size());
prim_type.resize(references.size());
prim_index.resize(references.size());
prim_object.resize(references.size());
@ -373,12 +377,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
if(start == prim_index.size()) {
assert(params.use_spatial_split);
prim_segment.push_back(ref->prim_segment());
prim_type.push_back(ref->prim_type());
prim_index.push_back(ref->prim_index());
prim_object.push_back(ref->prim_object());
}
else {
prim_segment[start] = ref->prim_segment();
prim_type[start] = ref->prim_type();
prim_index[start] = ref->prim_index();
prim_object[start] = ref->prim_object();
}
@ -401,7 +405,7 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
{
vector<int>& p_segment = prim_segment;
vector<int>& p_type = prim_type;
vector<int>& p_index = prim_index;
vector<int>& p_object = prim_object;
BoundBox bounds = BoundBox::empty;
@ -415,12 +419,12 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
if(range.start() + num == prim_index.size()) {
assert(params.use_spatial_split);
p_segment.push_back(ref.prim_segment());
p_type.push_back(ref.prim_type());
p_index.push_back(ref.prim_index());
p_object.push_back(ref.prim_object());
}
else {
p_segment[range.start() + num] = ref.prim_segment();
p_type[range.start() + num] = ref.prim_type();
p_index[range.start() + num] = ref.prim_index();
p_object[range.start() + num] = ref.prim_object();
}

View File

@ -44,7 +44,7 @@ public:
/* Constructor/Destructor */
BVHBuild(
const vector<Object*>& objects,
vector<int>& prim_segment,
vector<int>& prim_type,
vector<int>& prim_index,
vector<int>& prim_object,
const BVHParams& params,
@ -88,7 +88,7 @@ protected:
int num_original_references;
/* output primitive indexes and objects */
vector<int>& prim_segment;
vector<int>& prim_type;
vector<int>& prim_index;
vector<int>& prim_object;

View File

@ -98,22 +98,22 @@ class BVHReference
public:
__forceinline BVHReference() {}
__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_segment)
__forceinline BVHReference(const BoundBox& bounds_, int prim_index_, int prim_object_, int prim_type)
: rbounds(bounds_)
{
rbounds.min.w = __int_as_float(prim_index_);
rbounds.max.w = __int_as_float(prim_object_);
segment = prim_segment;
type = prim_type;
}
__forceinline const BoundBox& bounds() const { return rbounds; }
__forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
__forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
__forceinline int prim_segment() const { return segment; }
__forceinline int prim_type() const { return type; }
protected:
BoundBox rbounds;
uint segment;
uint type;
};
/* BVH Range

View File

@ -52,8 +52,8 @@ public:
else if(ra.prim_object() > rb.prim_object()) return false;
else if(ra.prim_index() < rb.prim_index()) return true;
else if(ra.prim_index() > rb.prim_index()) return false;
else if(ra.prim_segment() < rb.prim_segment()) return true;
else if(ra.prim_segment() > rb.prim_segment()) return false;
else if(ra.prim_type() < rb.prim_type()) return true;
else if(ra.prim_type() > rb.prim_type()) return false;
return false;
}

View File

@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
Object *ob = builder->objects[ref.prim_object()];
const Mesh *mesh = ob->mesh;
if (ref.prim_segment() == ~0) {
if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
const int *inds = mesh->triangles[ref.prim_index()].v;
const float3 *verts = &mesh->verts[0];
const float3* v1 = &verts[inds[2]];
@ -282,7 +282,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
}
else {
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
const int k0 = mesh->curves[ref.prim_index()].first_key + ref.prim_segment();
const int k0 = mesh->curves[ref.prim_index()].first_key + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type());
const int k1 = k0 + 1;
const float3* v0 = &mesh->curve_keys[k0].co;
const float3* v1 = &mesh->curve_keys[k1].co;
@ -318,8 +318,8 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH
right_bounds.intersect(ref.bounds());
/* set references */
left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_segment());
left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
}
CCL_NAMESPACE_END

View File

@ -204,19 +204,23 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
/* primitive intersection */
for(; primAddr < primAddr2; primAddr++) {
#if FEATURE(BVH_HAIR)
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
if(segment != ~0)
continue;
#endif
/* only primitives from the same object */
uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object;
if(tri_object == subsurface_object) {
if(tri_object != subsurface_object)
continue;
/* intersect ray against primitive */
triangle_intersect_subsurface(kg, isect_array, P, idir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
/* intersect ray against primitive */
uint type = kernel_tex_fetch(__prim_type, primAddr);
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
triangle_intersect_subsurface(kg, isect_array, P, idir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
break;
}
default: {
break;
}
}
}
}

View File

@ -249,26 +249,35 @@ ccl_device bool BVH_FUNCTION_NAME
/* primitive intersection */
while(primAddr < primAddr2) {
bool hit;
uint type = kernel_tex_fetch(__prim_type, primAddr);
/* intersect ray against primitive */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
break;
}
#if FEATURE(BVH_HAIR)
uint segment = kernel_tex_fetch(__prim_segment, primAddr);
if(segment != ~0) {
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
case PRIMITIVE_CURVE: {
#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment, lcg_state, difl, extmax);
else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment, lcg_state, difl, extmax);
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
#else
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment);
else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, segment);
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type);
else
hit = bvh_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type);
#endif
break;
}
#endif
default: {
hit = false;
break;
}
}
else
#endif
hit = triangle_intersect(kg, isect, P, idir, visibility, object, primAddr);
/* shadow ray early termination */
#if defined(__KERNEL_SSE2__)

View File

@ -30,7 +30,7 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
}
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment;
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float f0 = kernel_tex_fetch(__attributes_float, offset + k0);
@ -69,7 +69,7 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
}
else if(elem == ATTR_ELEMENT_CURVE_KEY || elem == ATTR_ELEMENT_CURVE_KEY_MOTION) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment;
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + k0));
@ -98,9 +98,9 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{
float r = 0.0f;
if(sd->segment != ~0) {
if(sd->type & PRIMITIVE_ALL_CURVE) {
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
int k0 = __float_as_int(curvedata.x) + sd->segment;
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
@ -115,7 +115,7 @@ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
if(sd->segment != ~0) {
if(sd->type & PRIMITIVE_ALL_CURVE) {
tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu)));
tgN = normalize(tgN);
@ -192,12 +192,13 @@ ccl_device_inline __m128 transform_point_T3(const __m128 t[3], const __m128 &a)
#ifdef __KERNEL_SSE2__
/* Pass P and idir by reference to aligned vector */
ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
const float3 &P, const float3 &idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax)
const float3 &P, const float3 &idir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
#else
ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax)
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time,int type, uint *lcg_state, float difl, float extmax)
#endif
{
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
float epsilon = 0.0f;
float r_st, r_en;
@ -548,7 +549,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
/* record intersection */
isect->prim = curveAddr;
isect->object = object;
isect->segment = segment;
isect->type = type;
isect->u = u;
isect->v = 0.0f;
/*isect->v = 1.0f - coverage; */
@ -569,7 +570,7 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
}
ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int segment, uint *lcg_state, float difl, float extmax)
float3 P, float3 idir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
{
/* define few macros to minimize code duplication for SSE */
#ifndef __KERNEL_SSE2__
@ -578,6 +579,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
#define dot3(x, y) dot(x, y)
#endif
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
/* curve Intersection check */
int flags = kernel_data.curve.curveflags;
@ -768,7 +770,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
/* record intersection */
isect->prim = curveAddr;
isect->object = object;
isect->segment = segment;
isect->type = type;
isect->u = z*invl;
isect->v = td/(4*a*a);
/*isect->v = 1.0f - adjradius;*/
@ -841,7 +843,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 v00 = kernel_tex_fetch(__curves, prim);
int k0 = __float_as_int(v00.x) + sd->segment;
int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float3 tg;

View File

@ -290,6 +290,7 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect
/* record intersection */
isect->prim = triAddr;
isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
isect->u = u;
isect->v = v;
isect->t = t;
@ -353,6 +354,7 @@ ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersec
Intersection *isect = &isect_array[hit];
isect->prim = triAddr;
isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
isect->u = u;
isect->v = v;
isect->t = t;

View File

@ -43,12 +43,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando,
else
#endif
{
#ifdef __HAIR__
if(ls->type == LIGHT_STRAND)
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, ls->prim);
else
#endif
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1, ~0);
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time, bounce+1);
ls->Ng = sd.Ng;
@ -171,7 +166,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
float3 L = shader_emissive_eval(kg, sd);
#ifdef __HAIR__
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->segment == ~0)) {
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE)) {
#else
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS)) {
#endif

View File

@ -36,7 +36,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id,
/* for SVM, find attribute by unique id */
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
attr_offset = (sd->type & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
#endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
@ -58,7 +58,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id,
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
#ifdef __HAIR__
if(sd->segment == ~0)
if(sd->type & PRIMITIVE_ALL_TRIANGLE)
#endif
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__
@ -70,7 +70,7 @@ ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
#ifdef __HAIR__
if(sd->segment == ~0)
if(sd->type & PRIMITIVE_ALL_TRIANGLE)
#endif
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
#ifdef __HAIR__
@ -126,7 +126,7 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
if(sd->segment != ~0)
if(sd->type & PRIMITIVE_ALL_CURVE)
#ifdef __DPDU__
return normalize(sd->dPdu);
#else

View File

@ -55,6 +55,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->object = (isect->object == ~0)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
sd->type = isect->type;
sd->flag = kernel_tex_fetch(__object_flag, sd->object);
/* matrices and time */
@ -67,34 +68,27 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->ray_length = isect->t;
sd->ray_depth = bounce;
#ifdef __UV__
sd->u = isect->u;
sd->v = isect->v;
#endif
#ifdef __HAIR__
if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) {
/* Strand Shader setting*/
if(sd->type & PRIMITIVE_ALL_CURVE) {
/* curve */
float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
sd->shader = __float_as_int(curvedata.z);
sd->segment = isect->segment;
sd->P = bvh_curve_refine(kg, sd, isect, ray);
}
else {
else
#endif
{
/* fetch triangle data */
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
sd->shader = __float_as_int(Ns.w);
#ifdef __HAIR__
sd->segment = ~0;
/*elements for minimum hair width using transparency bsdf*/
/*sd->curve_transparency = 0.0f;*/
/*sd->curve_radius = 0.0f;*/
#endif
#ifdef __UV__
sd->u = isect->u;
sd->v = isect->v;
#endif
/* vectors */
sd->P = triangle_refine(kg, sd, isect, ray);
sd->Ng = Ng;
@ -108,10 +102,7 @@ ccl_device void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
/* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif
#ifdef __HAIR__
}
#endif
sd->I = -ray->D;
@ -161,34 +152,32 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
/* object, matrices, time, ray_length stay the same */
sd->flag = kernel_tex_fetch(__object_flag, sd->object);
sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
/* fetch triangle data */
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
sd->shader = __float_as_int(Ns.w);
#ifdef __HAIR__
sd->segment = ~0;
#endif
sd->type = isect->type;
#ifdef __UV__
sd->u = isect->u;
sd->v = isect->v;
#endif
/* vectors */
sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
sd->Ng = Ng;
sd->N = Ng;
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
/* fetch triangle data */
{
float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim);
float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
sd->shader = __float_as_int(Ns.w);
/* static triangle */
sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
sd->Ng = Ng;
sd->N = Ng;
if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __DPDU__
/* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
/* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif
}
sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
@ -231,7 +220,7 @@ ccl_device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderDat
ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
const float3 P, const float3 Ng, const float3 I,
int shader, int object, int prim, float u, float v, float t, float time, int bounce, int segment)
int shader, int object, int prim, float u, float v, float t, float time, int bounce)
{
/* vectors */
sd->P = P;
@ -239,9 +228,7 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
sd->Ng = Ng;
sd->I = I;
sd->shader = shader;
#ifdef __HAIR__
sd->segment = segment;
#endif
sd->type = (prim == ~0)? PRIMITIVE_NONE: PRIMITIVE_TRIANGLE;
/* primitive */
#ifdef __INSTANCING__
@ -283,35 +270,19 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
}
#endif
/* smooth normal */
#ifdef __HAIR__
if(sd->shader & SHADER_SMOOTH_NORMAL && sd->segment == ~0) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#else
if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#endif
if(sd->type & PRIMITIVE_TRIANGLE) {
/* smooth normal */
if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __INSTANCING__
if(instanced)
object_normal_transform(kg, sd, &sd->N);
if(instanced)
object_normal_transform(kg, sd, &sd->N);
#endif
}
}
/* dPdu/dPdv */
#ifdef __DPDU__
/* dPdu/dPdv */
#ifdef __HAIR__
if(sd->prim == ~0 || sd->segment != ~0) {
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
}
#else
if(sd->prim == ~0) {
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
}
#endif
else {
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#ifdef __INSTANCING__
@ -320,8 +291,14 @@ ccl_device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
object_dir_transform(kg, sd, &sd->dPdv);
}
#endif
}
#endif
}
else {
#ifdef __DPDU__
sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* backfacing test */
if(sd->prim != ~0) {
@ -362,7 +339,7 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
/* watch out: no instance transform currently */
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0, ~0);
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID, 0);
}
/* ShaderData setup from ray into background */
@ -429,9 +406,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->object = ~0; /* todo: fill this for texture coordinates */
#endif
sd->prim = ~0;
#ifdef __HAIR__
sd->segment = ~0;
#endif
sd->type = PRIMITIVE_NONE;
#ifdef __UV__
sd->u = 0.0f;
@ -1146,7 +1121,7 @@ ccl_device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect
int shader = 0;
#ifdef __HAIR__
if(kernel_tex_fetch(__prim_segment, isect->prim) == ~0) {
if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE) {
#endif
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
shader = __float_as_int(Ns.w);

View File

@ -25,7 +25,7 @@
/* bvh */
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
KERNEL_TEX(float4, texture_float4, __tri_woop)
KERNEL_TEX(uint, texture_uint, __prim_segment)
KERNEL_TEX(uint, texture_uint, __prim_type)
KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index)
KERNEL_TEX(uint, texture_uint, __prim_object)

View File

@ -420,9 +420,27 @@ typedef struct Intersection {
float t, u, v;
int prim;
int object;
int segment;
int type;
} Intersection;
/* Primitives */
typedef enum PrimitiveType {
PRIMITIVE_NONE = 0,
PRIMITIVE_TRIANGLE = 1,
PRIMITIVE_MOTION_TRIANGLE = 2,
PRIMITIVE_CURVE = 4,
PRIMITIVE_MOTION_CURVE = 8,
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)
#define PRIMITIVE_UNPACK_SEGMENT(type) (type >> 16)
/* Attributes */
#define ATTR_PRIM_TYPES 2
@ -565,13 +583,9 @@ typedef struct ShaderData {
/* primitive id if there is one, ~0 otherwise */
int prim;
#ifdef __HAIR__
/* for curves, segment number in curve, ~0 for triangles */
int segment;
/* variables for minimum hair width using transparency bsdf */
/*float curve_transparency; */
/*float curve_radius; */
#endif
/* combined type and curve segment for hair */
int type;
/* parametric coordinates
* - barycentric weights for triangles */
float u, v;

View File

@ -643,7 +643,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
}
else if ((name == u_geom_trianglevertices || name == u_geom_polyvertices)
#ifdef __HAIR__
&& sd->segment == ~0) {
&& sd->type & PRIMITIVE_ALL_TRIANGLE) {
#else
) {
#endif
@ -669,7 +669,7 @@ bool OSLRenderServices::get_object_standard_attribute(KernelGlobals *kg, ShaderD
#ifdef __HAIR__
/* Hair Attributes */
else if (name == u_is_curve) {
float f = (sd->segment != ~0);
float f = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
return set_attribute_float(f, type, derivatives, val);
}
else if (name == u_curve_thickness) {
@ -732,7 +732,8 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
{
ShaderData *sd = (ShaderData *)renderstate;
KernelGlobals *kg = sd->osl_globals;
int object, prim, segment;
bool is_curve;
int object, prim;
/* lookup of attribute on another object */
if (object_name != u_empty) {
@ -743,23 +744,19 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
object = it->second;
prim = ~0;
segment = ~0;
is_curve = false;
}
else {
object = sd->object;
prim = sd->prim;
#ifdef __HAIR__
segment = sd->segment;
#else
segment = ~0;
#endif
is_curve = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
if (object == ~0)
return get_background_attribute(kg, sd, name, type, derivatives, val);
}
/* find attribute on object */
object = object*ATTR_PRIM_TYPES + (segment != ~0);
object = object*ATTR_PRIM_TYPES + (is_curve == true);
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);

View File

@ -536,7 +536,7 @@ int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id,
/* for OSL, a hash map is used to lookup the attribute by name. */
int object = sd->object*ATTR_PRIM_TYPES;
#ifdef __HAIR__
if(sd->segment != ~0) object += ATTR_PRIM_CURVE;
if(sd->type & PRIMITIVE_ALL_CURVE) object += ATTR_PRIM_CURVE;
#endif
OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];

View File

@ -27,7 +27,7 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
uint id = node.y;
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
#ifdef __HAIR__
attr_offset = (sd->segment == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
attr_offset = (sd->type & PRIMITIVE_ALL_TRIANGLE)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
#endif
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);

View File

@ -364,7 +364,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
if(sd->flag & SD_BACKFACING && sd->segment != ~0) {
if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
sc->weight = make_float3(1.0f,1.0f,1.0f);
@ -381,7 +381,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
sc->data0 = param1;
sc->data1 = param2;
sc->offset = -stack_load_float(stack, data_node.z);
if(sd->segment == ~0) {
if(sd->type & PRIMITIVE_ALL_CURVE) {
sc->T = normalize(sd->dPdv);
sc->offset = 0.0f;
}

View File

@ -153,7 +153,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg, ShaderData *sd, float *sta
switch(type) {
case NODE_INFO_CURVE_IS_STRAND: {
data = (sd->segment != ~0);
data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
stack_store_float(stack, out_offset, data);
break;
}

View File

@ -45,7 +45,7 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta
/* Calculate wireframe */
#ifdef __HAIR__
if (sd->prim != ~0 && sd->segment == ~0) {
if (sd->prim != ~0 && sd->type & PRIMITIVE_ALL_TRIANGLE) {
#else
if (sd->prim != ~0) {
#endif

View File

@ -873,9 +873,9 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
device->tex_alloc("__tri_woop", dscene->tri_woop);
}
if(pack.prim_segment.size()) {
dscene->prim_segment.reference((uint*)&pack.prim_segment[0], pack.prim_segment.size());
device->tex_alloc("__prim_segment", dscene->prim_segment);
if(pack.prim_type.size()) {
dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size());
device->tex_alloc("__prim_type", dscene->prim_type);
}
if(pack.prim_visibility.size()) {
dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
@ -986,7 +986,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->bvh_nodes);
device->tex_free(dscene->object_node);
device->tex_free(dscene->tri_woop);
device->tex_free(dscene->prim_segment);
device->tex_free(dscene->prim_type);
device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index);
device->tex_free(dscene->prim_object);
@ -1003,7 +1003,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->bvh_nodes.clear();
dscene->object_node.clear();
dscene->tri_woop.clear();
dscene->prim_segment.clear();
dscene->prim_type.clear();
dscene->prim_visibility.clear();
dscene->prim_index.clear();
dscene->prim_object.clear();

View File

@ -60,7 +60,7 @@ public:
device_vector<float4> bvh_nodes;
device_vector<uint> object_node;
device_vector<float4> tri_woop;
device_vector<uint> prim_segment;
device_vector<uint> prim_type;
device_vector<uint> prim_visibility;
device_vector<uint> prim_index;
device_vector<uint> prim_object;