Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/geom/geom_triangle.h
| Show All 17 Lines | |||||
| /* Triangle Primitive | /* Triangle Primitive | ||||
| * | * | ||||
| * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH | * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH | ||||
| * ray intersection we use a precomputed triangle storage to accelerate | * ray intersection we use a precomputed triangle storage to accelerate | ||||
| * intersection at the cost of more memory usage */ | * intersection at the cost of more memory usage */ | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* 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) | |||||
| { | |||||
| float3 P = ray->P; | |||||
| float3 D = ray->D; | |||||
| float t = isect->t; | |||||
| #ifdef __INTERSECTION_REFINE__ | |||||
| if(isect->object != OBJECT_NONE) { | |||||
| #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*t); | |||||
| D = normalize_len(D, &t); | |||||
| } | |||||
| 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 != OBJECT_NONE) { | |||||
| #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 | |||||
| } | |||||
| /* 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 != OBJECT_NONE) { | |||||
| #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 != OBJECT_NONE) { | |||||
| #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 on triangle */ | /* normal on triangle */ | ||||
| ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd) | ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd) | ||||
| { | { | ||||
| /* load triangle vertices */ | /* load triangle vertices */ | ||||
| float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); | float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim)); | ||||
| float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); | 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 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y))); | ||||
| Show All 32 Lines | ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader) | ||||
| /* shader`*/ | /* shader`*/ | ||||
| *shader = kernel_tex_fetch(__tri_shader, prim); | *shader = kernel_tex_fetch(__tri_shader, prim); | ||||
| } | } | ||||
| /* Triangle vertex locations */ | /* Triangle vertex locations */ | ||||
| ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3]) | ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3]) | ||||
| { | { | ||||
| float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim)); | float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim); | ||||
| P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x))); | 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[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))); | P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z))); | ||||
| } | } | ||||
| /* Interpolate smooth vertex normal from vertices */ | /* Interpolate smooth vertex normal from vertices */ | ||||
| ▲ Show 20 Lines • Show All 117 Lines • ▼ Show 20 Lines | #endif | ||||
| else { | else { | ||||
| if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); | if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f); | ||||
| if(dy) *dy = 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); | return make_float3(0.0f, 0.0f, 0.0f); | ||||
| } | } | ||||
| } | } | ||||
| /* Ray-Triangle intersection for BVH traversal | |||||
| * | |||||
| * Based on Sven Woop's algorithm with precomputed triangle storage */ | |||||
| ccl_device_inline bool triangle_intersect(KernelGlobals *kg, Intersection *isect, | |||||
| float3 P, float3 dir, 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); | |||||
| 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->type = PRIMITIVE_TRIANGLE; | |||||
| isect->u = u; | |||||
| isect->v = v; | |||||
| isect->t = t; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /* 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. */ | |||||
| #ifdef __SUBSURFACE__ | |||||
| ccl_device_inline void triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect_array, | |||||
| float3 P, float3 dir, 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); | |||||
| 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->type = PRIMITIVE_TRIANGLE; | |||||
| isect->u = u; | |||||
| isect->v = v; | |||||
| isect->t = t; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| #endif | |||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||