Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/kernel/svm/svm_voronoi.h
| Show All 12 Lines | |||||
| * See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
| * limitations under the License. | * limitations under the License. | ||||
| */ | */ | ||||
| CCL_NAMESPACE_BEGIN | CCL_NAMESPACE_BEGIN | ||||
| /* Voronoi */ | /* Voronoi */ | ||||
| ccl_device float voronoi_F1_distance(float3 p) | ccl_device void voronoi_neighbors(float3 p, NodeVoronoiDistanceMetric distance, float e, float da[4], float3 pa[4]) | ||||
| { | { | ||||
| /* returns squared distance in da */ | /* Compute the distance to and the position of the closest neighbors to p. | ||||
| float da = 1e10f; | * | ||||
| * The neighbors are randomly placed, 1 each in a 3x3x3 grid (Worley pattern). | |||||
| int3 xyzi = quick_floor_to_int3(p); | * The distances and points are returned in ascending order, i.e. da[0] and pa[0] will | ||||
| * contain the distance to the closest point and its coordinates respectively. | |||||
| for(int xx = -1; xx <= 1; xx++) { | */ | ||||
| for(int yy = -1; yy <= 1; yy++) { | |||||
| for(int zz = -1; zz <= 1; zz++) { | |||||
| int3 ip = xyzi + make_int3(xx, yy, zz); | |||||
| float3 fp = make_float3(ip.x, ip.y, ip.z); | |||||
| float3 vp = fp + cellnoise3(fp); | |||||
| float d = len_squared(p - vp); | |||||
| da = min(d, da); | |||||
| } | |||||
| } | |||||
| } | |||||
| return da; | |||||
| } | |||||
| ccl_device float3 voronoi_F1_color(float3 p) | da[0] = 1e10f; | ||||
| { | da[1] = 1e10f; | ||||
| /* returns color of the nearest point */ | da[2] = 1e10f; | ||||
| float da = 1e10f; | da[3] = 1e10f; | ||||
| float3 pa; | |||||
| int3 xyzi = quick_floor_to_int3(p); | int3 xyzi = quick_floor_to_int3(p); | ||||
| for(int xx = -1; xx <= 1; xx++) { | for(int xx = -1; xx <= 1; xx++) { | ||||
| for(int yy = -1; yy <= 1; yy++) { | for(int yy = -1; yy <= 1; yy++) { | ||||
| for(int zz = -1; zz <= 1; zz++) { | for(int zz = -1; zz <= 1; zz++) { | ||||
| int3 ip = xyzi + make_int3(xx, yy, zz); | int3 ip = xyzi + make_int3(xx, yy, zz); | ||||
| float3 fp = make_float3(ip.x, ip.y, ip.z); | float3 fp = make_float3(ip.x, ip.y, ip.z); | ||||
| float3 vp = fp + cellnoise3(fp); | float3 vp = fp + cellnoise3(fp); | ||||
| float d = len_squared(p - vp); | |||||
| if(d < da) { | float d; | ||||
| da = d; | switch(distance) { | ||||
| pa = vp; | case NODE_VORONOI_DISTANCE: | ||||
| } | d = len_squared(p - vp); | ||||
| break; | |||||
| case NODE_VORONOI_MANHATTAN: | |||||
| d = reduce_add(fabs(vp - p)); | |||||
| break; | |||||
| case NODE_VORONOI_CHEBYCHEV: | |||||
| d = max3(fabs(vp - p)); | |||||
| break; | |||||
| case NODE_VORONOI_MINKOWSKI: | |||||
| float3 n = fabs(vp - p); | |||||
| if(e == 0.5f) { | |||||
| d = sqr(reduce_add(sqrt(n))); | |||||
| } | } | ||||
| else { | |||||
| d = powf(reduce_add(pow3(n, e)), 1.0f/e); | |||||
| } | } | ||||
| break; | |||||
| } | } | ||||
| return cellnoise3(pa); | /* To keep the shortest four distances and associated points we have to keep them in sorted order. */ | ||||
| if (d < da[0]) { | |||||
| da[3] = da[2]; | |||||
| da[2] = da[1]; | |||||
| da[1] = da[0]; | |||||
| da[0] = d; | |||||
| pa[3] = pa[2]; | |||||
| pa[2] = pa[1]; | |||||
| pa[1] = pa[0]; | |||||
| pa[0] = vp; | |||||
| } | |||||
| else if (d < da[1]) { | |||||
| da[3] = da[2]; | |||||
| da[2] = da[1]; | |||||
| da[1] = d; | |||||
| pa[3] = pa[2]; | |||||
| pa[2] = pa[1]; | |||||
| pa[1] = vp; | |||||
| } | |||||
| else if (d < da[2]) { | |||||
| da[3] = da[2]; | |||||
| da[2] = d; | |||||
| pa[3] = pa[2]; | |||||
| pa[2] = vp; | |||||
| } | |||||
| else if (d < da[3]) { | |||||
| da[3] = d; | |||||
| pa[3] = vp; | |||||
| } | |||||
| } | } | ||||
| ccl_device_noinline float4 svm_voronoi(NodeVoronoiColoring coloring, float3 p) | |||||
| { | |||||
| if(coloring == NODE_VORONOI_INTENSITY) { | |||||
| /* compute squared distance to the nearest neighbour */ | |||||
| float fac = voronoi_F1_distance(p); | |||||
| return make_float4(fac, fac, fac, fac); | |||||
| } | } | ||||
| else { | |||||
| /* compute color of the nearest neighbour */ | |||||
| float3 color = voronoi_F1_color(p); | |||||
| return make_float4(color.x, color.y, color.z, average(color)); | |||||
| } | } | ||||
| } | } | ||||
| ccl_device void svm_node_tex_voronoi(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) | ccl_device void svm_node_tex_voronoi(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset) | ||||
| { | { | ||||
| uint coloring = node.y; | uint4 node2 = read_node(kg, offset); | ||||
| uint scale_offset, co_offset, fac_offset, color_offset; | |||||
| decode_node_uchar4(node.z, &scale_offset, &co_offset, &fac_offset, &color_offset); | uint co_offset, coloring, distance, feature; | ||||
| uint scale_offset, e_offset, fac_offset, color_offset; | |||||
| decode_node_uchar4(node.y, &co_offset, &coloring, &distance, &feature); | |||||
| decode_node_uchar4(node.z, &scale_offset, &e_offset, &fac_offset, &color_offset); | |||||
| float3 co = stack_load_float3(stack, co_offset); | float3 co = stack_load_float3(stack, co_offset); | ||||
| float scale = stack_load_float_default(stack, scale_offset, node.w); | float scale = stack_load_float_default(stack, scale_offset, node2.x); | ||||
| float exponent = stack_load_float_default(stack, e_offset, node2.y); | |||||
| float dist[4]; | |||||
| float3 neighbor[4]; | |||||
| voronoi_neighbors(co*scale, (NodeVoronoiDistanceMetric)distance, exponent, dist, neighbor); | |||||
| float4 result = svm_voronoi((NodeVoronoiColoring)coloring, co*scale); | float3 color; | ||||
| float3 color = make_float3(result.x, result.y, result.z); | float fac; | ||||
| float f = result.w; | if(coloring == NODE_VORONOI_INTENSITY) { | ||||
| switch(feature) { | |||||
| case NODE_VORONOI_F1: fac = dist[0]; break; | |||||
| case NODE_VORONOI_F2: fac = dist[1]; break; | |||||
| case NODE_VORONOI_F3: fac = dist[2]; break; | |||||
| case NODE_VORONOI_F4: fac = dist[3]; break; | |||||
| case NODE_VORONOI_F2F1: fac = dist[1] - dist[0]; break; | |||||
| } | |||||
| color = make_float3(fac, fac, fac); | |||||
| } | |||||
| else { | |||||
| /* NODE_VORONOI_CELLS */ | |||||
| switch(feature) { | |||||
| case NODE_VORONOI_F1: color = neighbor[0]; break; | |||||
| case NODE_VORONOI_F2: color = neighbor[1]; break; | |||||
| case NODE_VORONOI_F3: color = neighbor[2]; break; | |||||
| case NODE_VORONOI_F4: color = neighbor[3]; break; | |||||
| /* Usefulness of this vector is questionable. Note F2 >= F1 but the | |||||
| * individual vector components might not be. */ | |||||
| case NODE_VORONOI_F2F1: color = fabs(neighbor[1] - neighbor[0]); break; | |||||
| } | |||||
| color = cellnoise3(color); | |||||
| fac = average(color); | |||||
| } | |||||
| if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, f); | if(stack_valid(fac_offset)) stack_store_float(stack, fac_offset, fac); | ||||
| if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, color); | if(stack_valid(color_offset)) stack_store_float3(stack, color_offset, color); | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||