Fix T43755: Wireframe attribute doesn't work with displace
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.
This commit is contained in:
parent
3445ff0f93
commit
a97bc1bedf
Notes:
blender-bot
2023-02-14 09:27:23 +01:00
Referenced by issue #43755, Wireframe attribute doesn't work with displace.
|
@ -18,10 +18,21 @@
|
|||
#include "oslutil.h"
|
||||
|
||||
shader node_wireframe(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -361,7 +361,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
typedef enum ShaderType {
|
||||
SHADER_TYPE_SURFACE,
|
||||
SHADER_TYPE_VOLUME,
|
||||
|
|
|
@ -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,
|
||||
ShaderData *sd,
|
||||
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,
|
||||
ShaderData *sd,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -3577,14 +3577,34 @@ void WireframeNode::compile(SVMCompiler& compiler)
|
|||
{
|
||||
ShaderInput *size_in = input("Size");
|
||||
ShaderOutput *fac_out = output("Fac");
|
||||
|
||||
NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
|
||||
if(bump == SHADER_BUMP_DX) {
|
||||
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);
|
||||
compiler.add_node(NODE_WIREFRAME, size_in->stack_offset, fac_out->stack_offset, use_pixel_size);
|
||||
compiler.add_node(NODE_WIREFRAME,
|
||||
size_in->stack_offset,
|
||||
fac_out->stack_offset,
|
||||
compiler.encode_uchar4(use_pixel_size,
|
||||
bump_offset,
|
||||
0, 0));
|
||||
}
|
||||
|
||||
void WireframeNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
if(bump == SHADER_BUMP_DX) {
|
||||
compiler.parameter("bump_offset", "dx");
|
||||
}
|
||||
else if(bump == SHADER_BUMP_DY) {
|
||||
compiler.parameter("bump_offset", "dy");
|
||||
}
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("use_pixel_size", use_pixel_size);
|
||||
compiler.add(this, "node_wireframe");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue