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:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:45 +0400
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:45 +0400
commit41d1675053b457370e70be137fd8105b9cd1890b (patch)
tree1c0567bc1441dd9bd55f9f5b184b7ce346aa2073 /intern/cycles/kernel/geom/geom_triangle.h
parent84470a1190b28cd37491e5002aea4695e4f26f44 (diff)
Cycles code refactor: move more geometry code into per primitive files.
Diffstat (limited to 'intern/cycles/kernel/geom/geom_triangle.h')
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h242
1 files changed, 214 insertions, 28 deletions
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 0455df85961..6eaa077584b 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -1,5 +1,6 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation
+ * Modifications Copyright 2011, Blender Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -11,61 +12,138 @@
* 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
+ * limitations under the License.
*/
CCL_NAMESPACE_BEGIN
-/* Point on triangle for Moller-Trumbore triangles */
-ccl_device_inline float3 triangle_point_MT(KernelGlobals *kg, int tri_index, float u, float v)
+/* Refine triangle intersection to more precise hit point. For rays that travel
+ * far the precision is often not so good, this reintersects the primitive from
+ * a closer distance. */
+
+ccl_device_inline float3 triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
{
- /* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
- float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
- float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D*t);
+ D = normalize_len(D, &t);
+ }
- /* compute point */
- float t = 1.0f - u - v;
- return (u*v0 + v*v1 + t*v2);
+ P = P + D*t;
+
+ float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
+ float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
+ float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
+ float rt = Oz * invDz;
+
+ P = P + D*rt;
+
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
}
-/* Normal for Moller-Trumbore triangles */
-ccl_device_inline float3 triangle_normal_MT(KernelGlobals *kg, int tri_index, int *shader)
+/* same as above, except that isect->t is assumed to be in object space for instancing */
+ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray)
+{
+ float3 P = ray->P;
+ float3 D = ray->D;
+ float t = isect->t;
+
+#ifdef __INTERSECTION_REFINE__
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_itfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ D = transform_direction(&tfm, D);
+ D = normalize(D);
+ }
+
+ P = P + D*t;
+
+ float4 v00 = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
+ float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
+ float invDz = 1.0f/(D.x*v00.x + D.y*v00.y + D.z*v00.z);
+ float rt = Oz * invDz;
+
+ P = P + D*rt;
+
+ if(isect->object != ~0) {
+#ifdef __OBJECT_MOTION__
+ Transform tfm = sd->ob_tfm;
+#else
+ Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
+#endif
+
+ P = transform_point(&tfm, P);
+ }
+
+ return P;
+#else
+ return P + D*t;
+#endif
+}
+
+/* point and normal on triangle */
+ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
{
-#if 0
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
- /* compute normal */
- return normalize(cross(v2 - v0, v1 - v0));
-#else
- float4 Nm = kernel_tex_fetch(__tri_normal, tri_index);
+ /* compute point */
+ float t = 1.0f - u - v;
+ *P = (u*v0 + v*v1 + t*v2);
+
+ float4 Nm = kernel_tex_fetch(__tri_normal, prim);
+ *Ng = make_float3(Nm.x, Nm.y, Nm.z);
*shader = __float_as_int(Nm.w);
- return make_float3(Nm.x, Nm.y, Nm.z);
-#endif
}
/* Return 3 triangle vertex locations */
-ccl_device_inline void triangle_vertices(KernelGlobals *kg, int tri_index, float3 P[3])
+ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
}
-ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v)
+ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, float u, float v)
{
/* load triangle vertices */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
@@ -74,10 +152,10 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index
return normalize((1.0f - u - v)*n2 + u*n0 + v*n1);
}
-ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dPdv, int tri)
+ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, float3 *dPdu, float3 *dPdv)
{
/* fetch triangle vertex coordinates */
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri));
+ float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
float3 p0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
float3 p1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
@@ -176,5 +254,113 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
}
}
+/* Sven Woop's algorithm */
+ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect,
+ float3 P, float3 idir, uint visibility, int object, int triAddr)
+{
+ /* compute and check intersection t-value */
+ float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
+ float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
+ float3 dir = 1.0f/idir;
+
+ float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
+ float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
+ float t = Oz * invDz;
+
+ if(t > 0.0f && t < isect->t) {
+ /* compute and check barycentric u */
+ float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
+ float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
+ float u = Ox + t*Dx;
+
+ if(u >= 0.0f) {
+ /* compute and check barycentric v */
+ float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
+ float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
+ float v = Oy + t*Dy;
+
+ if(v >= 0.0f && u + v <= 1.0f) {
+#ifdef __VISIBILITY_FLAG__
+ /* visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags */
+ if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
+#endif
+ {
+ /* record intersection */
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+#ifdef __SUBSURFACE__
+/* Special ray intersection routines for subsurface scattering. In that case we
+ * only want to intersect with primitives in the same object, and if case of
+ * multiple hits we pick a single random primitive as the intersection point. */
+
+ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect_array,
+ float3 P, float3 idir, int object, int triAddr, float tmax, uint *num_hits, uint *lcg_state, int max_hits)
+{
+ /* compute and check intersection t-value */
+ float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
+ float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
+ float3 dir = 1.0f/idir;
+
+ float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z;
+ float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z);
+ float t = Oz * invDz;
+
+ if(t > 0.0f && t < tmax) {
+ /* compute and check barycentric u */
+ float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z;
+ float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z;
+ float u = Ox + t*Dx;
+
+ if(u >= 0.0f) {
+ /* compute and check barycentric v */
+ float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z;
+ float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z;
+ float v = Oy + t*Dy;
+
+ if(v >= 0.0f && u + v <= 1.0f) {
+ (*num_hits)++;
+
+ int hit;
+
+ if(*num_hits <= max_hits) {
+ hit = *num_hits - 1;
+ }
+ else {
+ /* reservoir sampling: if we are at the maximum number of
+ * hits, randomly replace element or skip it */
+ hit = lcg_step_uint(lcg_state) % *num_hits;
+
+ if(hit >= max_hits)
+ return;
+ }
+
+ /* record intersection */
+ Intersection *isect = &isect_array[hit];
+ isect->prim = triAddr;
+ isect->object = object;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+ }
+ }
+ }
+}
+#endif
+
CCL_NAMESPACE_END