123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- /*
- * Copyright 2011-2013 Blender Foundation
- *
- * 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
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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.
- */
- /* Primitive Utilities
- *
- * Generic functions to look up mesh, curve and volume primitive attributes for
- * shading and render passes. */
- CCL_NAMESPACE_BEGIN
- /* Generic primitive attribute reading functions */
- ccl_device_inline float primitive_attribute_float(
- KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float(kg, sd, desc, dx, dy);
- }
- #endif
- #ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
- return volume_attribute_float(kg, sd, desc);
- }
- #endif
- else {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
- return 0.0f;
- }
- }
- ccl_device_inline float primitive_surface_attribute_float(
- KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float(kg, sd, desc, dx, dy);
- }
- #endif
- else {
- if (dx)
- *dx = 0.0f;
- if (dy)
- *dy = 0.0f;
- return 0.0f;
- }
- }
- #ifdef __VOLUME__
- ccl_device_inline float primitive_volume_attribute_float(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc)
- {
- if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float(kg, sd, desc);
- }
- else {
- return 0.0f;
- }
- }
- #endif
- ccl_device_inline float2 primitive_attribute_float2(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float2 *dx,
- float2 *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float2(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float2(kg, sd, desc, dx, dy);
- }
- #endif
- #ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- kernel_assert(0);
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
- #endif
- else {
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
- }
- ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float3 *dx,
- float3 *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float3(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float3(kg, sd, desc, dx, dy);
- }
- #endif
- #ifdef __VOLUME__
- else if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- if (dx)
- *dx = make_float3(0.0f, 0.0f, 0.0f);
- if (dy)
- *dy = make_float3(0.0f, 0.0f, 0.0f);
- return volume_attribute_float3(kg, sd, desc);
- }
- #endif
- 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);
- }
- }
- ccl_device_inline float2 primitive_surface_attribute_float2(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float2 *dx,
- float2 *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float2(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float2(kg, sd, desc, dx, dy);
- }
- #endif
- else {
- if (dx)
- *dx = make_float2(0.0f, 0.0f);
- if (dy)
- *dy = make_float2(0.0f, 0.0f);
- return make_float2(0.0f, 0.0f);
- }
- }
- ccl_device_inline float3 primitive_surface_attribute_float3(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc,
- float3 *dx,
- float3 *dy)
- {
- if (sd->type & PRIMITIVE_ALL_TRIANGLE) {
- if (subd_triangle_patch(kg, sd) == ~0)
- return triangle_attribute_float3(kg, sd, desc, dx, dy);
- else
- return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
- }
- #ifdef __HAIR__
- else if (sd->type & PRIMITIVE_ALL_CURVE) {
- return curve_attribute_float3(kg, sd, desc, dx, dy);
- }
- #endif
- 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);
- }
- }
- #ifdef __VOLUME__
- ccl_device_inline float3 primitive_volume_attribute_float3(KernelGlobals *kg,
- const ShaderData *sd,
- const AttributeDescriptor desc)
- {
- if (sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
- return volume_attribute_float3(kg, sd, desc);
- }
- else {
- return make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- #endif
- /* Default UV coordinate */
- ccl_device_inline float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
- {
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
- if (desc.offset == ATTR_STD_NOT_FOUND)
- return make_float3(0.0f, 0.0f, 0.0f);
- float2 uv = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
- return make_float3(uv.x, uv.y, 1.0f);
- }
- /* Ptex coordinates */
- 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 */
- const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
- const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
- if (desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND)
- return false;
- float3 uv3 = primitive_surface_attribute_float3(kg, sd, desc_uv, NULL, NULL);
- float face_id_f = primitive_surface_attribute_float(kg, sd, desc_face_id, NULL, NULL);
- *uv = make_float2(uv3.x, uv3.y);
- *face_id = (int)face_id_f;
- return true;
- }
- /* Surface tangent */
- ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
- {
- #ifdef __HAIR__
- if (sd->type & PRIMITIVE_ALL_CURVE)
- # ifdef __DPDU__
- return normalize(sd->dPdu);
- # else
- return make_float3(0.0f, 0.0f, 0.0f);
- # endif
- #endif
- /* try to create spherical tangent from generated coordinates */
- const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_GENERATED);
- if (desc.offset != ATTR_STD_NOT_FOUND) {
- float3 data = primitive_surface_attribute_float3(kg, sd, desc, 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 */
- #ifdef __DPDU__
- return normalize(sd->dPdu);
- #else
- return make_float3(0.0f, 0.0f, 0.0f);
- #endif
- }
- }
- /* Motion vector for motion pass */
- ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
- {
- /* center position */
- float3 center;
- #ifdef __HAIR__
- bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
- if (is_curve_primitive) {
- center = curve_motion_center_location(kg, sd);
- if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_position_transform(kg, sd, ¢er);
- }
- }
- else
- #endif
- center = sd->P;
- float3 motion_pre = center, motion_post = center;
- /* deformation motion */
- AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION);
- if (desc.offset != ATTR_STD_NOT_FOUND) {
- /* get motion info */
- int numverts, numkeys;
- object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
- /* lookup attributes */
- motion_pre = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
- desc.offset += (sd->type & PRIMITIVE_ALL_TRIANGLE) ? numverts : numkeys;
- motion_post = primitive_surface_attribute_float3(kg, sd, desc, NULL, NULL);
- #ifdef __HAIR__
- if (is_curve_primitive && (sd->object_flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
- object_position_transform(kg, sd, &motion_pre);
- object_position_transform(kg, sd, &motion_post);
- }
- #endif
- }
- /* 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_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_PRE);
- motion_pre = transform_point(&tfm, motion_pre);
- tfm = object_fetch_motion_pass_transform(kg, sd->object, OBJECT_PASS_MOTION_POST);
- motion_post = transform_point(&tfm, motion_post);
- float3 motion_center;
- /* 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) {
- ProjectionTransform projection = kernel_data.cam.worldtoraster;
- motion_center = transform_perspective(&projection, center);
- projection = kernel_data.cam.perspective_pre;
- motion_pre = transform_perspective(&projection, motion_pre);
- projection = kernel_data.cam.perspective_post;
- motion_post = transform_perspective(&projection, motion_post);
- }
- else {
- tfm = kernel_data.cam.worldtocamera;
- motion_center = normalize(transform_point(&tfm, center));
- motion_center = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_center));
- motion_center.x *= kernel_data.cam.width;
- motion_center.y *= kernel_data.cam.height;
- tfm = kernel_data.cam.motion_pass_pre;
- motion_pre = normalize(transform_point(&tfm, motion_pre));
- motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre));
- motion_pre.x *= kernel_data.cam.width;
- motion_pre.y *= kernel_data.cam.height;
- tfm = kernel_data.cam.motion_pass_post;
- motion_post = normalize(transform_point(&tfm, motion_post));
- motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post));
- motion_post.x *= kernel_data.cam.width;
- motion_post.y *= kernel_data.cam.height;
- }
- motion_pre = motion_pre - motion_center;
- motion_post = motion_center - motion_post;
- return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
- }
- CCL_NAMESPACE_END
|