Cycles Hair: refactoring to support generic attributes for hair curves. There
should be no functional changes yet. UV, tangent and intercept are now stored as attributes, with the intention to add more like multiple uv's, vertex colors, generated coordinates and motion vectors later. Things got a bit messy due to having both triangle and curve data in the same mesh data structure, which also gives us two sets of attributes. This will get cleaned up when we split the mesh class.
This commit is contained in:
183
intern/cycles/kernel/kernel_primitive.h
Normal file
183
intern/cycles/kernel/kernel_primitive.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __KERNEL_ATTRIBUTE_CL__
|
||||
#define __KERNEL_ATTRIBUTE_CL__
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* attribute lookup */
|
||||
|
||||
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id, AttributeElement *elem)
|
||||
{
|
||||
if(sd->object == ~0)
|
||||
return (int)ATTR_STD_NOT_FOUND;
|
||||
|
||||
#ifdef __OSL__
|
||||
if (kg->osl) {
|
||||
return OSLShader::find_attribute(kg, sd, id, elem);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* for SVM, find attribute by unique id */
|
||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||
attr_offset = (sd->curve_seg == ~0)? attr_offset: attr_offset + ATTR_PRIM_CURVE;
|
||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
|
||||
while(attr_map.x != id) {
|
||||
attr_offset += ATTR_PRIM_TYPES;
|
||||
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
}
|
||||
|
||||
*elem = (AttributeElement)attr_map.y;
|
||||
|
||||
/* return result */
|
||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
||||
}
|
||||
}
|
||||
|
||||
__device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
||||
{
|
||||
#ifdef __HAIR__
|
||||
if(sd->curve_seg == ~0)
|
||||
#endif
|
||||
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||
#ifdef __HAIR__
|
||||
else
|
||||
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
|
||||
#endif
|
||||
}
|
||||
|
||||
__device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
||||
{
|
||||
#ifdef __HAIR__
|
||||
if(sd->curve_seg == ~0)
|
||||
#endif
|
||||
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||
#ifdef __HAIR__
|
||||
else
|
||||
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
|
||||
#endif
|
||||
}
|
||||
|
||||
__device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
AttributeElement elem_uv;
|
||||
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
|
||||
|
||||
if(offset_uv == ATTR_STD_NOT_FOUND)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
|
||||
uv.z = 1.0f;
|
||||
return uv;
|
||||
}
|
||||
|
||||
__device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
#ifdef __HAIR__
|
||||
if(sd->curve_seg != ~0)
|
||||
return normalize(sd->dPdu);
|
||||
#endif
|
||||
|
||||
/* try to create spherical tangent from generated coordinates */
|
||||
AttributeElement attr_elem;
|
||||
int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
|
||||
|
||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
||||
float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
|
||||
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
|
||||
object_normal_transform(kg, sd, &data);
|
||||
return cross(sd->N, normalize(cross(data, sd->N)));;
|
||||
}
|
||||
else {
|
||||
/* otherwise use surface derivatives */
|
||||
return normalize(sd->dPdu);
|
||||
}
|
||||
}
|
||||
|
||||
/* motion */
|
||||
|
||||
__device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
float3 motion_pre = sd->P, motion_post = sd->P;
|
||||
|
||||
/* deformation motion */
|
||||
AttributeElement elem_pre, elem_post;
|
||||
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre);
|
||||
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post);
|
||||
|
||||
if(offset_pre != ATTR_STD_NOT_FOUND)
|
||||
motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL);
|
||||
if(offset_post != ATTR_STD_NOT_FOUND)
|
||||
motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL);
|
||||
|
||||
/* object motion. note that depending on the mesh having motion vectors, this
|
||||
* transformation was set match the world/object space of motion_pre/post */
|
||||
Transform tfm;
|
||||
|
||||
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
|
||||
motion_pre = transform_point(&tfm, motion_pre);
|
||||
|
||||
tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
|
||||
motion_post = transform_point(&tfm, motion_post);
|
||||
|
||||
float3 P;
|
||||
|
||||
/* camera motion, for perspective/orthographic motion.pre/post will be a
|
||||
* world-to-raster matrix, for panorama it's world-to-camera */
|
||||
if (kernel_data.cam.type != CAMERA_PANORAMA) {
|
||||
tfm = kernel_data.cam.worldtoraster;
|
||||
P = transform_perspective(&tfm, sd->P);
|
||||
|
||||
tfm = kernel_data.cam.motion.pre;
|
||||
motion_pre = transform_perspective(&tfm, motion_pre);
|
||||
|
||||
tfm = kernel_data.cam.motion.post;
|
||||
motion_post = transform_perspective(&tfm, motion_post);
|
||||
}
|
||||
else {
|
||||
tfm = kernel_data.cam.worldtocamera;
|
||||
P = normalize(transform_point(&tfm, sd->P));
|
||||
P = float2_to_float3(direction_to_panorama(kg, P));
|
||||
P.x *= kernel_data.cam.width;
|
||||
P.y *= kernel_data.cam.height;
|
||||
|
||||
tfm = kernel_data.cam.motion.pre;
|
||||
motion_pre = normalize(transform_point(&tfm, motion_pre));
|
||||
motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
|
||||
motion_pre.x *= kernel_data.cam.width;
|
||||
motion_pre.y *= kernel_data.cam.height;
|
||||
|
||||
tfm = kernel_data.cam.motion.post;
|
||||
motion_post = normalize(transform_point(&tfm, motion_post));
|
||||
motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
|
||||
motion_post.x *= kernel_data.cam.width;
|
||||
motion_post.y *= kernel_data.cam.height;
|
||||
}
|
||||
|
||||
motion_pre = motion_pre - P;
|
||||
motion_post = P - motion_post;
|
||||
|
||||
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __KERNEL_ATTRIBUTE_CL__ */
|
Reference in New Issue
Block a user