Node: Gabor Noise Texture #110802

Open
Charlie Jolly wants to merge 68 commits from CharlieJolly/blender:gabor into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
10 changed files with 154 additions and 130 deletions
Showing only changes of commit 1b53cd0928 - Show all commits

View File

@ -942,7 +942,7 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeTexGabor)) {
BL::ShaderNodeTexGabor b_gabor_node(b_node);
GaborTextureNode *gabor = graph->create_node<GaborTextureNode>();
gabor->set_kernel_shape((NodeGaborKernel)b_gabor_node.kernel());
gabor->set_mode((NodeGaborMode)b_gabor_node.mode());
gabor->set_anisotropic((NodeGaborAnisotropic)b_gabor_node.anisotropic());
gabor->set_dimensions(b_gabor_node.gabor_dimensions());
gabor->set_periodic(b_gabor_node.periodic());

View File

@ -40,7 +40,7 @@ struct GaborParams {
float cell_randomness;
float rotation;
float rot_variance;
string kernel_shape;
string mode;
string anisotropic;
vector direction;
};
@ -62,18 +62,22 @@ int impulses_per_cell(int seed, vector3 cell, float impulses)
vector3 gabor_kernel(GaborParams gp, float freq, point omega, float phi, point position, float g)
{
float h;
if (gp.kernel_shape == "phasor") { /* SHD_GABOR_KERNEL_PHASOR */
if (gp.mode == "phasor") { /* SHD_GABOR_MODE_PHASOR */
float phase = freq * dot(omega, position) + phi;
return vector3(cos(phase), sin(phase), 0.0) * g;
}
else if (gp.kernel_shape == "square") { /* SHD_GABOR_KERNEL_SQUARE */
else if (gp.mode == "phasor_cross") { /* SHD_GABOR_MODE_PHASOR_CROSS */
float phase = freq * length(position * omega) + phi;
return g * vector3(cos(phase), sin(phase), 0.0);
}
else if (gp.mode == "square") { /* SHD_GABOR_MODE_SQUARE */
vector3 positionyx = vector3(position.y, position.x, position.z);
h = (cos(freq * dot(omega, position) + phi) + cos(freq * dot(omega, positionyx) + phi)) * 0.5;
}
else if (gp.kernel_shape == "cross") { /* SHD_GABOR_KERNEL_CROSS */
else if (gp.mode == "cross") { /* SHD_GABOR_MODE_CROSS */
h = cos(freq * length(position * omega) + phi);
}
else if (gp.kernel_shape == "ring" /* SHD_GABOR_KERNEL_RING */) {
else if (gp.mode == "ring" /* SHD_GABOR_MODE_RING */) {
h = cos(freq * dot(position, omega) + phi) - cos(freq * length(position) + phi);
}
else {
@ -200,7 +204,7 @@ float gabor_grid_3d(output GaborParams gp, point p, float scale, int seed, int p
}
}
if (gp.kernel_shape == "phasor") {
if (gp.mode == "phasor" || gp.mode == "phasor_cross") {
float pn = atan2(sum.y, sum.x) / M_PI;
return pn;
}
@ -231,7 +235,7 @@ float gabor_grid_2d(output GaborParams gp, point p, float scale, int seed, int p
}
}
if (gp.kernel_shape == "phasor") {
if (gp.mode == "phasor" || gp.mode == "phasor_cross") {
float pn = atan2(sum.y, sum.x) / M_PI;
return pn;
}
@ -255,7 +259,7 @@ GaborParams gabor_parameters(vector direction,
float cell_randomness,
float rotation,
float rot_variance,
string kernel_shape,
string mode,
string anisotropic,
int periodic)
{
@ -268,7 +272,7 @@ GaborParams gabor_parameters(vector direction,
gp.fre_lacunarity = fre_lacunarity;
gp.rot_lacunarity = rot_lacunarity;
gp.anisotropic = anisotropic;
gp.kernel_shape = kernel_shape;
gp.mode = mode;
gp.direction = direction;
gp.phase = phase;
gp.rotation = rotation;
@ -334,7 +338,7 @@ float gabor_noise(point p,
float rotation,
float rot_variance,
string dimensions,
string kernel_shape,
string mode,
string anisotropic,
int use_normalize,
int periodic)
@ -361,7 +365,7 @@ float gabor_noise(point p,
cell_randomness,
rotation,
rot_variance,
kernel_shape,
mode,
anisotropic,
use_normalize);
@ -382,7 +386,7 @@ float gabor_noise(point p,
shader node_gabor_texture(int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
string dimensions = "2D",
string kernel_shape = "gabor",
string mode = "gabor",
string anisotropic = "iso",
int use_normalize = 1,
int periodic = 0,
@ -428,7 +432,7 @@ shader node_gabor_texture(int use_mapping = 0,
Rotation,
RotationVariance,
dimensions,
kernel_shape,
mode,
anisotropic,
use_normalize,
periodic);

View File

@ -34,7 +34,7 @@ typedef struct GaborParams {
float cell_randomness;
float rotation;
float rot_variance;
int kernel_shape;
int mode;
int anisotropic;
float3 direction;
} GaborParams;
@ -55,21 +55,25 @@ gabor_kernel(GaborParams gp, float freq, float3 omega, float phi, float3 positio
{
float h;
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR) {
float phase = freq * dot(omega, position) + phi;
return make_float3(cos(phase), sin(phase), 0.0f) * g;
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_SQUARE) {
if (gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float phase = freq * len(position * omega) + phi;
return make_float3(cos(phase), sin(phase), 0.0f) * g;
}
else if (gp.mode == SHD_GABOR_MODE_SQUARE) {
float3 positionyx = make_float3(position.y, position.x, position.z);
h = (cos(freq * dot(omega, position) + phi) + cos(freq * dot(omega, positionyx) + phi)) * 0.5f;
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_CROSS) {
else if (gp.mode == SHD_GABOR_MODE_CROSS) {
h = cos(freq * len(position * omega) + phi);
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_RING) {
else if (gp.mode == SHD_GABOR_MODE_RING) {
h = cos(freq * dot(position, omega) + phi) - cos(freq * len(position) + phi);
}
else { // SHD_GABOR_KERNEL_GABOR
else { // SHD_GABOR_MODE_GABOR
h = cos(freq * dot(omega, position) + phi);
}
@ -194,7 +198,7 @@ ccl_device float gabor_grid_3d(GaborParams gp, float3 p, float scale, int seed,
}
}
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float pn = atan2f(sum.y, sum.x) / M_PI_F;
return pn;
}
@ -225,7 +229,7 @@ ccl_device float gabor_grid_2d(GaborParams gp, float3 p, float scale, int seed,
}
}
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float pn = atan2f(sum.y, sum.x) / M_PI_F;
return pn;
}
@ -283,7 +287,7 @@ ccl_device GaborParams gabor_parameters(float3 direction,
float cell_randomness,
float rotation,
float rot_variance,
int kernel_shape,
int mode,
int anisotropic)
{
GaborParams gp;
@ -295,7 +299,7 @@ ccl_device GaborParams gabor_parameters(float3 direction,
gp.fre_lacunarity = fre_lacunarity;
gp.rot_lacunarity = rot_lacunarity;
gp.anisotropic = anisotropic;
gp.kernel_shape = kernel_shape;
gp.mode = mode;
gp.direction = direction;
gp.phase = phase;
gp.rotation = rotation;
@ -327,7 +331,7 @@ ccl_device float gabor_noise(float3 p,
float rotation,
float rot_variance,
int dimensions,
int kernel_shape,
int mode,
int anisotropic,
int normalize,
int periodic)
@ -351,7 +355,7 @@ ccl_device float gabor_noise(float3 p,
cell_randomness,
rotation,
rot_variance,
kernel_shape,
mode,
anisotropic);
float g = gabor_fractal_noise(gp, p, scale, dimensions, periodic);
@ -376,7 +380,7 @@ ccl_device_noinline int svm_node_tex_gabor(
/* Input and Output Sockets */
uint vector_in_offset, scale_offset, detail_offset, phase_offset, impulse_offset;
uint direction_offset, value_out_offset, fre_lacunarity_offset;
uint kernel_shape_offset, aniso_offset, periodic_offset, roughness_offset;
uint mode_offset, aniso_offset, periodic_offset, roughness_offset;
uint rot_variance_offset, phase_variance_offset, rotation_offset, bandwidth_offset,
cell_randomness_offset;
uint scl_lacunarity_offset, use_normalize_offset, dimension_offset, rot_lacunarity_offset;
@ -397,7 +401,7 @@ ccl_device_noinline int svm_node_tex_gabor(
svm_unpack_node_uchar4(
node2.y, &rot_variance_offset, &direction_offset, &value_out_offset, &dimension_offset);
svm_unpack_node_uchar4(
node2.z, &kernel_shape_offset, &aniso_offset, &periodic_offset, &use_normalize_offset);
node2.z, &mode_offset, &aniso_offset, &periodic_offset, &use_normalize_offset);
float3 vector_in = stack_load_float3(stack, vector_in_offset);
@ -442,7 +446,7 @@ ccl_device_noinline int svm_node_tex_gabor(
rotation,
rot_variance,
dimension_offset,
kernel_shape_offset,
mode_offset,
aniso_offset,
use_normalize_offset,
periodic_offset);

View File

@ -409,17 +409,18 @@ typedef enum NodeCombSepColorType {
NODE_COMBSEP_COLOR_HSL,
} NodeCombSepColorType;
typedef enum NodeGaborKernel {
SHD_GABOR_KERNEL_GABOR,
SHD_GABOR_KERNEL_RING,
SHD_GABOR_KERNEL_CROSS,
SHD_GABOR_KERNEL_SQUARE,
SHD_GABOR_KERNEL_PHASOR,
} NodeGaborKernel;
typedef enum NodeGaborMode {
SHD_GABOR_MODE_GABOR,
SHD_GABOR_MODE_RING,
SHD_GABOR_MODE_CROSS,
SHD_GABOR_MODE_SQUARE,
SHD_GABOR_MODE_PHASOR,
SHD_GABOR_MODE_PHASOR_CROSS,
} NodeGaborMode;
typedef enum NodeGaborAnisotropic {
SHD_GABOR_MODE_ISOTROPIC,
SHD_GABOR_MODE_ANISOTROPIC,
SHD_GABOR_ISOTROPIC,
SHD_GABOR_ANISOTROPIC,
} NodeGaborAnisotropic;
/* Closure */

View File

@ -1202,18 +1202,19 @@ NODE_DEFINE(GaborTextureNode)
dimensions_enum.insert("3D", 3);
SOCKET_ENUM(dimensions, "Dimensions", dimensions_enum, 2);
static NodeEnum mode_enum;
mode_enum.insert("iso", SHD_GABOR_MODE_ISOTROPIC);
mode_enum.insert("aniso", SHD_GABOR_MODE_ANISOTROPIC);
SOCKET_ENUM(anisotropic, "Anisotropic", mode_enum, SHD_GABOR_MODE_ISOTROPIC);
static NodeEnum aniso_enum;
aniso_enum.insert("iso", SHD_GABOR_ISOTROPIC);
aniso_enum.insert("aniso", SHD_GABOR_ANISOTROPIC);
SOCKET_ENUM(anisotropic, "Anisotropic", aniso_enum, SHD_GABOR_ISOTROPIC);
static NodeEnum kernel_enum;
kernel_enum.insert("gabor", SHD_GABOR_KERNEL_GABOR);
kernel_enum.insert("ring", SHD_GABOR_KERNEL_RING);
kernel_enum.insert("cross", SHD_GABOR_KERNEL_CROSS);
kernel_enum.insert("square", SHD_GABOR_KERNEL_SQUARE);
kernel_enum.insert("phasor", SHD_GABOR_KERNEL_PHASOR);
SOCKET_ENUM(kernel_shape, "Kernel", kernel_enum, SHD_GABOR_KERNEL_GABOR);
static NodeEnum mode_enum;
mode_enum.insert("gabor", SHD_GABOR_MODE_GABOR);
mode_enum.insert("ring", SHD_GABOR_MODE_RING);
mode_enum.insert("cross", SHD_GABOR_MODE_CROSS);
mode_enum.insert("square", SHD_GABOR_MODE_SQUARE);
mode_enum.insert("phasor", SHD_GABOR_MODE_PHASOR);
mode_enum.insert("phasor_cross", SHD_GABOR_MODE_PHASOR_CROSS);
SOCKET_ENUM(mode, "Mode", mode_enum, SHD_GABOR_MODE_GABOR);
SOCKET_BOOLEAN(periodic, "Periodic", false);
SOCKET_BOOLEAN(use_normalize, "Normalize", true);
@ -1320,7 +1321,7 @@ void GaborTextureNode::compile(SVMCompiler &compiler)
direction_in_stack_offset,
value_out_stack_offset,
dimensions),
compiler.encode_uchar4(kernel_shape, anisotropic, periodic, use_normalize));
compiler.encode_uchar4(mode, anisotropic, periodic, use_normalize));
compiler.add_node(__float_as_int(scale),
__float_as_int(base_frequency),
@ -1344,7 +1345,7 @@ void GaborTextureNode::compile(OSLCompiler &compiler)
{
tex_mapping.compile(compiler);
compiler.parameter(this, "dimensions");
compiler.parameter(this, "kernel_shape");
compiler.parameter(this, "mode");
compiler.parameter(this, "anisotropic");
compiler.parameter(this, "periodic");
compiler.parameter(this, "use_normalize");

View File

@ -244,7 +244,7 @@ class GaborTextureNode : public TextureNode {
void constant_fold(const ConstantFolder &folder);
NODE_SOCKET_API(int, dimensions)
NODE_SOCKET_API(NodeGaborKernel, kernel_shape);
NODE_SOCKET_API(NodeGaborMode, mode);
NODE_SOCKET_API(NodeGaborAnisotropic, anisotropic);
NODE_SOCKET_API(bool, periodic)
NODE_SOCKET_API(bool, use_normalize)

View File

@ -45,6 +45,13 @@
# define M_EPI 0.0432139182637722
CharlieJolly marked this conversation as resolved Outdated

What is M_EPI?

What is `M_EPI`?

Added comment to define: e^(-PI)

Added comment to define: e^(-PI)
#endif
#define SHD_GABOR_MODE_GABOR 0
#define SHD_GABOR_MODE_RING 1
#define SHD_GABOR_MODE_CROSS 2
#define SHD_GABOR_MODE_SQUARE 3
#define SHD_GABOR_MODE_PHASOR 4
#define SHD_GABOR_MODE_PHASOR_CROSS 5
struct GaborParams {
float base_frequency;
float octaves;
@ -60,7 +67,7 @@ struct GaborParams {
float cell_randomness;
float rotation;
float rot_variance;
int kernel_shape;
int mode;
int anisotropic;
vec3 direction;
};
@ -84,21 +91,25 @@ vec3 gabor_kernel(GaborParams gp, float freq, vec3 omega, float phi, vec3 positi
{
float h;
if (gp.kernel_shape == 4) { /* SHD_GABOR_KERNEL_PHASOR */
if (gp.mode == SHD_GABOR_MODE_PHASOR) {
float phase = freq * dot(omega, position) + phi;
CharlieJolly marked this conversation as resolved Outdated

Can we find a way to incorporate all three options into a single factor input that controls the amount of anisotropy?

Can we find a way to incorporate all three options into a single factor input that controls the amount of anisotropy?

This has been slightly refactored but combining to a single factor is not feasible for Gabor noise.

This has been slightly refactored but combining to a single factor is not feasible for Gabor noise.

Latest version now combines all three modes/options into one.
There is now an Anisotropy Factor to mix between Isotropic/Manual direction and Anisotropic/Fixed Direction.

Latest version now combines all three modes/options into one. There is now an Anisotropy Factor to mix between Isotropic/Manual direction and Anisotropic/Fixed Direction.
return g * vec3(cos(phase), sin(phase), 0.0);
}
else if (gp.kernel_shape == 3) { /* SHD_GABOR_KERNEL_SQUARE */
else if (gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float phase = freq * length(position * omega) + phi;
return g * vec3(cos(phase), sin(phase), 0.0);
}
else if (gp.mode == SHD_GABOR_MODE_SQUARE) {
h = (cos(freq * dot(omega, position) + phi) + cos(freq * dot(omega, position.yxz) + phi)) *
0.5;
}
else if (gp.kernel_shape == 2) { /* SHD_GABOR_KERNEL_CROSS */
else if (gp.mode == SHD_GABOR_MODE_CROSS) {
h = cos(freq * length(position * omega) + phi);
}
else if (gp.kernel_shape == 1) { /* SHD_GABOR_KERNEL_RING */
else if (gp.mode == SHD_GABOR_MODE_RING) {
h = cos(freq * dot(position, omega) + phi) - cos(freq * length(position) + phi);
}
else { // SHD_GABOR_KERNEL_GABOR
else { // SHD_GABOR_MODE_GABOR
h = cos(freq * dot(omega, position) + phi);
CharlieJolly marked this conversation as resolved Outdated

Why are we computing the fractcal on the freqiency as opposed to the scale to make it consistent with other noise functions? Is there a good reason for that?

Why are we computing the fractcal on the freqiency as opposed to the scale to make it consistent with other noise functions? Is there a good reason for that?

This was implemented per impulse/splat rather than per texture pass. This was mentioned to me by @Hoshinova so I have this marked as a todo. The results are quite different.

This was implemented per impulse/splat rather than per texture pass. This was mentioned to me by @Hoshinova so I have this marked as a todo. The results are quite different.

Implemented fractal based on other noise functions.

Implemented fractal based on other noise functions.
}
@ -233,7 +244,7 @@ float gabor_grid_3d(GaborParams gp, vec3 p, float scale, int seed, int periodic)
}
}
if (gp.kernel_shape == 4) { /* SHD_GABOR_KERNEL_PHASOR */
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float pn = atan(sum.y, sum.x) / M_PI;
return pn;
}
@ -266,7 +277,7 @@ float gabor_grid_2d(GaborParams gp, vec3 p, float scale, int seed, int periodic)
}
}
if (gp.kernel_shape == 4) { /* SHD_GABOR_KERNEL_PHASOR */
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
float pn = atan(sum.y, sum.x) / M_PI;
return pn;
}
@ -291,7 +302,7 @@ GaborParams gabor_parameters(vec3 direction,
float cell_randomness,
float rotation,
float rot_variance,
int kernel_shape,
int mode,
int anisotropic)
{
GaborParams gp;
@ -303,7 +314,7 @@ GaborParams gabor_parameters(vec3 direction,
gp.fre_lacunarity = fre_lacunarity;
gp.rot_lacunarity = rot_lacunarity;
gp.anisotropic = anisotropic;
gp.kernel_shape = kernel_shape;
gp.mode = mode;
gp.direction = direction;
gp.phase = phase;
gp.rotation = rotation;
@ -372,7 +383,7 @@ void node_tex_gabor(vec3 co,
float rot_variance,
vec3 direction,
float dimensions,
float kernel_shape,
float mode,
float anisotropic,
float use_normalize,
float periodic,
@ -401,7 +412,7 @@ void node_tex_gabor(vec3 co,
cell_randomness,
rotation,
rot_variance,
int(kernel_shape),
int(mode),
int(anisotropic));
/* Normalise height of noise by the number of impulses. This is empircal as there is no easy way

View File

@ -1223,7 +1223,7 @@ typedef struct NodeTexNoise {
typedef struct NodeTexGabor {
NodeTexBase base;
char kernel;
char mode;
char anisotropic;
char periodic;
char normalize;
@ -1991,17 +1991,18 @@ enum {
SHD_VORONOI_N_SPHERE_RADIUS = 4,
};
typedef enum NodeGaborKernel {
SHD_GABOR_KERNEL_GABOR,
SHD_GABOR_KERNEL_RING,
SHD_GABOR_KERNEL_CROSS,
SHD_GABOR_KERNEL_SQUARE,
SHD_GABOR_KERNEL_PHASOR,
} NodeGaborKernel;
typedef enum NodeGaborMode {
SHD_GABOR_MODE_GABOR,
SHD_GABOR_MODE_RING,
SHD_GABOR_MODE_CROSS,
SHD_GABOR_MODE_SQUARE,
SHD_GABOR_MODE_PHASOR,
SHD_GABOR_MODE_PHASOR_CROSS,
} NodeGaborMode;
typedef enum NodeGaborAnisotropic {
SHD_GABOR_MODE_ISOTROPIC,
SHD_GABOR_MODE_ANISOTROPIC,
SHD_GABOR_ISOTROPIC,
SHD_GABOR_ANISOTROPIC,
} NodeGaborAnisotropic;
/* musgrave texture */

View File

@ -5283,18 +5283,19 @@ static void def_sh_tex_musgrave(StructRNA *srna)
static void def_sh_tex_gabor(StructRNA *srna)
{
static const EnumPropertyItem prop_gabor_kernel[] = {
{SHD_GABOR_KERNEL_GABOR, "GABOR", 0, "Gabor", "Gabor pattern"},
{SHD_GABOR_KERNEL_RING, "RING", 0, "Ring", "Ring kernel pattern"},
{SHD_GABOR_KERNEL_CROSS, "CROSS", 0, "Cross", "Cross kernel pattern"},
{SHD_GABOR_KERNEL_SQUARE, "SQUARE", 0, "Square", "Square kernel pattern"},
{SHD_GABOR_KERNEL_PHASOR, "PHASOR", 0, "Phasor", "Phasor kernel pattern"},
static const EnumPropertyItem prop_gabor_mode[] = {
{SHD_GABOR_MODE_GABOR, "GABOR", 0, "Gabor", "Gabor default kernel"},
{SHD_GABOR_MODE_RING, "RING", 0, "Ring", "Gabor ring kernel"},
{SHD_GABOR_MODE_CROSS, "CROSS", 0, "Cross", "Gabor cross kernel"},
{SHD_GABOR_MODE_SQUARE, "SQUARE", 0, "Square", "Gabor square kernel"},
{SHD_GABOR_MODE_PHASOR, "PHASOR", 0, "Phasor", "Phasor default kernel"},
{SHD_GABOR_MODE_PHASOR_CROSS, "PHASOR_CROSS", 0, "Phasor Cross", "Phasor cross kernel"},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem prop_gabor_mode[] = {
{SHD_GABOR_MODE_ISOTROPIC, "ISOTROPIC", 0, "Isotropic", "Isotropic noise"},
{SHD_GABOR_MODE_ANISOTROPIC, "ANISOTROPIC", 0, "Anisotropic", "Anisotropic noise"},
static const EnumPropertyItem prop_gabor_aniso[] = {
{SHD_GABOR_ISOTROPIC, "ISOTROPIC", 0, "Isotropic", "Isotropic noise"},
{SHD_GABOR_ANISOTROPIC, "ANISOTROPIC", 0, "Anisotropic", "Anisotropic noise"},
{0, nullptr, 0, nullptr, nullptr},
};
@ -5314,16 +5315,16 @@ static void def_sh_tex_gabor(StructRNA *srna)
RNA_def_property_ui_text(prop, "Dimensions", "Number of dimensions to output noise for");
RNA_def_property_update(prop, 0, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "kernel", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "kernel");
RNA_def_property_enum_items(prop, prop_gabor_kernel);
RNA_def_property_ui_text(prop, "Kernel", "Kernel pattern");
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, prop_gabor_mode);
RNA_def_property_ui_text(prop, "Mode", "Mode");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "anisotropic", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "anisotropic");
RNA_def_property_enum_items(prop, prop_gabor_mode);
RNA_def_property_ui_text(prop, "Mode", "Mode");
RNA_def_property_enum_items(prop, prop_gabor_aniso);
RNA_def_property_ui_text(prop, "Anisotropic", "Anisotropic");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "periodic", PROP_BOOLEAN, PROP_NONE);

View File

@ -120,7 +120,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
uiItemR(split, ptr, "anisotropic", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
col = uiLayoutColumn(layout, true);
uiItemR(col, ptr, "kernel", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
uiItemR(col, ptr, "mode", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
uiItemR(col, ptr, "periodic", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
uiItemR(col, ptr, "normalize", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
}
@ -131,8 +131,8 @@ static void node_init(bNodeTree * /*ntree*/, bNode *node)
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
tex->kernel = SHD_GABOR_KERNEL_GABOR;
tex->anisotropic = SHD_GABOR_MODE_ISOTROPIC;
tex->mode = SHD_GABOR_MODE_GABOR;
tex->anisotropic = SHD_GABOR_ISOTROPIC;
tex->periodic = 0;
tex->normalize = 1;
tex->dimensions = 2;
@ -150,7 +150,7 @@ static int node_shader_gpu_tex_gabor(GPUMaterial *mat,
const NodeTexGabor &storage = node_storage(*node);
const float dimensions = storage.dimensions;
const float kernel = storage.kernel;
const float mode = storage.mode;
const float anisotropic = storage.anisotropic;
const float periodic = storage.periodic;
const float use_normalize = storage.normalize;
@ -161,7 +161,7 @@ static int node_shader_gpu_tex_gabor(GPUMaterial *mat,
in,
out,
GPU_constant(&dimensions),
GPU_constant(&kernel),
GPU_constant(&mode),
GPU_constant(&anisotropic),
GPU_constant(&use_normalize),
GPU_constant(&periodic));
@ -177,13 +177,13 @@ static void node_update(bNodeTree *ntree, bNode *node)
const NodeTexGabor &storage = node_storage(*node);
bke::nodeSetSocketAvailability(
ntree, inDirectionSock, (storage.anisotropic != SHD_GABOR_MODE_ISOTROPIC));
ntree, inDirectionSock, (storage.anisotropic != SHD_GABOR_ISOTROPIC));
bke::nodeSetSocketAvailability(
ntree, inRotationSock, (storage.anisotropic != SHD_GABOR_MODE_ANISOTROPIC));
ntree, inRotationSock, (storage.anisotropic != SHD_GABOR_ANISOTROPIC));
bke::nodeSetSocketAvailability(
ntree, inVarianceSock, (storage.anisotropic != SHD_GABOR_MODE_ANISOTROPIC));
ntree, inVarianceSock, (storage.anisotropic != SHD_GABOR_ANISOTROPIC));
bke::nodeSetSocketAvailability(
ntree, inRotationLacunaritySock, (storage.anisotropic != SHD_GABOR_MODE_ANISOTROPIC));
ntree, inRotationLacunaritySock, (storage.anisotropic != SHD_GABOR_ANISOTROPIC));
}
#ifndef M_EPI_F
@ -205,7 +205,7 @@ typedef struct GaborParams {
float cell_randomness;
float rotation;
float rot_variance;
int kernel_shape;
int mode;
int anisotropic;
float3 direction;
} GaborParams;
@ -230,24 +230,28 @@ static float3 gabor_kernel(const GaborParams gp,
{
float h;
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR) {
const float phase = freq * math::dot(omega, position) + phi;
return float3(math::cos(phase), math::sin(phase), 0.0f) * g;
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_SQUARE) {
else if (gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
const float phase = freq * math::length(position * omega) + phi;
return float3(math::cos(phase), math::sin(phase), 0.0f) * g;
}
else if (gp.mode == SHD_GABOR_MODE_SQUARE) {
const float3 positionyx = float3(position.y, position.x, position.z);
h = (math::cos(freq * math::dot(omega, position) + phi) +
math::cos(freq * math::dot(omega, positionyx) + phi)) *
0.5f;
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_CROSS) {
else if (gp.mode == SHD_GABOR_MODE_CROSS) {
h = math::cos(freq * math::length(position * omega) + phi);
}
else if (gp.kernel_shape == SHD_GABOR_KERNEL_RING) {
else if (gp.mode == SHD_GABOR_MODE_RING) {
h = math::cos(freq * math::dot(position, omega) + phi) -
math::cos(freq * math::length(position) + phi);
}
else { // SHD_GABOR_KERNEL_GABOR
else { // SHD_GABOR_MODE_GABOR
h = math::cos(freq * math::dot(omega, position) + phi);
}
@ -264,7 +268,7 @@ static void gabor_sample(const GaborParams gp,
const float pvar = math::interpolate(0.0f, prand * 2.0f - 1.0f, gp.phase_variance);
phi = 2.0f * float(M_PI) * pvar + gp.phase;
if (gp.anisotropic == SHD_GABOR_MODE_ANISOTROPIC) { /* ANISO */
if (gp.anisotropic == SHD_GABOR_ANISOTROPIC) { /* ANISO */
omega = gp.direction;
}
else { /* ISO */
@ -383,7 +387,7 @@ static float gabor_grid_3d(
}
}
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
const float pn = math::atan2(sum.y, sum.x) / float(M_PI);
return pn;
}
@ -423,7 +427,7 @@ static float gabor_grid_2d(
}
}
if (gp.kernel_shape == SHD_GABOR_KERNEL_PHASOR) {
if (gp.mode == SHD_GABOR_MODE_PHASOR || gp.mode == SHD_GABOR_MODE_PHASOR_CROSS) {
const float pn = math::atan2(sum.y, sum.x) / float(M_PI);
return pn;
}
@ -483,7 +487,7 @@ static GaborParams gabor_parameters(float3 direction,
float cell_randomness,
float rotation,
float rot_variance,
int kernel_shape,
int mode,
int anisotropic)
{
GaborParams gp;
@ -495,7 +499,7 @@ static GaborParams gabor_parameters(float3 direction,
gp.fre_lacunarity = fre_lacunarity;
gp.rot_lacunarity = rot_lacunarity;
gp.anisotropic = anisotropic;
gp.kernel_shape = kernel_shape;
gp.mode = mode;
gp.direction = direction;
gp.phase = phase;
gp.rotation = rotation;
@ -573,7 +577,7 @@ static mf::Signature gabor_signature(const char *name, const int anistropic)
builder.single_input<float>("Roughness");
builder.single_input<float>("Scale Lacunarity");
builder.single_input<float>("Frequency Lacunarity");
if (anistropic == SHD_GABOR_MODE_ISOTROPIC) {
if (anistropic == SHD_GABOR_ISOTROPIC) {
builder.single_input<float>("Rotation Lacunarity");
}
builder.single_input<float>("Bandwidth");
@ -582,11 +586,11 @@ static mf::Signature gabor_signature(const char *name, const int anistropic)
builder.single_input<float>("Phase");
builder.single_input<float>("Phase Variance");
builder.single_input<float>("Cell Randomness");
if (anistropic == SHD_GABOR_MODE_ISOTROPIC) {
if (anistropic == SHD_GABOR_ISOTROPIC) {
builder.single_input<float>("Rotation");
builder.single_input<float>("Rotation Variance");
}
if (anistropic == SHD_GABOR_MODE_ANISOTROPIC) {
if (anistropic == SHD_GABOR_ANISOTROPIC) {
builder.single_input<float3>("Direction");
}
builder.single_output<float>("Value");
@ -596,15 +600,15 @@ static mf::Signature gabor_signature(const char *name, const int anistropic)
class GaborNoiseFunction : public mf::MultiFunction {
private:
int dimensions_;
int kernel_shape_;
int mode_;
int periodic_;
int normalize_;
public:
GaborNoiseFunction(int dimensions, int kernel, int periodic, int normalize)
: dimensions_(dimensions), kernel_shape_(kernel), periodic_(periodic), normalize_(normalize)
: dimensions_(dimensions), mode_(kernel), periodic_(periodic), normalize_(normalize)
{
static mf::Signature signature = gabor_signature("GaborNoise", SHD_GABOR_MODE_ISOTROPIC);
static mf::Signature signature = gabor_signature("GaborNoise", SHD_GABOR_ISOTROPIC);
this->set_signature(&signature);
}
@ -657,8 +661,8 @@ class GaborNoiseFunction : public mf::MultiFunction {
rotation[i],
rot_variance[i],
dimensions_,
kernel_shape_,
SHD_GABOR_MODE_ISOTROPIC,
mode_,
SHD_GABOR_ISOTROPIC,
normalize_,
periodic_);
});
@ -676,19 +680,16 @@ class GaborNoiseFunction : public mf::MultiFunction {
class AnisotropicGaborNoiseFunction : public mf::MultiFunction {
private:
int dimensions_;
int kernel_shape_;
int mode_;
int periodic_;
int normalize_;
public:
AnisotropicGaborNoiseFunction(int dimensions, int kernel_shape, int periodic, int normalize)
: dimensions_(dimensions),
kernel_shape_(kernel_shape),
periodic_(periodic),
normalize_(normalize)
AnisotropicGaborNoiseFunction(int dimensions, int mode, int periodic, int normalize)
: dimensions_(dimensions), mode_(mode), periodic_(periodic), normalize_(normalize)
{
static mf::Signature signature = gabor_signature("AnistropicGaborNoise",
SHD_GABOR_MODE_ANISOTROPIC);
SHD_GABOR_ANISOTROPIC);
this->set_signature(&signature);
}
@ -736,8 +737,8 @@ class AnisotropicGaborNoiseFunction : public mf::MultiFunction {
0.0f,
0.0f,
dimensions_,
kernel_shape_,
SHD_GABOR_MODE_ANISOTROPIC,
mode_,
SHD_GABOR_ANISOTROPIC,
normalize_,
periodic_);
});
@ -756,13 +757,13 @@ static void build_multi_function(NodeMultiFunctionBuilder &builder)
{
const NodeTexGabor &storage = node_storage(builder.node());
switch (storage.anisotropic) {
case SHD_GABOR_MODE_ISOTROPIC:
case SHD_GABOR_ISOTROPIC:
builder.construct_and_set_matching_fn<GaborNoiseFunction>(
storage.dimensions, storage.kernel, storage.periodic, storage.normalize);
storage.dimensions, storage.mode, storage.periodic, storage.normalize);
break;
case SHD_GABOR_MODE_ANISOTROPIC:
case SHD_GABOR_ANISOTROPIC:
builder.construct_and_set_matching_fn<AnisotropicGaborNoiseFunction>(
storage.dimensions, storage.kernel, storage.periodic, storage.normalize);
storage.dimensions, storage.mode, storage.periodic, storage.normalize);
break;
}
}