2013-01-03 12:08:54 +00:00
|
|
|
/*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Copyright 2011-2013 Blender Foundation
|
2013-01-03 12:08:54 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2013-01-03 12:08:54 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2013-01-03 12:08:54 +00:00
|
|
|
*
|
2013-08-18 14:16:15 +00:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License
|
2013-01-03 12:08:54 +00:00
|
|
|
*/
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Primitive Utilities
|
|
|
|
*
|
|
|
|
* Generic functions to look up mesh, curve and volume primitive attributes for
|
|
|
|
* shading and render passes. */
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Generic primitive attribute reading functions */
|
2013-01-03 12:08:54 +00:00
|
|
|
|
2013-11-15 23:17:10 +00:00
|
|
|
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
|
2013-01-03 12:08:54 +00:00
|
|
|
{
|
2014-03-29 12:03:48 +00:00
|
|
|
if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
|
2013-01-03 12:08:54 +00:00
|
|
|
return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
|
2014-03-29 12:03:48 +00:00
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
#ifdef __HAIR__
|
2014-03-29 12:03:48 +00:00
|
|
|
else if(sd->type & PRIMITIVE_ALL_CURVE) {
|
2013-01-03 12:08:54 +00:00
|
|
|
return curve_attribute_float(kg, sd, elem, offset, dx, dy);
|
2014-03-29 12:03:48 +00:00
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
#endif
|
2014-03-29 12:03:48 +00:00
|
|
|
#ifdef __VOLUME__
|
|
|
|
else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
|
|
|
|
return volume_attribute_float(kg, sd, elem, offset, dx, dy);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
else {
|
|
|
|
if(dx) *dx = 0.0f;
|
|
|
|
if(dy) *dy = 0.0f;
|
|
|
|
return 0.0f;
|
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
}
|
|
|
|
|
2013-11-15 23:17:10 +00:00
|
|
|
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
|
2013-01-03 12:08:54 +00:00
|
|
|
{
|
2014-03-29 12:03:48 +00:00
|
|
|
if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
|
2013-01-03 12:08:54 +00:00
|
|
|
return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
|
2014-03-29 12:03:48 +00:00
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
#ifdef __HAIR__
|
2014-03-29 12:03:48 +00:00
|
|
|
else if(sd->type & PRIMITIVE_ALL_CURVE) {
|
2013-01-03 12:08:54 +00:00
|
|
|
return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
|
2014-03-29 12:03:48 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef __VOLUME__
|
|
|
|
else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
|
|
|
|
return volume_attribute_float3(kg, sd, elem, offset, dx, dy);
|
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
#endif
|
2014-03-29 12:03:48 +00:00
|
|
|
else {
|
|
|
|
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
return make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
}
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Default UV coordinate */
|
2013-12-31 16:33:55 +00:00
|
|
|
|
2013-11-15 23:17:10 +00:00
|
|
|
ccl_device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
|
2013-01-03 12:08:54 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Ptex coordinates */
|
|
|
|
|
2013-11-28 00:28:57 +00:00
|
|
|
ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
|
|
|
|
{
|
|
|
|
/* storing ptex data as attributes is not memory efficient but simple for tests */
|
|
|
|
AttributeElement elem_face_id, elem_uv;
|
|
|
|
int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id);
|
|
|
|
int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv);
|
|
|
|
|
|
|
|
if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
|
|
|
|
float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL);
|
|
|
|
|
|
|
|
*uv = make_float2(uv3.x, uv3.y);
|
|
|
|
*face_id = (int)face_id_f;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Surface tangent */
|
|
|
|
|
2013-11-15 23:17:10 +00:00
|
|
|
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
|
2013-01-03 12:08:54 +00:00
|
|
|
{
|
|
|
|
#ifdef __HAIR__
|
2014-03-29 12:03:46 +00:00
|
|
|
if(sd->type & PRIMITIVE_ALL_CURVE)
|
2013-09-27 19:09:31 +00:00
|
|
|
#ifdef __DPDU__
|
2013-01-03 12:08:54 +00:00
|
|
|
return normalize(sd->dPdu);
|
2013-09-27 19:09:31 +00:00
|
|
|
#else
|
|
|
|
return make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
#endif
|
2013-01-03 12:08:54 +00:00
|
|
|
#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);
|
2013-01-20 14:50:50 +00:00
|
|
|
return cross(sd->N, normalize(cross(data, sd->N)));
|
2013-01-03 12:08:54 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* otherwise use surface derivatives */
|
2013-09-27 19:09:31 +00:00
|
|
|
#ifdef __DPDU__
|
2013-01-03 12:08:54 +00:00
|
|
|
return normalize(sd->dPdu);
|
2013-09-27 19:09:31 +00:00
|
|
|
#else
|
|
|
|
return make_float3(0.0f, 0.0f, 0.0f);
|
|
|
|
#endif
|
2013-01-03 12:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-29 12:03:48 +00:00
|
|
|
/* Motion vector for motion pass */
|
2013-01-03 12:08:54 +00:00
|
|
|
|
2013-11-15 23:17:10 +00:00
|
|
|
ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
2013-01-03 12:08:54 +00:00
|
|
|
{
|
2014-05-09 13:32:13 +00:00
|
|
|
/* center position */
|
|
|
|
float3 center;
|
|
|
|
|
2014-05-29 10:38:03 +00:00
|
|
|
#ifdef __HAIR__
|
2014-11-18 13:58:33 +00:00
|
|
|
bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
|
|
|
|
if(is_curve_primitive) {
|
2014-05-09 13:32:13 +00:00
|
|
|
center = curve_motion_center_location(kg, sd);
|
|
|
|
|
|
|
|
if(!(sd->flag & SD_TRANSFORM_APPLIED))
|
|
|
|
object_position_transform(kg, sd, ¢er);
|
|
|
|
}
|
|
|
|
else
|
2014-05-29 10:38:03 +00:00
|
|
|
#endif
|
2014-05-09 13:32:13 +00:00
|
|
|
center = sd->P;
|
|
|
|
|
|
|
|
float3 motion_pre = center, motion_post = center;
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
/* deformation motion */
|
2014-03-29 12:03:46 +00:00
|
|
|
AttributeElement elem;
|
|
|
|
int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
|
|
|
|
|
|
|
|
if(offset != ATTR_STD_NOT_FOUND) {
|
|
|
|
/* get motion info */
|
|
|
|
int numverts, numkeys;
|
|
|
|
object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
|
|
|
|
|
|
|
|
/* lookup attributes */
|
|
|
|
int offset_next = (sd->type & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys;
|
|
|
|
|
|
|
|
motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
|
|
|
|
motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL);
|
2014-11-18 13:58:33 +00:00
|
|
|
|
|
|
|
#ifdef __HAIR__
|
2014-11-18 21:42:22 +00:00
|
|
|
if(is_curve_primitive && (sd->flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
|
2014-11-18 13:58:33 +00:00
|
|
|
object_position_transform(kg, sd, &motion_pre);
|
|
|
|
object_position_transform(kg, sd, &motion_post);
|
|
|
|
}
|
|
|
|
#endif
|
2014-03-29 12:03:46 +00:00
|
|
|
}
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2014-05-09 13:32:13 +00:00
|
|
|
float3 motion_center;
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
/* 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;
|
2014-05-09 13:32:13 +00:00
|
|
|
motion_center = transform_perspective(&tfm, center);
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
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;
|
2014-05-09 13:32:13 +00:00
|
|
|
motion_center = normalize(transform_point(&tfm, center));
|
|
|
|
motion_center = float2_to_float3(direction_to_panorama(kg, motion_center));
|
|
|
|
motion_center.x *= kernel_data.cam.width;
|
|
|
|
motion_center.y *= kernel_data.cam.height;
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-05-09 13:32:13 +00:00
|
|
|
motion_pre = motion_pre - motion_center;
|
|
|
|
motion_post = motion_center - motion_post;
|
2013-01-03 12:08:54 +00:00
|
|
|
|
|
|
|
return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|