Shaders: Add Filter Width input to Bump node
This makes it possible to restore previous Blender 4.3 behavior of bump mapping, where the large filter width was sometimes (ab)used to get a bevel like effect on stepwise textures. For bump from the displacement socket, filter width remains fixed at 0.1. Ref #133991, #135841 Pull Request: https://projects.blender.org/blender/blender/pulls/136465
This commit is contained in:
@@ -242,10 +242,8 @@ ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals kg,
|
||||
motion_triangle_normals(kg, object, tri_vindex, numsteps, numverts, step, t, n);
|
||||
|
||||
const float3 N = safe_normalize(triangle_interpolate(u, v, n[0], n[1], n[2]));
|
||||
N_x = safe_normalize(
|
||||
triangle_interpolate(u + du.dx * BUMP_DX, v + dv.dx * BUMP_DX, n[0], n[1], n[2]));
|
||||
N_y = safe_normalize(
|
||||
triangle_interpolate(u + du.dy * BUMP_DY, v + dv.dy * BUMP_DY, n[0], n[1], n[2]));
|
||||
N_x = safe_normalize(triangle_interpolate(u + du.dx, v + dv.dx, n[0], n[1], n[2]));
|
||||
N_y = safe_normalize(triangle_interpolate(u + du.dy, v + dv.dy, n[0], n[1], n[2]));
|
||||
|
||||
N_x = is_zero(N_x) ? Ng : N_x;
|
||||
N_y = is_zero(N_y) ? Ng : N_y;
|
||||
|
||||
@@ -139,8 +139,8 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg,
|
||||
const float3 n2 = kernel_data_fetch(tri_vnormal, tri_vindex.z);
|
||||
|
||||
const float3 N = safe_normalize(triangle_interpolate(u, v, n0, n1, n2));
|
||||
N_x = safe_normalize(triangle_interpolate(u + du.dx * BUMP_DX, v + dv.dx * BUMP_DX, n0, n1, n2));
|
||||
N_y = safe_normalize(triangle_interpolate(u + du.dy * BUMP_DY, v + dv.dy * BUMP_DY, n0, n1, n2));
|
||||
N_x = safe_normalize(triangle_interpolate(u + du.dx, v + dv.dx, n0, n1, n2));
|
||||
N_y = safe_normalize(triangle_interpolate(u + du.dy, v + dv.dy, n0, n1, n2));
|
||||
|
||||
N_x = is_zero(N_x) ? Ng : N_x;
|
||||
N_y = is_zero(N_y) ? Ng : N_y;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_attribute(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
string name = "",
|
||||
output point Vector = point(0.0, 0.0, 0.0),
|
||||
output color Color = 0.0,
|
||||
@@ -19,15 +20,15 @@ shader node_attribute(string bump_offset = "center",
|
||||
Alpha = data[3];
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
Color += Dx(Color) * BUMP_DX;
|
||||
Vector += Dx(Vector) * BUMP_DX;
|
||||
Fac += Dx(Fac) * BUMP_DX;
|
||||
Alpha += Dx(Alpha) * BUMP_DX;
|
||||
Color += Dx(Color) * bump_filter_width;
|
||||
Vector += Dx(Vector) * bump_filter_width;
|
||||
Fac += Dx(Fac) * bump_filter_width;
|
||||
Alpha += Dx(Alpha) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Color += Dy(Color) * BUMP_DY;
|
||||
Vector += Dy(Vector) * BUMP_DY;
|
||||
Fac += Dy(Fac) * BUMP_DY;
|
||||
Alpha += Dy(Alpha) * BUMP_DY;
|
||||
Color += Dy(Color) * bump_filter_width;
|
||||
Vector += Dy(Vector) * bump_filter_width;
|
||||
Fac += Dy(Fac) * bump_filter_width;
|
||||
Alpha += Dy(Alpha) * bump_filter_width;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ surface node_bump(int invert = 0,
|
||||
normal NormalIn = N,
|
||||
float Strength = 0.1,
|
||||
float Distance = 1.0,
|
||||
float FilterWidth = BUMP_FILTER_WIDTH,
|
||||
float SampleCenter = 0.0,
|
||||
float SampleX = 0.0,
|
||||
float SampleY = 0.0,
|
||||
@@ -45,7 +46,7 @@ surface node_bump(int invert = 0,
|
||||
dist *= -1.0;
|
||||
|
||||
/* compute and output perturbed normal */
|
||||
NormalOut = normalize(BUMP_DX * absdet * Normal - dist * sign(det) * surfgrad);
|
||||
NormalOut = normalize(FilterWidth * absdet * Normal - dist * sign(det) * surfgrad);
|
||||
NormalOut = normalize(strength * NormalOut + (1.0 - strength) * Normal);
|
||||
|
||||
if (use_object_space) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_geometry(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
|
||||
output point Position = point(0.0, 0.0, 0.0),
|
||||
output normal Normal = normal(0.0, 0.0, 0.0),
|
||||
@@ -24,12 +25,12 @@ shader node_geometry(string bump_offset = "center",
|
||||
Backfacing = backfacing();
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
Position += Dx(Position) * BUMP_DX;
|
||||
Parametric += Dx(Parametric) * BUMP_DX;
|
||||
Position += Dx(Position) * bump_filter_width;
|
||||
Parametric += Dx(Parametric) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Position += Dy(Position) * BUMP_DY;
|
||||
Parametric += Dy(Parametric) * BUMP_DY;
|
||||
Position += Dy(Position) * bump_filter_width;
|
||||
Parametric += Dy(Parametric) * bump_filter_width;
|
||||
}
|
||||
|
||||
point generated;
|
||||
@@ -52,10 +53,10 @@ shader node_geometry(string bump_offset = "center",
|
||||
|
||||
getattribute("geom:pointiness", Pointiness);
|
||||
if (bump_offset == "dx") {
|
||||
Pointiness += Dx(Pointiness) * BUMP_DX;
|
||||
Pointiness += Dx(Pointiness) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Pointiness += Dy(Pointiness) * BUMP_DY;
|
||||
Pointiness += Dy(Pointiness) * bump_filter_width;
|
||||
}
|
||||
|
||||
getattribute("geom:random_per_island", RandomPerIsland);
|
||||
|
||||
@@ -10,6 +10,7 @@ shader node_texture_coordinate(
|
||||
int from_dupli = 0,
|
||||
int use_transform = 0,
|
||||
string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
matrix object_itfm = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
|
||||
output point Generated = point(0.0, 0.0, 0.0),
|
||||
@@ -74,28 +75,26 @@ shader node_texture_coordinate(
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
if (!from_dupli) {
|
||||
Generated += Dx(Generated) * BUMP_DX;
|
||||
UV += Dx(UV) * BUMP_DX;
|
||||
Generated += Dx(Generated) * bump_filter_width;
|
||||
UV += Dx(UV) * bump_filter_width;
|
||||
}
|
||||
Object += Dx(Object) * BUMP_DX;
|
||||
Camera += Dx(Camera) * BUMP_DX;
|
||||
Window += Dx(Window) * BUMP_DX;
|
||||
Object += Dx(Object) * bump_filter_width;
|
||||
Camera += Dx(Camera) * bump_filter_width;
|
||||
Window += Dx(Window) * bump_filter_width;
|
||||
if (getattribute("geom:bump_map_normal", Normal)) {
|
||||
/* A scaling of `BUMP_DX` is already applied when computing the derivatives, no additional
|
||||
* scaling is needed here. */
|
||||
Normal = normalize(Normal + Dx(Normal));
|
||||
Normal = normalize(Normal + Dx(Normal) * bump_filter_width);
|
||||
}
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
if (!from_dupli) {
|
||||
Generated += Dy(Generated) * BUMP_DY;
|
||||
UV += Dy(UV) * BUMP_DY;
|
||||
Generated += Dy(Generated) * bump_filter_width;
|
||||
UV += Dy(UV) * bump_filter_width;
|
||||
}
|
||||
Object += Dy(Object) * BUMP_DY;
|
||||
Camera += Dy(Camera) * BUMP_DY;
|
||||
Window += Dy(Window) * BUMP_DY;
|
||||
Object += Dy(Object) * bump_filter_width;
|
||||
Camera += Dy(Camera) * bump_filter_width;
|
||||
Window += Dy(Window) * bump_filter_width;
|
||||
if (getattribute("geom:bump_map_normal", Normal)) {
|
||||
Normal = normalize(Normal + Dy(Normal));
|
||||
Normal = normalize(Normal + Dy(Normal) * bump_filter_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
shader node_uv_map(int from_dupli = 0,
|
||||
string attribute = "",
|
||||
string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
output point UV = point(0.0, 0.0, 0.0))
|
||||
{
|
||||
if (from_dupli) {
|
||||
@@ -21,12 +22,12 @@ shader node_uv_map(int from_dupli = 0,
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
if (!from_dupli) {
|
||||
UV += Dx(UV) * BUMP_DX;
|
||||
UV += Dx(UV) * bump_filter_width;
|
||||
}
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
if (!from_dupli) {
|
||||
UV += Dy(UV) * BUMP_DY;
|
||||
UV += Dy(UV) * bump_filter_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_vertex_color(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
string layer_name = "",
|
||||
output color Color = 0.0,
|
||||
output float Alpha = 0.0)
|
||||
@@ -24,12 +25,12 @@ shader node_vertex_color(string bump_offset = "center",
|
||||
Alpha = vertex_color[3];
|
||||
|
||||
if (bump_offset == "dx") {
|
||||
Color += Dx(Color) * BUMP_DX;
|
||||
Alpha += Dx(Alpha) * BUMP_DX;
|
||||
Color += Dx(Color) * bump_filter_width;
|
||||
Alpha += Dx(Alpha) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
Color += Dy(Color) * BUMP_DY;
|
||||
Alpha += Dy(Alpha) * BUMP_DY;
|
||||
Color += Dy(Color) * bump_filter_width;
|
||||
Alpha += Dy(Alpha) * bump_filter_width;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
#include "stdcycles.h"
|
||||
|
||||
shader node_wireframe(string bump_offset = "center",
|
||||
float bump_filter_width = BUMP_FILTER_WIDTH,
|
||||
int use_pixel_size = 0,
|
||||
float Size = 0.01,
|
||||
output float Fac = 0.0)
|
||||
{
|
||||
if (bump_offset == "dx") {
|
||||
P += Dx(P) * BUMP_DX;
|
||||
P += Dx(P) * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == "dy") {
|
||||
P += Dy(P) * BUMP_DY;
|
||||
P += Dy(P) * bump_filter_width;
|
||||
}
|
||||
|
||||
Fac = wireframe("triangles", Size, use_pixel_size);
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
// Constants
|
||||
#define FLT_MAX 3.402823466e+38 // max value
|
||||
|
||||
/* Offset of coordinates for evaluating bump node. Unit in pixel.
|
||||
* NOTE: keep the same as SVM. */
|
||||
#define BUMP_DX 0.1
|
||||
#define BUMP_DY BUMP_DX
|
||||
/* Default offset of coordinates for evaluating bump node. Unit in pixel. */
|
||||
#define BUMP_FILTER_WIDTH 0.1
|
||||
|
||||
// Declaration of built-in functions and closures, stdosl.h does not make
|
||||
// these available so we have to redefine them.
|
||||
|
||||
@@ -25,8 +25,9 @@ ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg,
|
||||
ccl_private NodeAttributeOutputType *type,
|
||||
ccl_private uint *out_offset)
|
||||
{
|
||||
*out_offset = node.z;
|
||||
*type = (NodeAttributeOutputType)node.w;
|
||||
uint type_value;
|
||||
svm_unpack_node_uchar2(node.z, out_offset, &type_value);
|
||||
*type = (NodeAttributeOutputType)type_value;
|
||||
|
||||
AttributeDescriptor desc;
|
||||
|
||||
@@ -35,14 +36,14 @@ ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals kg,
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
desc = attribute_not_found();
|
||||
desc.offset = 0;
|
||||
desc.type = (NodeAttributeType)node.w;
|
||||
desc.type = (NodeAttributeType)type_value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* background */
|
||||
desc = attribute_not_found();
|
||||
desc.offset = 0;
|
||||
desc.type = (NodeAttributeType)node.w;
|
||||
desc.type = (NodeAttributeType)type_value;
|
||||
}
|
||||
|
||||
return desc;
|
||||
@@ -158,15 +159,17 @@ ccl_device_noinline void svm_node_attr(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Position offsetted in x direction. */
|
||||
ccl_device_forceinline float3 svm_node_bump_P_dx(const ccl_private ShaderData *sd)
|
||||
ccl_device_forceinline float3 svm_node_bump_P_dx(const ccl_private ShaderData *sd,
|
||||
const float bump_filter_width)
|
||||
{
|
||||
return sd->P + differential_from_compact(sd->Ng, sd->dP).dx * BUMP_DX;
|
||||
return sd->P + differential_from_compact(sd->Ng, sd->dP).dx * bump_filter_width;
|
||||
}
|
||||
|
||||
/* Position offsetted in y direction. */
|
||||
ccl_device_forceinline float3 svm_node_bump_P_dy(const ccl_private ShaderData *sd)
|
||||
ccl_device_forceinline float3 svm_node_bump_P_dy(const ccl_private ShaderData *sd,
|
||||
const float bump_filter_width)
|
||||
{
|
||||
return sd->P + differential_from_compact(sd->Ng, sd->dP).dy * BUMP_DY;
|
||||
return sd->P + differential_from_compact(sd->Ng, sd->dP).dy * bump_filter_width;
|
||||
}
|
||||
|
||||
/* Evaluate attributes at a position shifted in x direction. */
|
||||
@@ -178,6 +181,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
|
||||
uint out_offset = 0;
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
|
||||
#ifdef __VOLUME__
|
||||
/* Volume */
|
||||
@@ -197,7 +201,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
|
||||
if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
|
||||
/* No generated attribute, fall back to object coordinates. */
|
||||
float3 f_x = svm_node_bump_P_dx(sd);
|
||||
float3 f_x = svm_node_bump_P_dx(sd, bump_filter_width);
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
object_inverse_position_transform(kg, sd, &f_x);
|
||||
}
|
||||
@@ -217,7 +221,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
if (desc.type == NODE_ATTR_FLOAT) {
|
||||
float dfdx;
|
||||
const float f = primitive_surface_attribute_float(kg, sd, desc, &dfdx, nullptr);
|
||||
const float f_x = f + dfdx * BUMP_DX;
|
||||
const float f_x = f + dfdx * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, f_x);
|
||||
}
|
||||
@@ -231,7 +235,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
else if (desc.type == NODE_ATTR_FLOAT2) {
|
||||
float2 dfdx;
|
||||
const float2 f = primitive_surface_attribute_float2(kg, sd, desc, &dfdx, nullptr);
|
||||
const float2 f_x = f + dfdx * BUMP_DX;
|
||||
const float2 f_x = f + dfdx * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, f_x.x);
|
||||
}
|
||||
@@ -245,7 +249,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
|
||||
float4 dfdx;
|
||||
const float4 f = primitive_surface_attribute_float4(kg, sd, desc, &dfdx, nullptr);
|
||||
const float4 f_x = f + dfdx * BUMP_DX;
|
||||
const float4 f_x = f + dfdx * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, average(make_float3(f_x)));
|
||||
}
|
||||
@@ -259,7 +263,7 @@ ccl_device_noinline void svm_node_attr_bump_dx(KernelGlobals kg,
|
||||
else {
|
||||
float3 dfdx;
|
||||
const float3 f = primitive_surface_attribute_float3(kg, sd, desc, &dfdx, nullptr);
|
||||
const float3 f_x = f + dfdx * BUMP_DX;
|
||||
const float3 f_x = f + dfdx * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, average(f_x));
|
||||
}
|
||||
@@ -281,6 +285,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
NodeAttributeOutputType type = NODE_ATTR_OUTPUT_FLOAT;
|
||||
uint out_offset = 0;
|
||||
const AttributeDescriptor desc = svm_node_attr_init(kg, sd, node, &type, &out_offset);
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
|
||||
#ifdef __VOLUME__
|
||||
/* Volume */
|
||||
@@ -300,7 +305,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
|
||||
if (node.y == ATTR_STD_GENERATED && desc.element == ATTR_ELEMENT_NONE) {
|
||||
/* No generated attribute, fall back to object coordinates. */
|
||||
float3 f_y = svm_node_bump_P_dy(sd);
|
||||
float3 f_y = svm_node_bump_P_dy(sd, bump_filter_width);
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
object_inverse_position_transform(kg, sd, &f_y);
|
||||
}
|
||||
@@ -320,7 +325,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
if (desc.type == NODE_ATTR_FLOAT) {
|
||||
float dfdy;
|
||||
const float f = primitive_surface_attribute_float(kg, sd, desc, nullptr, &dfdy);
|
||||
const float f_y = f + dfdy * BUMP_DY;
|
||||
const float f_y = f + dfdy * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, f_y);
|
||||
}
|
||||
@@ -334,7 +339,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
else if (desc.type == NODE_ATTR_FLOAT2) {
|
||||
float2 dfdy;
|
||||
const float2 f = primitive_surface_attribute_float2(kg, sd, desc, nullptr, &dfdy);
|
||||
const float2 f_y = f + dfdy * BUMP_DY;
|
||||
const float2 f_y = f + dfdy * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, f_y.x);
|
||||
}
|
||||
@@ -348,7 +353,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) {
|
||||
float4 dfdy;
|
||||
const float4 f = primitive_surface_attribute_float4(kg, sd, desc, nullptr, &dfdy);
|
||||
const float4 f_y = f + dfdy * BUMP_DY;
|
||||
const float4 f_y = f + dfdy * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, average(make_float3(f_y)));
|
||||
}
|
||||
@@ -362,7 +367,7 @@ ccl_device_noinline void svm_node_attr_bump_dy(KernelGlobals kg,
|
||||
else {
|
||||
float3 dfdy;
|
||||
const float3 f = primitive_surface_attribute_float3(kg, sd, desc, nullptr, &dfdy);
|
||||
const float3 f_y = f + dfdy * BUMP_DY;
|
||||
const float3 f_y = f + dfdy * bump_filter_width;
|
||||
if (type == NODE_ATTR_OUTPUT_FLOAT) {
|
||||
stack_store_float(stack, out_offset, average(f_y));
|
||||
}
|
||||
|
||||
@@ -16,15 +16,17 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Bump Node */
|
||||
template<uint node_feature_mask>
|
||||
ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node)
|
||||
ccl_device_noinline int svm_node_set_bump(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint4 node,
|
||||
int offset)
|
||||
{
|
||||
uint out_offset;
|
||||
uint bump_state_offset;
|
||||
uint dummy;
|
||||
svm_unpack_node_uchar4(node.w, &out_offset, &bump_state_offset, &dummy, &dummy);
|
||||
svm_unpack_node_uchar2(node.w, &out_offset, &bump_state_offset);
|
||||
const uint4 data_node = read_node(kg, &offset);
|
||||
const float bump_filter_width = __uint_as_float(data_node.x);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
@@ -87,14 +89,13 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
||||
strength = max(strength, 0.0f);
|
||||
|
||||
/* Compute and output perturbed normal.
|
||||
* dP'dx = dPdx + scale * (h_x - h_c) / BUMP_DX * normal
|
||||
* dP'dy = dPdy + scale * (h_y - h_c) / BUMP_DY * normal
|
||||
* dP'dx = dPdx + scale * (h_x - h_c) / filter_width * normal
|
||||
* dP'dy = dPdy + scale * (h_y - h_c) / filter_width * normal
|
||||
* N' = cross(dP'dx, dP'dy)
|
||||
* = cross(dPdx, dPdy) - scale * ((h_y - h_c) / BUMP_DY * Ry + (h_x - h_c) / BUMP_DX * Rx)
|
||||
* ≈ det * normal_in - scale * surfgrad / BUMP_DX
|
||||
* = cross(dPdx, dPdy) - scale * ((h_y - h_c) / filter_width * Ry + (h_x - h_c) /
|
||||
* filter_width * Rx) ≈ det * normal_in - scale * surfgrad / filter_width
|
||||
*/
|
||||
kernel_assert(BUMP_DX == BUMP_DY);
|
||||
float3 normal_out = safe_normalize(BUMP_DX * absdet * normal_in -
|
||||
float3 normal_out = safe_normalize(bump_filter_width * absdet * normal_in -
|
||||
scale * signf(det) * surfgrad);
|
||||
if (is_zero(normal_out)) {
|
||||
normal_out = normal_in;
|
||||
@@ -113,6 +114,8 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
||||
stack_store_float3(stack, out_offset, zero_float3());
|
||||
}
|
||||
#endif
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* Displacement Node */
|
||||
|
||||
@@ -56,18 +56,19 @@ ccl_device_noinline void svm_node_geometry_bump_dx(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
const uint out_offset,
|
||||
const float bump_filter_width)
|
||||
{
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 data;
|
||||
|
||||
switch (type) {
|
||||
case NODE_GEOM_P:
|
||||
data = svm_node_bump_P_dx(sd);
|
||||
data = svm_node_bump_P_dx(sd, bump_filter_width);
|
||||
break;
|
||||
case NODE_GEOM_uv: {
|
||||
const float u_x = sd->u + sd->du.dx * BUMP_DX;
|
||||
const float v_x = sd->v + sd->dv.dx * BUMP_DX;
|
||||
const float u_x = sd->u + sd->du.dx * bump_filter_width;
|
||||
const float v_x = sd->v + sd->dv.dx * bump_filter_width;
|
||||
data = make_float3(1.0f - u_x - v_x, u_x, 0.0f);
|
||||
break;
|
||||
}
|
||||
@@ -86,18 +87,19 @@ ccl_device_noinline void svm_node_geometry_bump_dy(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint type,
|
||||
const uint out_offset)
|
||||
const uint out_offset,
|
||||
const float bump_filter_width)
|
||||
{
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 data;
|
||||
|
||||
switch (type) {
|
||||
case NODE_GEOM_P:
|
||||
data = svm_node_bump_P_dy(sd);
|
||||
data = svm_node_bump_P_dy(sd, bump_filter_width);
|
||||
break;
|
||||
case NODE_GEOM_uv: {
|
||||
const float u_y = sd->u + sd->du.dy * BUMP_DY;
|
||||
const float v_y = sd->v + sd->dv.dy * BUMP_DY;
|
||||
const float u_y = sd->u + sd->du.dy * bump_filter_width;
|
||||
const float v_y = sd->v + sd->dv.dy * bump_filter_width;
|
||||
data = make_float3(1.0f - u_y - v_y, u_y, 0.0f);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -189,18 +189,18 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
||||
svm_node_attr<node_feature_mask>(kg, sd, stack, node);
|
||||
break;
|
||||
SVM_CASE(NODE_VERTEX_COLOR)
|
||||
svm_node_vertex_color(kg, sd, stack, node.y, node.z, node.w);
|
||||
svm_node_vertex_color(kg, sd, stack, node);
|
||||
break;
|
||||
SVM_CASE(NODE_GEOMETRY_BUMP_DX)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z);
|
||||
svm_node_geometry_bump_dx(kg, sd, stack, node.y, node.z, __uint_as_float(node.w));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_GEOMETRY_BUMP_DY)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
|
||||
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z, __uint_as_float(node.w));
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_SET_DISPLACEMENT)
|
||||
@@ -222,7 +222,7 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
||||
offset = svm_node_tex_noise(kg, sd, stack, node.y, node.z, node.w, offset);
|
||||
break;
|
||||
SVM_CASE(NODE_SET_BUMP)
|
||||
svm_node_set_bump<node_feature_mask>(kg, sd, stack, node);
|
||||
offset = svm_node_set_bump<node_feature_mask>(kg, sd, stack, node, offset);
|
||||
break;
|
||||
SVM_CASE(NODE_ATTR_BUMP_DX)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
@@ -239,13 +239,13 @@ ccl_device void svm_eval_nodes(KernelGlobals kg,
|
||||
SVM_CASE(NODE_VERTEX_COLOR_BUMP_DX)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
svm_node_vertex_color_bump_dx(kg, sd, stack, node.y, node.z, node.w);
|
||||
svm_node_vertex_color_bump_dx(kg, sd, stack, node);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_VERTEX_COLOR_BUMP_DY)
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
svm_node_vertex_color_bump_dy(kg, sd, stack, node.y, node.z, node.w);
|
||||
svm_node_vertex_color_bump_dy(kg, sd, stack, node);
|
||||
}
|
||||
break;
|
||||
SVM_CASE(NODE_TEX_COORD_BUMP_DX)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include "kernel/geom/primitive.h"
|
||||
|
||||
#include "kernel/svm/attribute.h"
|
||||
#include "kernel/svm/types.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/math_base.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -29,9 +31,10 @@ ccl_device_noinline int svm_node_tex_coord(KernelGlobals kg,
|
||||
const uint out_offset = node.z;
|
||||
|
||||
switch ((NodeTexCoord)type) {
|
||||
case NODE_TEXCO_OBJECT: {
|
||||
case NODE_TEXCO_OBJECT:
|
||||
case NODE_TEXCO_OBJECT_WITH_TRANSFORM: {
|
||||
data = sd->P;
|
||||
if (node.w == 0) {
|
||||
if (type == NODE_TEXCO_OBJECT) {
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
object_inverse_position_transform(kg, sd, &data);
|
||||
}
|
||||
@@ -149,11 +152,13 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
|
||||
float3 data = zero_float3();
|
||||
const uint type = node.y;
|
||||
const uint out_offset = node.z;
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
|
||||
switch ((NodeTexCoord)type) {
|
||||
case NODE_TEXCO_OBJECT: {
|
||||
data = svm_node_bump_P_dx(sd);
|
||||
if (node.w == 0) {
|
||||
case NODE_TEXCO_OBJECT:
|
||||
case NODE_TEXCO_OBJECT_WITH_TRANSFORM: {
|
||||
data = svm_node_bump_P_dx(sd, bump_filter_width);
|
||||
if (type == NODE_TEXCO_OBJECT) {
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
object_inverse_position_transform(kg, sd, &data);
|
||||
}
|
||||
@@ -169,17 +174,18 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
|
||||
}
|
||||
case NODE_TEXCO_NORMAL: {
|
||||
data = texco_normal_from_uv(
|
||||
kg, sd, sd->u + sd->du.dx * BUMP_DX, sd->v + sd->dv.dx * BUMP_DX);
|
||||
kg, sd, sd->u + sd->du.dx * bump_filter_width, sd->v + sd->dv.dx * bump_filter_width);
|
||||
break;
|
||||
}
|
||||
case NODE_TEXCO_CAMERA: {
|
||||
const Transform tfm = kernel_data.cam.worldtocamera;
|
||||
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
data = transform_point(&tfm, svm_node_bump_P_dx(sd));
|
||||
data = transform_point(&tfm, svm_node_bump_P_dx(sd, bump_filter_width));
|
||||
}
|
||||
else {
|
||||
data = transform_point(&tfm, svm_node_bump_P_dx(sd) + camera_position(kg));
|
||||
data = transform_point(&tfm,
|
||||
svm_node_bump_P_dx(sd, bump_filter_width) + camera_position(kg));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -190,7 +196,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
|
||||
data = camera_world_to_ndc(kg, sd, sd->ray_P);
|
||||
}
|
||||
else {
|
||||
data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dx(sd));
|
||||
data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dx(sd, bump_filter_width));
|
||||
}
|
||||
data.z = 0.0f;
|
||||
break;
|
||||
@@ -213,7 +219,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
case NODE_TEXCO_VOLUME_GENERATED: {
|
||||
data = svm_node_bump_P_dx(sd);
|
||||
data = svm_node_bump_P_dx(sd, bump_filter_width);
|
||||
|
||||
# ifdef __VOLUME__
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
@@ -242,11 +248,13 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
|
||||
float3 data = zero_float3();
|
||||
const uint type = node.y;
|
||||
const uint out_offset = node.z;
|
||||
const float bump_filter_width = __uint_as_float(node.w);
|
||||
|
||||
switch ((NodeTexCoord)type) {
|
||||
case NODE_TEXCO_OBJECT: {
|
||||
data = svm_node_bump_P_dy(sd);
|
||||
if (node.w == 0) {
|
||||
case NODE_TEXCO_OBJECT:
|
||||
case NODE_TEXCO_OBJECT_WITH_TRANSFORM: {
|
||||
data = svm_node_bump_P_dy(sd, bump_filter_width);
|
||||
if (type == NODE_TEXCO_OBJECT) {
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
object_inverse_position_transform(kg, sd, &data);
|
||||
}
|
||||
@@ -262,17 +270,18 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
|
||||
}
|
||||
case NODE_TEXCO_NORMAL: {
|
||||
data = texco_normal_from_uv(
|
||||
kg, sd, sd->u + sd->du.dy * BUMP_DY, sd->v + sd->dv.dy * BUMP_DY);
|
||||
kg, sd, sd->u + sd->du.dy * bump_filter_width, sd->v + sd->dv.dy * bump_filter_width);
|
||||
break;
|
||||
}
|
||||
case NODE_TEXCO_CAMERA: {
|
||||
const Transform tfm = kernel_data.cam.worldtocamera;
|
||||
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
data = transform_point(&tfm, svm_node_bump_P_dy(sd));
|
||||
data = transform_point(&tfm, svm_node_bump_P_dy(sd, bump_filter_width));
|
||||
}
|
||||
else {
|
||||
data = transform_point(&tfm, svm_node_bump_P_dy(sd) + camera_position(kg));
|
||||
data = transform_point(&tfm,
|
||||
svm_node_bump_P_dy(sd, bump_filter_width) + camera_position(kg));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -283,7 +292,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
|
||||
data = camera_world_to_ndc(kg, sd, sd->ray_P);
|
||||
}
|
||||
else {
|
||||
data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dy(sd));
|
||||
data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dy(sd, bump_filter_width));
|
||||
}
|
||||
data.z = 0.0f;
|
||||
break;
|
||||
@@ -306,7 +315,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
|
||||
break;
|
||||
}
|
||||
case NODE_TEXCO_VOLUME_GENERATED: {
|
||||
data = svm_node_bump_P_dy(sd);
|
||||
data = svm_node_bump_P_dy(sd, bump_filter_width);
|
||||
|
||||
# ifdef __VOLUME__
|
||||
if (sd->object != OBJECT_NONE) {
|
||||
|
||||
@@ -112,6 +112,7 @@ enum NodeLightFalloff {
|
||||
enum NodeTexCoord {
|
||||
NODE_TEXCO_NORMAL,
|
||||
NODE_TEXCO_OBJECT,
|
||||
NODE_TEXCO_OBJECT_WITH_TRANSFORM,
|
||||
NODE_TEXCO_CAMERA,
|
||||
NODE_TEXCO_WINDOW,
|
||||
NODE_TEXCO_REFLECTION,
|
||||
@@ -518,8 +519,5 @@ enum ClosureType {
|
||||
#define CLOSURE_WEIGHT_CUTOFF 1e-5f
|
||||
/* Treat closure as singular if the squared roughness is below this threshold. */
|
||||
#define BSDF_ROUGHNESS_SQ_THRESH 2e-10f
|
||||
/* Offset of coordinates for evaluating bump node. Unit in pixel. */
|
||||
#define BUMP_DX 0.1f
|
||||
#define BUMP_DY BUMP_DX
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -7,16 +7,20 @@
|
||||
#include "kernel/geom/attribute.h"
|
||||
#include "kernel/geom/primitive.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "util/math_base.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device_noinline void svm_node_vertex_color(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint layer_id,
|
||||
const uint color_offset,
|
||||
const uint alpha_offset)
|
||||
const uint4 node)
|
||||
{
|
||||
uint layer_id;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
svm_unpack_node_uchar3(node.y, &layer_id, &color_offset, &alpha_offset);
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
@@ -41,23 +45,27 @@ ccl_device_noinline void svm_node_vertex_color(KernelGlobals kg,
|
||||
ccl_device_noinline void svm_node_vertex_color_bump_dx(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint layer_id,
|
||||
const uint color_offset,
|
||||
const uint alpha_offset)
|
||||
const uint4 node)
|
||||
{
|
||||
uint layer_id;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
svm_unpack_node_uchar3(node.y, &layer_id, &color_offset, &alpha_offset);
|
||||
const float bump_filter_width = __uint_as_float(node.z);
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
float4 dfdx;
|
||||
float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, &dfdx, nullptr);
|
||||
vertex_color += dfdx * BUMP_DX;
|
||||
vertex_color += dfdx * bump_filter_width;
|
||||
stack_store_float3(stack, color_offset, make_float3(vertex_color));
|
||||
stack_store_float(stack, alpha_offset, vertex_color.w);
|
||||
}
|
||||
else {
|
||||
float3 dfdx;
|
||||
float3 vertex_color = primitive_surface_attribute_float3(kg, sd, descriptor, &dfdx, nullptr);
|
||||
vertex_color += dfdx * BUMP_DX;
|
||||
vertex_color += dfdx * bump_filter_width;
|
||||
stack_store_float3(stack, color_offset, vertex_color);
|
||||
stack_store_float(stack, alpha_offset, 1.0f);
|
||||
}
|
||||
@@ -71,23 +79,27 @@ ccl_device_noinline void svm_node_vertex_color_bump_dx(KernelGlobals kg,
|
||||
ccl_device_noinline void svm_node_vertex_color_bump_dy(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private float *stack,
|
||||
const uint layer_id,
|
||||
const uint color_offset,
|
||||
const uint alpha_offset)
|
||||
const uint4 node)
|
||||
{
|
||||
uint layer_id;
|
||||
uint color_offset;
|
||||
uint alpha_offset;
|
||||
svm_unpack_node_uchar3(node.y, &layer_id, &color_offset, &alpha_offset);
|
||||
const float bump_filter_width = __uint_as_float(node.z);
|
||||
|
||||
const AttributeDescriptor descriptor = find_attribute(kg, sd, layer_id);
|
||||
if (descriptor.offset != ATTR_STD_NOT_FOUND) {
|
||||
if (descriptor.type == NODE_ATTR_FLOAT4 || descriptor.type == NODE_ATTR_RGBA) {
|
||||
float4 dfdy;
|
||||
float4 vertex_color = primitive_surface_attribute_float4(kg, sd, descriptor, nullptr, &dfdy);
|
||||
vertex_color += dfdy * BUMP_DY;
|
||||
vertex_color += dfdy * bump_filter_width;
|
||||
stack_store_float3(stack, color_offset, make_float3(vertex_color));
|
||||
stack_store_float(stack, alpha_offset, vertex_color.w);
|
||||
}
|
||||
else {
|
||||
float3 dfdy;
|
||||
float3 vertex_color = primitive_surface_attribute_float3(kg, sd, descriptor, nullptr, &dfdy);
|
||||
vertex_color += dfdy * BUMP_DY;
|
||||
vertex_color += dfdy * bump_filter_width;
|
||||
stack_store_float3(stack, color_offset, vertex_color);
|
||||
stack_store_float(stack, alpha_offset, 1.0f);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "kernel/geom/triangle.h"
|
||||
#include "kernel/svm/util.h"
|
||||
#include "kernel/util/differential.h"
|
||||
#include "util/math_base.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -84,10 +85,11 @@ ccl_device_noinline void svm_node_wireframe(KernelGlobals kg,
|
||||
const uint4 node)
|
||||
{
|
||||
const uint in_size = node.y;
|
||||
const uint out_fac = node.z;
|
||||
const float bump_filter_width = __uint_as_float(node.z);
|
||||
uint use_pixel_size;
|
||||
uint bump_offset;
|
||||
svm_unpack_node_uchar2(node.w, &use_pixel_size, &bump_offset);
|
||||
uint out_fac;
|
||||
svm_unpack_node_uchar3(node.w, &use_pixel_size, &bump_offset, &out_fac);
|
||||
|
||||
/* Input Data */
|
||||
const float size = stack_load_float(stack, in_size);
|
||||
@@ -98,10 +100,10 @@ ccl_device_noinline void svm_node_wireframe(KernelGlobals kg,
|
||||
|
||||
float3 P = sd->P;
|
||||
if (bump_offset == NODE_BUMP_OFFSET_DX) {
|
||||
P += dP.dx * BUMP_DX;
|
||||
P += dP.dx * bump_filter_width;
|
||||
}
|
||||
else if (bump_offset == NODE_BUMP_OFFSET_DY) {
|
||||
P += dP.dy * BUMP_DY;
|
||||
P += dP.dy * bump_filter_width;
|
||||
}
|
||||
|
||||
const float f = wireframe(kg, sd, dP, size, pixel_size, &P);
|
||||
|
||||
@@ -924,6 +924,7 @@ void ShaderGraph::refine_bump_nodes()
|
||||
ShaderNode *node = nodes[i];
|
||||
|
||||
if (node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
|
||||
BumpNode *bump = static_cast<BumpNode *>(node);
|
||||
ShaderInput *bump_input = node->input("Height");
|
||||
ShaderNodeSet nodes_bump;
|
||||
|
||||
@@ -941,12 +942,15 @@ void ShaderGraph::refine_bump_nodes()
|
||||
* that any texture coordinates are shifted by dx/dy when sampling. */
|
||||
for (ShaderNode *node : nodes_bump) {
|
||||
node->bump = SHADER_BUMP_CENTER;
|
||||
node->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
for (const NodePair &pair : nodes_dx) {
|
||||
pair.second->bump = SHADER_BUMP_DX;
|
||||
pair.second->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
for (const NodePair &pair : nodes_dy) {
|
||||
pair.second->bump = SHADER_BUMP_DY;
|
||||
pair.second->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
|
||||
ShaderOutput *out = bump_input->link;
|
||||
@@ -992,6 +996,11 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
ShaderNodeSet nodes_displace;
|
||||
find_dependencies(nodes_displace, displacement_in);
|
||||
|
||||
/* Add bump node. */
|
||||
BumpNode *bump = create_node<BumpNode>();
|
||||
bump->set_use_object_space(use_object_space);
|
||||
bump->set_distance(1.0f);
|
||||
|
||||
/* copy nodes for 3 bump samples */
|
||||
ShaderNodeMap nodes_center;
|
||||
ShaderNodeMap nodes_dx;
|
||||
@@ -1005,12 +1014,15 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
* that any texture coordinates are shifted by dx/dy when sampling */
|
||||
for (const NodePair &pair : nodes_center) {
|
||||
pair.second->bump = SHADER_BUMP_CENTER;
|
||||
pair.second->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
for (const NodePair &pair : nodes_dx) {
|
||||
pair.second->bump = SHADER_BUMP_DX;
|
||||
pair.second->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
for (const NodePair &pair : nodes_dy) {
|
||||
pair.second->bump = SHADER_BUMP_DY;
|
||||
pair.second->bump_filter_width = bump->get_filter_width();
|
||||
}
|
||||
|
||||
/* add set normal node and connect the bump normal output to the set normal
|
||||
@@ -1019,11 +1031,7 @@ void ShaderGraph::bump_from_displacement(bool use_object_space)
|
||||
* overwrite the shader normal */
|
||||
ShaderNode *set_normal = create_node<SetNormalNode>();
|
||||
|
||||
/* add bump node and connect copied graphs to it */
|
||||
BumpNode *bump = create_node<BumpNode>();
|
||||
bump->set_use_object_space(use_object_space);
|
||||
bump->set_distance(1.0f);
|
||||
|
||||
/* Connect copied graphs to bump node. */
|
||||
ShaderOutput *out = displacement_in->link;
|
||||
ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
|
||||
ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
|
||||
|
||||
@@ -212,6 +212,7 @@ class ShaderNode : public Node {
|
||||
int id = -1;
|
||||
/* for bump mapping utility */
|
||||
ShaderBump bump = SHADER_BUMP_NONE;
|
||||
float bump_filter_width = 0.0f;
|
||||
/* special node type */
|
||||
ShaderNodeSpecialType special_type = SHADER_SPECIAL_TYPE_NONE;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "kernel/svm/types.h"
|
||||
#include "scene/colorspace.h"
|
||||
#include "scene/constant_fold.h"
|
||||
#include "scene/film.h"
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "util/color.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/math_base.h"
|
||||
#include "util/transform.h"
|
||||
|
||||
#include "kernel/svm/color_util.h"
|
||||
@@ -3948,32 +3950,38 @@ void GeometryNode::compile(SVMCompiler &compiler)
|
||||
|
||||
out = output("Position");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_P, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Normal");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_N, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Tangent");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_T, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("True Normal");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_Ng, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Incoming");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_I, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Parametric");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_uv, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Backfacing");
|
||||
@@ -3984,8 +3992,10 @@ void GeometryNode::compile(SVMCompiler &compiler)
|
||||
out = output("Pointiness");
|
||||
if (!out->links.empty()) {
|
||||
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
|
||||
compiler.add_node(
|
||||
attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT);
|
||||
compiler.add_node(attr_node,
|
||||
ATTR_STD_POINTINESS,
|
||||
compiler.encode_uchar4(compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
|
||||
@@ -3997,8 +4007,8 @@ void GeometryNode::compile(SVMCompiler &compiler)
|
||||
if (compiler.output_type() != SHADER_TYPE_VOLUME) {
|
||||
compiler.add_node(attr_node,
|
||||
ATTR_STD_RANDOM_PER_ISLAND,
|
||||
compiler.stack_assign(out),
|
||||
NODE_ATTR_OUTPUT_FLOAT);
|
||||
compiler.encode_uchar4(compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
|
||||
@@ -4017,6 +4027,7 @@ void GeometryNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
compiler.add(this, "node_geometry");
|
||||
}
|
||||
@@ -4089,41 +4100,65 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
|
||||
out = output("Generated");
|
||||
if (!out->links.empty()) {
|
||||
if (compiler.background) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_P, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
if (from_dupli) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_DUPLI_GENERATED,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_VOLUME_GENERATED,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
const int attr = compiler.attribute(ATTR_STD_GENERATED);
|
||||
compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
|
||||
compiler.add_node(
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out = output("Normal");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_NORMAL,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("UV");
|
||||
if (!out->links.empty()) {
|
||||
if (from_dupli) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_DUPLI_UV,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
const int attr = compiler.attribute(ATTR_STD_UV);
|
||||
compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
|
||||
compiler.add_node(
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
|
||||
out = output("Object");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
|
||||
compiler.add_node(texco_node,
|
||||
(use_transform) ? NODE_TEXCO_OBJECT_WITH_TRANSFORM : NODE_TEXCO_OBJECT,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
if (use_transform) {
|
||||
const Transform ob_itfm = transform_inverse(ob_tfm);
|
||||
compiler.add_node(ob_itfm.x);
|
||||
@@ -4134,21 +4169,31 @@ void TextureCoordinateNode::compile(SVMCompiler &compiler)
|
||||
|
||||
out = output("Camera");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_CAMERA,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Window");
|
||||
if (!out->links.empty()) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_WINDOW,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
out = output("Reflection");
|
||||
if (!out->links.empty()) {
|
||||
if (compiler.background) {
|
||||
compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
|
||||
compiler.add_node(
|
||||
geom_node, NODE_GEOM_I, compiler.stack_assign(out), __float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_REFLECTION,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4164,6 +4209,7 @@ void TextureCoordinateNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
if (compiler.background) {
|
||||
compiler.parameter("is_background", true);
|
||||
@@ -4232,7 +4278,10 @@ void UVMapNode::compile(SVMCompiler &compiler)
|
||||
|
||||
if (!out->links.empty()) {
|
||||
if (from_dupli) {
|
||||
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
|
||||
compiler.add_node(texco_node,
|
||||
NODE_TEXCO_DUPLI_UV,
|
||||
compiler.stack_assign(out),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
else {
|
||||
if (!attribute.empty()) {
|
||||
@@ -4242,7 +4291,11 @@ void UVMapNode::compile(SVMCompiler &compiler)
|
||||
attr = compiler.attribute(ATTR_STD_UV);
|
||||
}
|
||||
|
||||
compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3);
|
||||
compiler.add_node(
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(out), NODE_ATTR_OUTPUT_FLOAT3),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4258,6 +4311,7 @@ void UVMapNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
compiler.parameter(this, "from_dupli");
|
||||
compiler.parameter(this, "attribute");
|
||||
@@ -4857,8 +4911,11 @@ void VertexColorNode::compile(SVMCompiler &compiler)
|
||||
node = NODE_VERTEX_COLOR;
|
||||
}
|
||||
|
||||
compiler.add_node(
|
||||
node, layer_id, compiler.stack_assign(color_out), compiler.stack_assign(alpha_out));
|
||||
compiler.add_node(node,
|
||||
compiler.encode_uchar4(layer_id,
|
||||
compiler.stack_assign(color_out),
|
||||
compiler.stack_assign(alpha_out)),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
void VertexColorNode::compile(OSLCompiler &compiler)
|
||||
@@ -4872,6 +4929,7 @@ void VertexColorNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
if (layer_name.empty()) {
|
||||
compiler.parameter("layer_name", ustring("geom:vertex_color"));
|
||||
@@ -6052,21 +6110,34 @@ void AttributeNode::compile(SVMCompiler &compiler)
|
||||
if (!color_out->links.empty() || !vector_out->links.empty()) {
|
||||
if (!color_out->links.empty()) {
|
||||
compiler.add_node(
|
||||
attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3);
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(color_out), NODE_ATTR_OUTPUT_FLOAT3),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
if (!vector_out->links.empty()) {
|
||||
compiler.add_node(
|
||||
attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3);
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(vector_out), NODE_ATTR_OUTPUT_FLOAT3),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
|
||||
if (!fac_out->links.empty()) {
|
||||
compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT);
|
||||
compiler.add_node(
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(fac_out), NODE_ATTR_OUTPUT_FLOAT),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
|
||||
if (!alpha_out->links.empty()) {
|
||||
compiler.add_node(
|
||||
attr_node, attr, compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA);
|
||||
attr_node,
|
||||
attr,
|
||||
compiler.encode_uchar4(compiler.stack_assign(alpha_out), NODE_ATTR_OUTPUT_FLOAT_ALPHA),
|
||||
__float_as_uint(bump_filter_width));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6081,6 +6152,7 @@ void AttributeNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE) {
|
||||
compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
|
||||
@@ -6234,10 +6306,11 @@ void WireframeNode::compile(SVMCompiler &compiler)
|
||||
else if (bump == SHADER_BUMP_DY) {
|
||||
bump_offset = NODE_BUMP_OFFSET_DY;
|
||||
}
|
||||
compiler.add_node(NODE_WIREFRAME,
|
||||
compiler.stack_assign(size_in),
|
||||
compiler.stack_assign(fac_out),
|
||||
compiler.encode_uchar4(use_pixel_size, bump_offset, 0, 0));
|
||||
compiler.add_node(
|
||||
NODE_WIREFRAME,
|
||||
compiler.stack_assign(size_in),
|
||||
__float_as_uint(bump_filter_width),
|
||||
compiler.encode_uchar4(use_pixel_size, bump_offset, compiler.stack_assign(fac_out), 0));
|
||||
}
|
||||
|
||||
void WireframeNode::compile(OSLCompiler &compiler)
|
||||
@@ -6251,6 +6324,8 @@ void WireframeNode::compile(OSLCompiler &compiler)
|
||||
else {
|
||||
compiler.parameter("bump_offset", "center");
|
||||
}
|
||||
compiler.parameter("bump_filter_width", bump_filter_width);
|
||||
|
||||
compiler.parameter(this, "use_pixel_size");
|
||||
compiler.add(this, "node_wireframe");
|
||||
}
|
||||
@@ -6976,6 +7051,7 @@ NODE_DEFINE(BumpNode)
|
||||
SOCKET_IN_NORMAL(normal, "Normal", zero_float3(), SocketType::LINK_NORMAL);
|
||||
SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
|
||||
SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
|
||||
SOCKET_IN_FLOAT(filter_width, "Filter Width", 0.1f);
|
||||
|
||||
SOCKET_OUT_NORMAL(normal, "Normal");
|
||||
|
||||
@@ -7009,6 +7085,7 @@ void BumpNode::compile(SVMCompiler &compiler)
|
||||
compiler.stack_assign(dy_in),
|
||||
compiler.stack_assign(strength_in)),
|
||||
compiler.encode_uchar4(compiler.stack_assign(normal_out), compiler.get_bump_state_offset()));
|
||||
compiler.add_node(__float_as_uint(filter_width));
|
||||
}
|
||||
|
||||
void BumpNode::compile(OSLCompiler &compiler)
|
||||
|
||||
@@ -1480,6 +1480,7 @@ class BumpNode : public ShaderNode {
|
||||
NODE_SOCKET_API(bool, invert)
|
||||
NODE_SOCKET_API(bool, use_object_space)
|
||||
NODE_SOCKET_API(float, height)
|
||||
NODE_SOCKET_API(float, filter_width)
|
||||
NODE_SOCKET_API(float, sample_center)
|
||||
NODE_SOCKET_API(float, sample_x)
|
||||
NODE_SOCKET_API(float, sample_y)
|
||||
|
||||
@@ -1287,6 +1287,21 @@ static void do_version_color_to_float_conversion(bNodeTree *node_tree)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_version_bump_filter_width(bNodeTree *node_tree)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_tree->nodes) {
|
||||
if (node->type_legacy != SH_NODE_BUMP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bNodeSocket *filter_width_input = blender::bke::node_find_socket(
|
||||
node, SOCK_IN, "Filter Width");
|
||||
if (filter_width_input) {
|
||||
*version_cycles_node_socket_float_value(filter_width_input) = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void do_version_viewer_shortcut(bNodeTree *node_tree)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_tree->nodes) {
|
||||
@@ -1636,6 +1651,9 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
|
||||
if (ntree->type == NTREE_COMPOSIT) {
|
||||
do_version_color_to_float_conversion(ntree);
|
||||
}
|
||||
else if (ntree->type == NTREE_SHADER) {
|
||||
do_version_bump_filter_width(ntree);
|
||||
}
|
||||
}
|
||||
FOREACH_NODETREE_END;
|
||||
}
|
||||
|
||||
@@ -621,8 +621,12 @@ vec2 bsdf_lut(float cos_theta, float roughness, float ior, bool do_multiscatter)
|
||||
vec3 displacement_bump()
|
||||
{
|
||||
# if defined(GPU_FRAGMENT_SHADER) && !defined(MAT_GEOM_CURVES)
|
||||
/* This is the filter width for automatic displacement + bump mapping, which is fixed.
|
||||
* NOTE: keep the same as default bump node filter width. */
|
||||
const float bump_filter_width = 0.1;
|
||||
|
||||
vec2 dHd;
|
||||
dF_branch(dot(nodetree_displacement(), g_data.N + dF_impl(g_data.N)), dHd);
|
||||
dF_branch(dot(nodetree_displacement(), g_data.N + dF_impl(g_data.N)), bump_filter_width, dHd);
|
||||
|
||||
vec3 dPdx = dFdx(g_data.P);
|
||||
vec3 dPdy = dFdy(g_data.P);
|
||||
@@ -637,9 +641,7 @@ vec3 displacement_bump()
|
||||
vec3 surfgrad = dHd.x * Rx + dHd.y * Ry;
|
||||
|
||||
float facing = FrontFacing ? 1.0 : -1.0;
|
||||
/* NOTE: keep the same as defined `BUMP_DX`. */
|
||||
const float bump_dx = 0.1;
|
||||
return normalize(bump_dx * abs(det) * g_data.N - facing * sign(det) * surfgrad);
|
||||
return normalize(bump_filter_width * abs(det) * g_data.N - facing * sign(det) * surfgrad);
|
||||
# else
|
||||
return g_data.N;
|
||||
# endif
|
||||
|
||||
@@ -186,7 +186,7 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *r_
|
||||
* The given function should return a float.
|
||||
* The result will be a vec2 containing dFdx and dFdy result of that function.
|
||||
*/
|
||||
GPUNodeLink *GPU_differentiate_float_function(const char *function_name);
|
||||
GPUNodeLink *GPU_differentiate_float_function(const char *function_name, const float filter_width);
|
||||
|
||||
bool GPU_link(GPUMaterial *mat, const char *name, ...);
|
||||
bool GPU_stack_link(GPUMaterial *mat,
|
||||
|
||||
@@ -151,7 +151,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
|
||||
case GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN:
|
||||
input->source = GPU_SOURCE_FUNCTION_CALL;
|
||||
/* NOTE(@fclem): End of function call is the return variable set during codegen. */
|
||||
SNPRINTF(input->function_call, "dF_branch_incomplete(%s(), ", link->function_name);
|
||||
SNPRINTF(input->function_call,
|
||||
"dF_branch_incomplete(%s(), %g, ",
|
||||
link->differentiate_float.function_name,
|
||||
link->differentiate_float.filter_width);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -638,11 +641,12 @@ GPUNodeLink *GPU_uniform(const float *num)
|
||||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_differentiate_float_function(const char *function_name)
|
||||
GPUNodeLink *GPU_differentiate_float_function(const char *function_name, const float filter_width)
|
||||
{
|
||||
GPUNodeLink *link = gpu_node_link_create();
|
||||
link->link_type = GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN;
|
||||
link->function_name = function_name;
|
||||
link->differentiate_float.function_name = function_name;
|
||||
link->differentiate_float.filter_width = filter_width;
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,10 @@ struct GPUNodeLink {
|
||||
/* GPU_NODE_LINK_IMAGE_BLENDER */
|
||||
GPUMaterialTexture *texture;
|
||||
/* GPU_NODE_LINK_DIFFERENTIATE_FLOAT_FN */
|
||||
const char *function_name;
|
||||
struct {
|
||||
const char *function_name;
|
||||
float filter_width;
|
||||
} differentiate_float;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -322,8 +322,8 @@ GlobalData g_data;
|
||||
/* Stubs. */
|
||||
|
||||
# define dF_impl(a) (vec3(0.0))
|
||||
# define dF_branch(a, b) (b = vec2(0.0))
|
||||
# define dF_branch_incomplete(a, b) (b = vec2(0.0))
|
||||
# define dF_branch(a, b, c) (c = vec2(0.0))
|
||||
# define dF_branch_incomplete(a, b, c) (c = vec2(0.0))
|
||||
|
||||
#elif defined(GPU_FAST_DERIVATIVE) /* TODO(@fclem): User Option? */
|
||||
/* Fast derivatives */
|
||||
@@ -334,33 +334,33 @@ vec3 dF_impl(vec3 v)
|
||||
|
||||
void dF_branch(float fn, out vec2 result)
|
||||
{
|
||||
/* NOTE: this function is currently unused, once it is used we need to check if `BUMP_DX/BUMP_DY`
|
||||
* needs to be applied. */
|
||||
/* NOTE: this function is currently unused, once it is used we need to check if
|
||||
* `g_derivative_filter_width` needs to be applied. */
|
||||
result.x = dFdx(fn);
|
||||
result.y = dFdy(fn);
|
||||
}
|
||||
|
||||
#else
|
||||
/* Offset of coordinates for evaluating bump node. Unit in pixel. */
|
||||
# define BUMP_DX 0.1
|
||||
# define BUMP_DY BUMP_DX
|
||||
|
||||
/* Offset of coordinates for evaluating bump node. Unit in pixel. */
|
||||
float g_derivative_filter_width = 0.0;
|
||||
/* Precise derivatives */
|
||||
int g_derivative_flag = 0;
|
||||
|
||||
vec3 dF_impl(vec3 v)
|
||||
{
|
||||
if (g_derivative_flag > 0) {
|
||||
return dFdx(v) * BUMP_DX;
|
||||
return dFdx(v) * g_derivative_filter_width;
|
||||
}
|
||||
else if (g_derivative_flag < 0) {
|
||||
return dFdy(v) * BUMP_DY;
|
||||
return dFdy(v) * g_derivative_filter_width;
|
||||
}
|
||||
return vec3(0.0);
|
||||
}
|
||||
|
||||
# define dF_branch(fn, result) \
|
||||
# define dF_branch(fn, filter_width, result) \
|
||||
if (true) { \
|
||||
g_derivative_filter_width = filter_width; \
|
||||
g_derivative_flag = 1; \
|
||||
result.x = (fn); \
|
||||
g_derivative_flag = -1; \
|
||||
@@ -370,8 +370,9 @@ vec3 dF_impl(vec3 v)
|
||||
}
|
||||
|
||||
/* Used when the non-offset value is already computed elsewhere */
|
||||
# define dF_branch_incomplete(fn, result) \
|
||||
# define dF_branch_incomplete(fn, filter_width, result) \
|
||||
if (true) { \
|
||||
g_derivative_filter_width = filter_width; \
|
||||
g_derivative_flag = 1; \
|
||||
result.x = (fn); \
|
||||
g_derivative_flag = -1; \
|
||||
|
||||
@@ -18,6 +18,7 @@ void differentiate_texco(vec4 v, out vec3 df)
|
||||
void node_bump(float strength,
|
||||
float dist,
|
||||
float height,
|
||||
float filter_width,
|
||||
vec3 N,
|
||||
vec2 height_xy,
|
||||
float invert,
|
||||
@@ -42,9 +43,7 @@ void node_bump(float strength,
|
||||
|
||||
strength = max(strength, 0.0);
|
||||
|
||||
/* NOTE: keep the same as defined `BUMP_DX`. */
|
||||
const float bump_dx = 0.1;
|
||||
result = normalize(bump_dx * abs(det) * N - dist * sign(det) * surfgrad);
|
||||
result = normalize(filter_width * abs(det) * N - dist * sign(det) * surfgrad);
|
||||
result = normalize(mix(N, result, strength));
|
||||
#else
|
||||
result = N;
|
||||
|
||||
@@ -32,7 +32,21 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
.max(1000.0f)
|
||||
.description(
|
||||
"Multiplier for the height value to control the overall distance for bump mapping");
|
||||
b.add_input<decl::Float>("Height").default_value(1.0f).min(-1000.0f).max(1000.0f).hide_value();
|
||||
b.add_input<decl::Float>("Filter Width")
|
||||
.default_value(0.1f)
|
||||
.min(0.001)
|
||||
.max(10.0f)
|
||||
.subtype(PROP_PIXEL)
|
||||
.description(
|
||||
"Filter width in pixels, used to compute the bump mapping direction. For most textures "
|
||||
"the default value of 0.1 enables subpixel filtering for stable results. For stepwise "
|
||||
"textures a larger filter width can be used to get a bevel like effect on the edges");
|
||||
b.add_input<decl::Float>("Height")
|
||||
.default_value(1.0f)
|
||||
.min(-1000.0f)
|
||||
.max(1000.0f)
|
||||
.hide_value()
|
||||
.description("Height above surface. Connect the height map texture to this input");
|
||||
b.add_input<decl::Vector>("Normal").min(-1.0f).max(1.0f).hide_value();
|
||||
b.add_output<decl::Vector>("Normal");
|
||||
}
|
||||
@@ -61,6 +75,7 @@ static int gpu_shader_bump(GPUMaterial *mat,
|
||||
GPU_link(mat, "world_normals_get", &in[3].link);
|
||||
}
|
||||
|
||||
const float filter_width = in[4].vec[0];
|
||||
const char *height_function = GPU_material_split_sub_function(mat, GPU_FLOAT, &in[2].link);
|
||||
|
||||
/* TODO (Miguel Pozo):
|
||||
@@ -71,7 +86,7 @@ static int gpu_shader_bump(GPUMaterial *mat,
|
||||
* A better option would be to add a "value" input socket (in this case the height) to the
|
||||
* differentiate node, but currently this kind of intermediate nodes are pruned in the
|
||||
* code generation process (see #104265), so we need to fix that first. */
|
||||
GPUNodeLink *dheight = GPU_differentiate_float_function(height_function);
|
||||
GPUNodeLink *dheight = GPU_differentiate_float_function(height_function, filter_width);
|
||||
|
||||
float invert = (node->custom1) ? -1.0 : 1.0;
|
||||
|
||||
|
||||
@@ -254,9 +254,12 @@ def main():
|
||||
# OSL tests:
|
||||
# Blackbody is slightly different between SVM and OSL.
|
||||
# Microfacet hair renders slightly differently, and fails on Windows and Linux with OSL
|
||||
#
|
||||
# both_displacement.blend has slight differences between Linux and other platforms.
|
||||
|
||||
test_dir_name = Path(args.testdir).name
|
||||
if (test_dir_name in {'motion_blur', 'integrator'}) or ((args.osl) and (test_dir_name in {'shader', 'hair'})):
|
||||
if (test_dir_name in {'motion_blur', 'integrator', "displacement"}) or \
|
||||
((args.osl) and (test_dir_name in {'shader', 'hair'})):
|
||||
report.set_fail_threshold(0.032)
|
||||
|
||||
# Layer mixing is different between SVM and OSL, so a few tests have
|
||||
|
||||
Reference in New Issue
Block a user