diff options
Diffstat (limited to 'intern/cycles/kernel/geom/geom_patch.h')
-rw-r--r-- | intern/cycles/kernel/geom/geom_patch.h | 554 |
1 files changed, 303 insertions, 251 deletions
diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h index edb82172959..df19199f68e 100644 --- a/intern/cycles/kernel/geom/geom_patch.h +++ b/intern/cycles/kernel/geom/geom_patch.h @@ -27,342 +27,394 @@ CCL_NAMESPACE_BEGIN typedef struct PatchHandle { - int array_index, patch_index, vert_index; + int array_index, patch_index, vert_index; } PatchHandle; ccl_device_inline int patch_map_resolve_quadrant(float median, float *u, float *v) { - int quadrant = -1; - - if(*u < median) { - if(*v < median) { - quadrant = 0; - } - else { - quadrant = 1; - *v -= median; - } - } - else { - if(*v < median) { - quadrant = 3; - } - else { - quadrant = 2; - *v -= median; - } - *u -= median; - } - - return quadrant; + int quadrant = -1; + + if (*u < median) { + if (*v < median) { + quadrant = 0; + } + else { + quadrant = 1; + *v -= median; + } + } + else { + if (*v < median) { + quadrant = 3; + } + else { + quadrant = 2; + *v -= median; + } + *u -= median; + } + + return quadrant; } /* retrieve PatchHandle from patch coords */ -ccl_device_inline PatchHandle patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v) +ccl_device_inline PatchHandle +patch_map_find_patch(KernelGlobals *kg, int object, int patch, float u, float v) { - PatchHandle handle; + PatchHandle handle; - kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f)); + kernel_assert((u >= 0.0f) && (u <= 1.0f) && (v >= 0.0f) && (v <= 1.0f)); - int node = (object_patch_map_offset(kg, object) + patch)/2; - float median = 0.5f; + int node = (object_patch_map_offset(kg, object) + patch) / 2; + float median = 0.5f; - for(int depth = 0; depth < 0xff; depth++) { - float delta = median * 0.5f; + for (int depth = 0; depth < 0xff; depth++) { + float delta = median * 0.5f; - int quadrant = patch_map_resolve_quadrant(median, &u, &v); - kernel_assert(quadrant >= 0); + int quadrant = patch_map_resolve_quadrant(median, &u, &v); + kernel_assert(quadrant >= 0); - uint child = kernel_tex_fetch(__patches, node + quadrant); + uint child = kernel_tex_fetch(__patches, node + quadrant); - /* is the quadrant a hole? */ - if(!(child & PATCH_MAP_NODE_IS_SET)) { - handle.array_index = -1; - return handle; - } + /* is the quadrant a hole? */ + if (!(child & PATCH_MAP_NODE_IS_SET)) { + handle.array_index = -1; + return handle; + } - uint index = child & PATCH_MAP_NODE_INDEX_MASK; + uint index = child & PATCH_MAP_NODE_INDEX_MASK; - if(child & PATCH_MAP_NODE_IS_LEAF) { - handle.array_index = kernel_tex_fetch(__patches, index + 0); - handle.patch_index = kernel_tex_fetch(__patches, index + 1); - handle.vert_index = kernel_tex_fetch(__patches, index + 2); + if (child & PATCH_MAP_NODE_IS_LEAF) { + handle.array_index = kernel_tex_fetch(__patches, index + 0); + handle.patch_index = kernel_tex_fetch(__patches, index + 1); + handle.vert_index = kernel_tex_fetch(__patches, index + 2); - return handle; - } else { - node = index; - } + return handle; + } + else { + node = index; + } - median = delta; - } + median = delta; + } - /* no leaf found */ - kernel_assert(0); + /* no leaf found */ + kernel_assert(0); - handle.array_index = -1; - return handle; + handle.array_index = -1; + return handle; } ccl_device_inline void patch_eval_bspline_weights(float t, float *point, float *deriv) { - /* The four uniform cubic B-Spline basis functions evaluated at t */ - float inv_6 = 1.0f / 6.0f; - - float t2 = t * t; - float t3 = t * t2; - - point[0] = inv_6 * (1.0f - 3.0f*(t - t2) - t3); - point[1] = inv_6 * (4.0f - 6.0f*t2 + 3.0f*t3); - point[2] = inv_6 * (1.0f + 3.0f*(t + t2 - t3)); - point[3] = inv_6 * t3; - - /* Derivatives of the above four basis functions at t */ - deriv[0] = -0.5f*t2 + t - 0.5f; - deriv[1] = 1.5f*t2 - 2.0f*t; - deriv[2] = -1.5f*t2 + t + 0.5f; - deriv[3] = 0.5f*t2; + /* The four uniform cubic B-Spline basis functions evaluated at t */ + float inv_6 = 1.0f / 6.0f; + + float t2 = t * t; + float t3 = t * t2; + + point[0] = inv_6 * (1.0f - 3.0f * (t - t2) - t3); + point[1] = inv_6 * (4.0f - 6.0f * t2 + 3.0f * t3); + point[2] = inv_6 * (1.0f + 3.0f * (t + t2 - t3)); + point[3] = inv_6 * t3; + + /* Derivatives of the above four basis functions at t */ + deriv[0] = -0.5f * t2 + t - 0.5f; + deriv[1] = 1.5f * t2 - 2.0f * t; + deriv[2] = -1.5f * t2 + t + 0.5f; + deriv[3] = 0.5f * t2; } ccl_device_inline void patch_eval_adjust_boundary_weights(uint bits, float *s, float *t) { - int boundary = ((bits >> 8) & 0xf); - - if(boundary & 1) { - t[2] -= t[0]; - t[1] += 2*t[0]; - t[0] = 0; - } - - if(boundary & 2) { - s[1] -= s[3]; - s[2] += 2*s[3]; - s[3] = 0; - } - - if(boundary & 4) { - t[1] -= t[3]; - t[2] += 2*t[3]; - t[3] = 0; - } - - if(boundary & 8) { - s[2] -= s[0]; - s[1] += 2*s[0]; - s[0] = 0; - } + int boundary = ((bits >> 8) & 0xf); + + if (boundary & 1) { + t[2] -= t[0]; + t[1] += 2 * t[0]; + t[0] = 0; + } + + if (boundary & 2) { + s[1] -= s[3]; + s[2] += 2 * s[3]; + s[3] = 0; + } + + if (boundary & 4) { + t[1] -= t[3]; + t[2] += 2 * t[3]; + t[3] = 0; + } + + if (boundary & 8) { + s[2] -= s[0]; + s[1] += 2 * s[0]; + s[0] = 0; + } } ccl_device_inline int patch_eval_depth(uint patch_bits) { - return (patch_bits & 0xf); + return (patch_bits & 0xf); } ccl_device_inline float patch_eval_param_fraction(uint patch_bits) { - bool non_quad_root = (patch_bits >> 4) & 0x1; - int depth = patch_eval_depth(patch_bits); - - if(non_quad_root) { - return 1.0f / (float)(1 << (depth-1)); - } - else { - return 1.0f / (float)(1 << depth); - } + bool non_quad_root = (patch_bits >> 4) & 0x1; + int depth = patch_eval_depth(patch_bits); + + if (non_quad_root) { + return 1.0f / (float)(1 << (depth - 1)); + } + else { + return 1.0f / (float)(1 << depth); + } } ccl_device_inline void patch_eval_normalize_coords(uint patch_bits, float *u, float *v) { - float frac = patch_eval_param_fraction(patch_bits); + float frac = patch_eval_param_fraction(patch_bits); - int iu = (patch_bits >> 22) & 0x3ff; - int iv = (patch_bits >> 12) & 0x3ff; + int iu = (patch_bits >> 22) & 0x3ff; + int iv = (patch_bits >> 12) & 0x3ff; - /* top left corner */ - float pu = (float)iu*frac; - float pv = (float)iv*frac; + /* top left corner */ + float pu = (float)iu * frac; + float pv = (float)iv * frac; - /* normalize uv coordinates */ - *u = (*u - pu) / frac; - *v = (*v - pv) / frac; + /* normalize uv coordinates */ + *u = (*u - pu) / frac; + *v = (*v - pv) / frac; } /* retrieve patch control indices */ -ccl_device_inline int patch_eval_indices(KernelGlobals *kg, const PatchHandle *handle, int channel, +ccl_device_inline int patch_eval_indices(KernelGlobals *kg, + const PatchHandle *handle, + int channel, int indices[PATCH_MAX_CONTROL_VERTS]) { - int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index; + int index_base = kernel_tex_fetch(__patches, handle->array_index + 2) + handle->vert_index; - /* XXX: regular patches only */ - for(int i = 0; i < 16; i++) { - indices[i] = kernel_tex_fetch(__patches, index_base + i); - } + /* XXX: regular patches only */ + for (int i = 0; i < 16; i++) { + indices[i] = kernel_tex_fetch(__patches, index_base + i); + } - return 16; + return 16; } /* evaluate patch basis functions */ -ccl_device_inline void patch_eval_basis(KernelGlobals *kg, const PatchHandle *handle, float u, float v, - float weights[PATCH_MAX_CONTROL_VERTS], - float weights_du[PATCH_MAX_CONTROL_VERTS], - float weights_dv[PATCH_MAX_CONTROL_VERTS]) +ccl_device_inline void patch_eval_basis(KernelGlobals *kg, + const PatchHandle *handle, + float u, + float v, + float weights[PATCH_MAX_CONTROL_VERTS], + float weights_du[PATCH_MAX_CONTROL_VERTS], + float weights_dv[PATCH_MAX_CONTROL_VERTS]) { - uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */ - float d_scale = 1 << patch_eval_depth(patch_bits); + uint patch_bits = kernel_tex_fetch(__patches, handle->patch_index + 1); /* read patch param */ + float d_scale = 1 << patch_eval_depth(patch_bits); - bool non_quad_root = (patch_bits >> 4) & 0x1; - if(non_quad_root) { - d_scale *= 0.5f; - } + bool non_quad_root = (patch_bits >> 4) & 0x1; + if (non_quad_root) { + d_scale *= 0.5f; + } - patch_eval_normalize_coords(patch_bits, &u, &v); + patch_eval_normalize_coords(patch_bits, &u, &v); - /* XXX: regular patches only for now. */ + /* XXX: regular patches only for now. */ - float s[4], t[4], ds[4], dt[4]; + float s[4], t[4], ds[4], dt[4]; - patch_eval_bspline_weights(u, s, ds); - patch_eval_bspline_weights(v, t, dt); + patch_eval_bspline_weights(u, s, ds); + patch_eval_bspline_weights(v, t, dt); - patch_eval_adjust_boundary_weights(patch_bits, s, t); - patch_eval_adjust_boundary_weights(patch_bits, ds, dt); + patch_eval_adjust_boundary_weights(patch_bits, s, t); + patch_eval_adjust_boundary_weights(patch_bits, ds, dt); - for(int k = 0; k < 4; k++) { - for(int l = 0; l < 4; l++) { - weights[4*k+l] = s[l] * t[k]; - weights_du[4*k+l] = ds[l] * t[k] * d_scale; - weights_dv[4*k+l] = s[l] * dt[k] * d_scale; - } - } + for (int k = 0; k < 4; k++) { + for (int l = 0; l < 4; l++) { + weights[4 * k + l] = s[l] * t[k]; + weights_du[4 * k + l] = ds[l] * t[k] * d_scale; + weights_dv[4 * k + l] = s[l] * dt[k] * d_scale; + } + } } /* generic function for evaluating indices and weights from patch coords */ -ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg, int object, int patch, float u, float v, int channel, - int indices[PATCH_MAX_CONTROL_VERTS], - float weights[PATCH_MAX_CONTROL_VERTS], - float weights_du[PATCH_MAX_CONTROL_VERTS], - float weights_dv[PATCH_MAX_CONTROL_VERTS]) +ccl_device_inline int patch_eval_control_verts(KernelGlobals *kg, + int object, + int patch, + float u, + float v, + int channel, + int indices[PATCH_MAX_CONTROL_VERTS], + float weights[PATCH_MAX_CONTROL_VERTS], + float weights_du[PATCH_MAX_CONTROL_VERTS], + float weights_dv[PATCH_MAX_CONTROL_VERTS]) { - PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v); - kernel_assert(handle.array_index >= 0); + PatchHandle handle = patch_map_find_patch(kg, object, patch, u, v); + kernel_assert(handle.array_index >= 0); - int num_control = patch_eval_indices(kg, &handle, channel, indices); - patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv); + int num_control = patch_eval_indices(kg, &handle, channel, indices); + patch_eval_basis(kg, &handle, u, v, weights, weights_du, weights_dv); - return num_control; + return num_control; } /* functions for evaluating attributes on patches */ -ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int offset, - int patch, float u, float v, int channel, - float *du, float* dv) +ccl_device float patch_eval_float(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float *du, + float *dv) { - int indices[PATCH_MAX_CONTROL_VERTS]; - float weights[PATCH_MAX_CONTROL_VERTS]; - float weights_du[PATCH_MAX_CONTROL_VERTS]; - float weights_dv[PATCH_MAX_CONTROL_VERTS]; - - int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel, - indices, weights, weights_du, weights_dv); - - float val = 0.0f; - if(du) *du = 0.0f; - if(dv) *dv = 0.0f; - - for(int i = 0; i < num_control; i++) { - float v = kernel_tex_fetch(__attributes_float, offset + indices[i]); - - val += v * weights[i]; - if(du) *du += v * weights_du[i]; - if(dv) *dv += v * weights_dv[i]; - } - - return val; + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float val = 0.0f; + if (du) + *du = 0.0f; + if (dv) + *dv = 0.0f; + + for (int i = 0; i < num_control; i++) { + float v = kernel_tex_fetch(__attributes_float, offset + indices[i]); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; } -ccl_device float2 patch_eval_float2(KernelGlobals *kg, const ShaderData *sd, int offset, - int patch, float u, float v, int channel, - float2 *du, float2 *dv) +ccl_device float2 patch_eval_float2(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float2 *du, + float2 *dv) { - int indices[PATCH_MAX_CONTROL_VERTS]; - float weights[PATCH_MAX_CONTROL_VERTS]; - float weights_du[PATCH_MAX_CONTROL_VERTS]; - float weights_dv[PATCH_MAX_CONTROL_VERTS]; - - int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel, - indices, weights, weights_du, weights_dv); - - float2 val = make_float2(0.0f, 0.0f); - if(du) *du = make_float2(0.0f, 0.0f); - if(dv) *dv = make_float2(0.0f, 0.0f); - - for(int i = 0; i < num_control; i++) { - float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]); - - val += v * weights[i]; - if(du) *du += v * weights_du[i]; - if(dv) *dv += v * weights_dv[i]; - } - - return val; + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float2 val = make_float2(0.0f, 0.0f); + if (du) + *du = make_float2(0.0f, 0.0f); + if (dv) + *dv = make_float2(0.0f, 0.0f); + + for (int i = 0; i < num_control; i++) { + float2 v = kernel_tex_fetch(__attributes_float2, offset + indices[i]); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; } -ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int offset, - int patch, float u, float v, int channel, - float3 *du, float3 *dv) +ccl_device float3 patch_eval_float3(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float3 *du, + float3 *dv) { - int indices[PATCH_MAX_CONTROL_VERTS]; - float weights[PATCH_MAX_CONTROL_VERTS]; - float weights_du[PATCH_MAX_CONTROL_VERTS]; - float weights_dv[PATCH_MAX_CONTROL_VERTS]; - - int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel, - indices, weights, weights_du, weights_dv); - - float3 val = make_float3(0.0f, 0.0f, 0.0f); - if(du) *du = make_float3(0.0f, 0.0f, 0.0f); - if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f); - - for(int i = 0; i < num_control; i++) { - float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i])); - - val += v * weights[i]; - if(du) *du += v * weights_du[i]; - if(dv) *dv += v * weights_dv[i]; - } - - return val; + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float3 val = make_float3(0.0f, 0.0f, 0.0f); + if (du) + *du = make_float3(0.0f, 0.0f, 0.0f); + if (dv) + *dv = make_float3(0.0f, 0.0f, 0.0f); + + for (int i = 0; i < num_control; i++) { + float3 v = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + indices[i])); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; } -ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int offset, - int patch, float u, float v, int channel, - float3 *du, float3 *dv) +ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, + const ShaderData *sd, + int offset, + int patch, + float u, + float v, + int channel, + float3 *du, + float3 *dv) { - int indices[PATCH_MAX_CONTROL_VERTS]; - float weights[PATCH_MAX_CONTROL_VERTS]; - float weights_du[PATCH_MAX_CONTROL_VERTS]; - float weights_dv[PATCH_MAX_CONTROL_VERTS]; - - int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel, - indices, weights, weights_du, weights_dv); - - float3 val = make_float3(0.0f, 0.0f, 0.0f); - if(du) *du = make_float3(0.0f, 0.0f, 0.0f); - if(dv) *dv = make_float3(0.0f, 0.0f, 0.0f); - - for(int i = 0; i < num_control; i++) { - float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])); - - val += v * weights[i]; - if(du) *du += v * weights_du[i]; - if(dv) *dv += v * weights_dv[i]; - } - - return val; + int indices[PATCH_MAX_CONTROL_VERTS]; + float weights[PATCH_MAX_CONTROL_VERTS]; + float weights_du[PATCH_MAX_CONTROL_VERTS]; + float weights_dv[PATCH_MAX_CONTROL_VERTS]; + + int num_control = patch_eval_control_verts( + kg, sd->object, patch, u, v, channel, indices, weights, weights_du, weights_dv); + + float3 val = make_float3(0.0f, 0.0f, 0.0f); + if (du) + *du = make_float3(0.0f, 0.0f, 0.0f); + if (dv) + *dv = make_float3(0.0f, 0.0f, 0.0f); + + for (int i = 0; i < num_control; i++) { + float3 v = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, offset + indices[i])); + + val += v * weights[i]; + if (du) + *du += v * weights_du[i]; + if (dv) + *dv += v * weights_dv[i]; + } + + return val; } CCL_NAMESPACE_END |