
* Replace license text in headers with SPDX identifiers. * Remove specific license info from outdated readme.txt, instead leave details to the source files. * Add list of SPDX license identifiers used, and corresponding license texts. * Update copyright dates while we're at it. Ref D14069, T95597
106 lines
3.2 KiB
C
106 lines
3.2 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
*
|
|
* Adapted from Open Shading Language
|
|
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
|
|
* All Rights Reserved.
|
|
*
|
|
* Modifications Copyright 2011-2022 Blender Foundation. */
|
|
|
|
#pragma once
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
/* Wireframe Node */
|
|
|
|
ccl_device_inline float wireframe(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
float size,
|
|
int pixel_size,
|
|
ccl_private float3 *P)
|
|
{
|
|
#if defined(__HAIR__) || defined(__POINTCLOUD__)
|
|
if (sd->prim != PRIM_NONE && sd->type & PRIMITIVE_TRIANGLE)
|
|
#else
|
|
if (sd->prim != PRIM_NONE)
|
|
#endif
|
|
{
|
|
float3 Co[3];
|
|
float pixelwidth = 1.0f;
|
|
|
|
/* Triangles */
|
|
int np = 3;
|
|
|
|
if (sd->type & PRIMITIVE_MOTION) {
|
|
motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co);
|
|
}
|
|
else {
|
|
triangle_vertices(kg, sd->prim, Co);
|
|
}
|
|
|
|
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
|
|
object_position_transform(kg, sd, &Co[0]);
|
|
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
|
|
float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I);
|
|
float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I);
|
|
// 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 = *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))
|
|
return 1.0f;
|
|
}
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
ccl_device_noinline void svm_node_wireframe(KernelGlobals kg,
|
|
ccl_private ShaderData *sd,
|
|
ccl_private float *stack,
|
|
uint4 node)
|
|
{
|
|
uint in_size = node.y;
|
|
uint out_fac = node.z;
|
|
uint use_pixel_size, bump_offset;
|
|
svm_unpack_node_uchar2(node.w, &use_pixel_size, &bump_offset);
|
|
|
|
/* 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);
|
|
}
|
|
|
|
CCL_NAMESPACE_END
|