author Sergey Sharybin Sat, 21 Feb 2015 09:49:55 +0000 (14:49 +0500) committer Sergey Sharybin Sat, 21 Feb 2015 12:30:29 +0000 (17:30 +0500)
This attribute missed derivatives calculation.

Not totally sure what's the proper approach for algebraic derivative
calculation, so calculating them by definition. This isn't fastest
way to do it in this case and could be replaced with some smarter magic
in the wireframe calculation loop.

At least currently implemented approach is better than nothing.

#include "oslutil.h"

+       string bump_offset = "center",
int use_pixel_size = 0,
float Size = 0.01,
output float Fac = 0.0)
{
Fac = wireframe("triangles", Size, use_pixel_size);
+       if (bump_offset == "dx") {
+               point dx = Dx(P);
+               P -= dx;
+               Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dx);
+       }
+       else if (bump_offset == "dy") {
+               point dy = Dy(P);
+               P -= dy;
+               Fac += (Fac - wireframe("triangles", Size, use_pixel_size)) / length(dy);
+       }
}

break;
#ifdef __EXTRA_NODES__
case NODE_WIREFRAME:
-                               svm_node_wireframe(kg, sd, stack, node.y, node.z, node.w);
+                               svm_node_wireframe(kg, sd, stack, node);
break;
case NODE_WAVELENGTH:
svm_node_wavelength(sd, stack, node.y, node.z);
index a8d0da6ff393fafddeb23949dc4479f7992da5be..7130b14a4260882e6431973b46613da7dfc872c9 100644 (file)
@@ -341,6 +341,12 @@ typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_TUBE   = 3,
} NodeImageProjection;

+typedef enum NodeBumpOffset {
+       NODE_BUMP_OFFSET_CENTER,
+       NODE_BUMP_OFFSET_DX,
+       NODE_BUMP_OFFSET_DY,
+} NodeBumpOffset;
+
index 660e6e2ca47015579925bd6b1118d9c8c6e25b86..42fe3e8e42908bacc7f5a1bb57ee0ff06c160497 100644 (file)
@@ -34,16 +34,12 @@ CCL_NAMESPACE_BEGIN

/* Wireframe Node */

-ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_size, uint out_fac, uint use_pixel_size)
+ccl_device float wireframe(KernelGlobals *kg,
+                           float size,
+                           int pixel_size,
+                           float3 *P)
{
-       /* Input Data */
-       float size = stack_load_float(stack, in_size);
-       int pixel_size = (int)use_pixel_size;
-
-       /* Output */
-       float f = 0.0f;
-
-       /* Calculate wireframe */
#ifdef __HAIR__
if (sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE)
#else
@@ -55,7 +51,7 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta

/* Triangles */
int np = 3;
-
+
if(sd->type & PRIMITIVE_TRIANGLE)
triangle_vertices(kg, sd->prim, Co);
else
@@ -66,7 +62,7 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta
object_position_transform(kg, sd, &Co[1]);
object_position_transform(kg, sd, &Co[2]);
}
-
+
if(pixel_size) {
// Project the derivatives of P to the viewing plane defined
// by I so we have a measure of how big is a pixel at this point
@@ -75,24 +71,53 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg, ShaderData *sd, float *sta
// Take the average of both axis' length
pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f;
}
-
+
// Use half the width as the neighbor face will render the
// other half. And take the square for fast comparison
pixelwidth *= 0.5f * size;
pixelwidth *= pixelwidth;
for (int i = 0; i < np; i++) {
int i2 = i ? i - 1 : np - 1;
-                       float3 dir = sd->P - Co[i];
+                       float3 dir = *P - Co[i];
float3 edge = Co[i] - Co[i2];
float3 crs = cross(edge, dir);
// At this point dot(crs, crs) / dot(edge, edge) is
// the square of area / length(edge) == square of the
// distance to the edge.
if (dot(crs, crs) < (dot(edge, edge) * pixelwidth))
-                               f = 1.0f;
+                               return 1.0f;
}
}
-
+       return 0.0f;
+}
+
+ccl_device void svm_node_wireframe(KernelGlobals *kg,
+                                   float *stack,
+                                   uint4 node)
+{
+       uint in_size = node.y;
+       uint out_fac = node.z;
+       uint use_pixel_size, bump_offset;
+       decode_node_uchar4(node.w, &use_pixel_size, &bump_offset, NULL, NULL);
+
+       /* Input Data */
+       float size = stack_load_float(stack, in_size);
+       int pixel_size = (int)use_pixel_size;
+
+       /* Calculate wireframe */
+       float f = wireframe(kg, sd, size, pixel_size, &sd->P);
+
+       /* TODO(sergey): Think of faster way to calculate derivatives. */
+       if(bump_offset == NODE_BUMP_OFFSET_DX) {
+               float3 Px = sd->P - sd->dP.dx;
+               f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx);
+       }
+       else if (bump_offset == NODE_BUMP_OFFSET_DY) {
+               float3 Py = sd->P - sd->dP.dy;
+               f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy);
+       }
+
if (stack_valid(out_fac))
stack_store_float(stack, out_fac, f);
}
index fa6ffffd9b4e56ba9f16cc6b06138a62bb8dc736..7a39811cacd24b900ae62030d798ea243e508122 100644 (file)
@@ -3577,14 +3577,34 @@ void WireframeNode::compile(SVMCompiler& compiler)
{
-
+       NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
+               bump_offset = NODE_BUMP_OFFSET_DX;
+       }
+       else if(bump == SHADER_BUMP_DY) {
+               bump_offset = NODE_BUMP_OFFSET_DY;
+       }
compiler.stack_assign(size_in);
compiler.stack_assign(fac_out);
+                         size_in->stack_offset,
+                         fac_out->stack_offset,
+                         compiler.encode_uchar4(use_pixel_size,
+                                                bump_offset,
+                                                0, 0));
}

void WireframeNode::compile(OSLCompiler& compiler)
{