Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/geom/object.h')
-rw-r--r--intern/cycles/kernel/geom/object.h600
1 files changed, 600 insertions, 0 deletions
diff --git a/intern/cycles/kernel/geom/object.h b/intern/cycles/kernel/geom/object.h
new file mode 100644
index 00000000000..34a9d639d9d
--- /dev/null
+++ b/intern/cycles/kernel/geom/object.h
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ */
+
+/* Object Primitive
+ *
+ * All mesh and curve primitives are part of an object. The same mesh and curves
+ * may be instanced multiple times by different objects.
+ *
+ * If the mesh is not instanced multiple times, the object will not be explicitly
+ * stored as a primitive in the BVH, rather the bare triangles are curved are
+ * directly primitives in the BVH with world space locations applied, and the object
+ * ID is looked up afterwards. */
+
+#pragma once
+
+CCL_NAMESPACE_BEGIN
+
+/* Object attributes, for now a fixed size and contents */
+
+enum ObjectTransform {
+ OBJECT_TRANSFORM = 0,
+ OBJECT_INVERSE_TRANSFORM = 1,
+};
+
+enum ObjectVectorTransform { OBJECT_PASS_MOTION_PRE = 0, OBJECT_PASS_MOTION_POST = 1 };
+
+/* Object to world space transformation */
+
+ccl_device_inline Transform object_fetch_transform(KernelGlobals kg,
+ int object,
+ enum ObjectTransform type)
+{
+ if (type == OBJECT_INVERSE_TRANSFORM) {
+ return kernel_tex_fetch(__objects, object).itfm;
+ }
+ else {
+ return kernel_tex_fetch(__objects, object).tfm;
+ }
+}
+
+/* Lamp to world space transformation */
+
+ccl_device_inline Transform lamp_fetch_transform(KernelGlobals kg, int lamp, bool inverse)
+{
+ if (inverse) {
+ return kernel_tex_fetch(__lights, lamp).itfm;
+ }
+ else {
+ return kernel_tex_fetch(__lights, lamp).tfm;
+ }
+}
+
+/* Object to world space transformation for motion vectors */
+
+ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals kg,
+ int object,
+ enum ObjectVectorTransform type)
+{
+ int offset = object * OBJECT_MOTION_PASS_SIZE + (int)type;
+ return kernel_tex_fetch(__object_motion_pass, offset);
+}
+
+/* Motion blurred object transformations */
+
+#ifdef __OBJECT_MOTION__
+ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals kg, int object, float time)
+{
+ const uint motion_offset = kernel_tex_fetch(__objects, object).motion_offset;
+ ccl_global const DecomposedTransform *motion = &kernel_tex_fetch(__object_motion, motion_offset);
+ const uint num_steps = kernel_tex_fetch(__objects, object).numsteps * 2 + 1;
+
+ Transform tfm;
+ transform_motion_array_interpolate(&tfm, motion, num_steps, time);
+
+ return tfm;
+}
+
+ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals kg,
+ int object,
+ float time,
+ ccl_private Transform *itfm)
+{
+ int object_flag = kernel_tex_fetch(__object_flag, object);
+ if (object_flag & SD_OBJECT_MOTION) {
+ /* if we do motion blur */
+ Transform tfm = object_fetch_transform_motion(kg, object, time);
+
+ if (itfm)
+ *itfm = transform_quick_inverse(tfm);
+
+ return tfm;
+ }
+ else {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
+ if (itfm)
+ *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+
+ return tfm;
+ }
+}
+#endif
+
+/* Get transform matrix for shading point. */
+
+ccl_device_inline Transform object_get_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd)
+{
+#ifdef __OBJECT_MOTION__
+ return (sd->object_flag & SD_OBJECT_MOTION) ?
+ sd->ob_tfm_motion :
+ object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+#else
+ return object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+#endif
+}
+
+ccl_device_inline Transform object_get_inverse_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd)
+{
+#ifdef __OBJECT_MOTION__
+ return (sd->object_flag & SD_OBJECT_MOTION) ?
+ sd->ob_itfm_motion :
+ object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+#else
+ return object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+}
+/* Transform position from object to world space */
+
+ccl_device_inline void object_position_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *P)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ *P = transform_point_auto(&sd->ob_tfm_motion, *P);
+ return;
+ }
+#endif
+
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *P = transform_point(&tfm, *P);
+}
+
+/* Transform position from world to object space */
+
+ccl_device_inline void object_inverse_position_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *P)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ *P = transform_point_auto(&sd->ob_itfm_motion, *P);
+ return;
+ }
+#endif
+
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *P = transform_point(&tfm, *P);
+}
+
+/* Transform normal from world to object space */
+
+ccl_device_inline void object_inverse_normal_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *N)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ if ((sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP)) {
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_tfm_motion, *N));
+ }
+ return;
+ }
+#endif
+
+ if (sd->object != OBJECT_NONE) {
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ Transform tfm = lamp_fetch_transform(kg, sd->lamp, false);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+ }
+}
+
+/* Transform normal from object to world space */
+
+ccl_device_inline void object_normal_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *N)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_itfm_motion, *N));
+ return;
+ }
+#endif
+
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *N = normalize(transform_direction_transposed(&tfm, *N));
+}
+
+/* Transform direction vector from object to world space */
+
+ccl_device_inline void object_dir_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *D)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ *D = transform_direction_auto(&sd->ob_tfm_motion, *D);
+ return;
+ }
+#endif
+
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ *D = transform_direction(&tfm, *D);
+}
+
+/* Transform direction vector from world to object space */
+
+ccl_device_inline void object_inverse_dir_transform(KernelGlobals kg,
+ ccl_private const ShaderData *sd,
+ ccl_private float3 *D)
+{
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ *D = transform_direction_auto(&sd->ob_itfm_motion, *D);
+ return;
+ }
+#endif
+
+ const Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+ *D = transform_direction(&tfm, *D);
+}
+
+/* Object center position */
+
+ccl_device_inline float3 object_location(KernelGlobals kg, ccl_private const ShaderData *sd)
+{
+ if (sd->object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+#ifdef __OBJECT_MOTION__
+ if (sd->object_flag & SD_OBJECT_MOTION) {
+ return make_float3(sd->ob_tfm_motion.x.w, sd->ob_tfm_motion.y.w, sd->ob_tfm_motion.z.w);
+ }
+#endif
+
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
+}
+
+/* Color of the object */
+
+ccl_device_inline float3 object_color(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object);
+ return make_float3(kobject->color[0], kobject->color[1], kobject->color[2]);
+}
+
+/* Pass ID number of object */
+
+ccl_device_inline float object_pass_id(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0.0f;
+
+ return kernel_tex_fetch(__objects, object).pass_id;
+}
+
+/* Per lamp random number for shader variation */
+
+ccl_device_inline float lamp_random_number(KernelGlobals kg, int lamp)
+{
+ if (lamp == LAMP_NONE)
+ return 0.0f;
+
+ return kernel_tex_fetch(__lights, lamp).random;
+}
+
+/* Per object random number for shader variation */
+
+ccl_device_inline float object_random_number(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0.0f;
+
+ return kernel_tex_fetch(__objects, object).random_number;
+}
+
+/* Particle ID from which this object was generated */
+
+ccl_device_inline int object_particle_id(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0;
+
+ return kernel_tex_fetch(__objects, object).particle_index;
+}
+
+/* Generated texture coordinate on surface from where object was instanced */
+
+ccl_device_inline float3 object_dupli_generated(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object);
+ return make_float3(
+ kobject->dupli_generated[0], kobject->dupli_generated[1], kobject->dupli_generated[2]);
+}
+
+/* UV texture coordinate on surface from where object was instanced */
+
+ccl_device_inline float3 object_dupli_uv(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return make_float3(0.0f, 0.0f, 0.0f);
+
+ ccl_global const KernelObject *kobject = &kernel_tex_fetch(__objects, object);
+ return make_float3(kobject->dupli_uv[0], kobject->dupli_uv[1], 0.0f);
+}
+
+/* Information about mesh for motion blurred triangles and curves */
+
+ccl_device_inline void object_motion_info(KernelGlobals kg,
+ int object,
+ ccl_private int *numsteps,
+ ccl_private int *numverts,
+ ccl_private int *numkeys)
+{
+ if (numkeys) {
+ *numkeys = kernel_tex_fetch(__objects, object).numkeys;
+ }
+
+ if (numsteps)
+ *numsteps = kernel_tex_fetch(__objects, object).numsteps;
+ if (numverts)
+ *numverts = kernel_tex_fetch(__objects, object).numverts;
+}
+
+/* Offset to an objects patch map */
+
+ccl_device_inline uint object_patch_map_offset(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0;
+
+ return kernel_tex_fetch(__objects, object).patch_map_offset;
+}
+
+/* Volume step size */
+
+ccl_device_inline float object_volume_density(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE) {
+ return 1.0f;
+ }
+
+ return kernel_tex_fetch(__objects, object).volume_density;
+}
+
+ccl_device_inline float object_volume_step_size(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE) {
+ return kernel_data.background.volume_step_size;
+ }
+
+ return kernel_tex_fetch(__object_volume_step, object);
+}
+
+/* Pass ID for shader */
+
+ccl_device int shader_pass_id(KernelGlobals kg, ccl_private const ShaderData *sd)
+{
+ return kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).pass_id;
+}
+
+/* Cryptomatte ID */
+
+ccl_device_inline float object_cryptomatte_id(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0.0f;
+
+ return kernel_tex_fetch(__objects, object).cryptomatte_object;
+}
+
+ccl_device_inline float object_cryptomatte_asset_id(KernelGlobals kg, int object)
+{
+ if (object == OBJECT_NONE)
+ return 0;
+
+ return kernel_tex_fetch(__objects, object).cryptomatte_asset;
+}
+
+/* Particle data from which object was instanced */
+
+ccl_device_inline uint particle_index(KernelGlobals kg, int particle)
+{
+ return kernel_tex_fetch(__particles, particle).index;
+}
+
+ccl_device float particle_age(KernelGlobals kg, int particle)
+{
+ return kernel_tex_fetch(__particles, particle).age;
+}
+
+ccl_device float particle_lifetime(KernelGlobals kg, int particle)
+{
+ return kernel_tex_fetch(__particles, particle).lifetime;
+}
+
+ccl_device float particle_size(KernelGlobals kg, int particle)
+{
+ return kernel_tex_fetch(__particles, particle).size;
+}
+
+ccl_device float4 particle_rotation(KernelGlobals kg, int particle)
+{
+ return kernel_tex_fetch(__particles, particle).rotation;
+}
+
+ccl_device float3 particle_location(KernelGlobals kg, int particle)
+{
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).location);
+}
+
+ccl_device float3 particle_velocity(KernelGlobals kg, int particle)
+{
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).velocity);
+}
+
+ccl_device float3 particle_angular_velocity(KernelGlobals kg, int particle)
+{
+ return float4_to_float3(kernel_tex_fetch(__particles, particle).angular_velocity);
+}
+
+/* Object intersection in BVH */
+
+ccl_device_inline float3 bvh_clamp_direction(float3 dir)
+{
+ const float ooeps = 8.271806E-25f;
+ return make_float3((fabsf(dir.x) > ooeps) ? dir.x : copysignf(ooeps, dir.x),
+ (fabsf(dir.y) > ooeps) ? dir.y : copysignf(ooeps, dir.y),
+ (fabsf(dir.z) > ooeps) ? dir.z : copysignf(ooeps, dir.z));
+}
+
+ccl_device_inline float3 bvh_inverse_direction(float3 dir)
+{
+ return rcp(dir);
+}
+
+/* Transform ray into object space to enter static object in BVH */
+
+ccl_device_inline float bvh_instance_push(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir)
+{
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+
+ *P = transform_point(&tfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+ return len;
+}
+
+/* Transform ray to exit static object in BVH. */
+
+ccl_device_inline float bvh_instance_pop(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir,
+ float t)
+{
+ if (t != FLT_MAX) {
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ t /= len(transform_direction(&tfm, ray->D));
+ }
+
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
+
+ return t;
+}
+
+/* Same as above, but returns scale factor to apply to multiple intersection distances */
+
+ccl_device_inline void bvh_instance_pop_factor(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir,
+ ccl_private float *t_fac)
+{
+ Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
+ *t_fac = 1.0f / len(transform_direction(&tfm, ray->D));
+
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
+}
+
+#ifdef __OBJECT_MOTION__
+/* Transform ray into object space to enter motion blurred object in BVH */
+
+ccl_device_inline float bvh_instance_motion_push(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir,
+ ccl_private Transform *itfm)
+{
+ object_fetch_transform_motion_test(kg, object, ray->time, itfm);
+
+ *P = transform_point(itfm, ray->P);
+
+ float len;
+ *dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
+ *idir = bvh_inverse_direction(*dir);
+
+ return len;
+}
+
+/* Transform ray to exit motion blurred object in BVH. */
+
+ccl_device_inline float bvh_instance_motion_pop(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir,
+ float t,
+ ccl_private Transform *itfm)
+{
+ if (t != FLT_MAX) {
+ t /= len(transform_direction(itfm, ray->D));
+ }
+
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
+
+ return t;
+}
+
+/* Same as above, but returns scale factor to apply to multiple intersection distances */
+
+ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals kg,
+ int object,
+ ccl_private const Ray *ray,
+ ccl_private float3 *P,
+ ccl_private float3 *dir,
+ ccl_private float3 *idir,
+ ccl_private float *t_fac,
+ ccl_private Transform *itfm)
+{
+ *t_fac = 1.0f / len(transform_direction(itfm, ray->D));
+ *P = ray->P;
+ *dir = bvh_clamp_direction(ray->D);
+ *idir = bvh_inverse_direction(*dir);
+}
+
+#endif
+
+/* TODO: This can be removed when we know if no devices will require explicit
+ * address space qualifiers for this case. */
+
+#define object_position_transform_auto object_position_transform
+#define object_dir_transform_auto object_dir_transform
+#define object_normal_transform_auto object_normal_transform
+
+CCL_NAMESPACE_END