GOOENGINE: Water Ripples Node
Patches originally written by Joseph and Thorn. Thank you! Adds a water ripple node
This commit is contained in:
@@ -349,6 +349,7 @@ class NODE_MT_category_goo_engine(Menu):
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSdfVectorOp")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeSdfNoise")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeTwirl")
|
||||
node_add_menu.add_node_type(layout, "ShaderNodeWaterRipples")
|
||||
|
||||
|
||||
class NODE_MT_category_shader_script(Menu):
|
||||
|
||||
@@ -1013,6 +1013,7 @@ void node_tree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index);
|
||||
#define SH_NODE_LIGHT_INFO 901
|
||||
#define SH_NODE_TEX_HEXAGON 902
|
||||
#define SH_NODE_TWIRL 903
|
||||
#define SH_NODE_WATER_RIPPLES 904
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
@@ -630,6 +630,7 @@ set(GLSL_SRC
|
||||
shaders/material/gpu_shader_material_tex_voronoi.glsl
|
||||
shaders/material/gpu_shader_material_tex_hexagon.glsl
|
||||
shaders/material/gpu_shader_material_twirl.glsl
|
||||
shaders/material/gpu_shader_material_water_ripples.glsl
|
||||
shaders/material/gpu_shader_material_tex_wave.glsl
|
||||
shaders/material/gpu_shader_material_tex_white_noise.glsl
|
||||
shaders/material/gpu_shader_material_toon.glsl
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_material_common.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_common_math_constants.glsl)
|
||||
|
||||
/* Utility functions */
|
||||
float bias_function(float x, float b)
|
||||
{
|
||||
float min_b = 1.0 / 100.0;
|
||||
float max_b = 99.0 / 100.0;
|
||||
float safe_b = clamp(b, min_b, max_b);
|
||||
return x / ((1.0/safe_b - 2.0) * (1.0 - x) + 1.0);
|
||||
}
|
||||
|
||||
/* Hash functions for procedural generation */
|
||||
float hash12(vec2 p, float hash_scale)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * hash_scale);
|
||||
vec3 add_val = p3.yzx + 19.19;
|
||||
p3 += dot(p3, add_val);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
vec2 hash22(vec2 p, vec3 hash_scale)
|
||||
{
|
||||
vec3 p3 = fract(vec3(p.xyx) * hash_scale);
|
||||
vec3 add_val = p3.yzx + 19.19;
|
||||
p3 += dot(p3, add_val);
|
||||
return fract((p3.xx + p3.yz) * p3.zy);
|
||||
}
|
||||
|
||||
void node_water_ripples(
|
||||
vec3 vector,
|
||||
float time,
|
||||
float mode,
|
||||
float scale,
|
||||
float intensity,
|
||||
float speed,
|
||||
float detail,
|
||||
float bias_amount,
|
||||
out vec3 distorted_vector,
|
||||
out float mask
|
||||
)
|
||||
{
|
||||
vec2 uv = vector.xy * max(scale, 1.0/1000.0);
|
||||
float h = 0.0;
|
||||
int imode = int(mode + 0.5);
|
||||
|
||||
if (imode == 0) {
|
||||
/* DROPS MODE */
|
||||
int divisions = int(detail * 8.0 + 2.0);
|
||||
divisions = clamp(divisions, 2, 8);
|
||||
for (int iy = 0; iy < 8; iy++) {
|
||||
if (iy >= divisions) break;
|
||||
for (int ix = 0; ix < 16; ix++) {
|
||||
if (ix >= divisions * 2) break;
|
||||
/* Generate pseudo-random variations */
|
||||
vec2 noise_coord = vec2(float(ix), float(iy)) / float(divisions);
|
||||
float hash_scale = 1031.0 / 10000.0;
|
||||
vec4 t = vec4(
|
||||
hash12(noise_coord, hash_scale),
|
||||
hash12(noise_coord + vec2(1.0/10.0, 0.0), hash_scale),
|
||||
hash12(noise_coord + vec2(0.0, 1.0/10.0), hash_scale),
|
||||
hash12(noise_coord + vec2(1.0/10.0, 1.0/10.0), hash_scale)
|
||||
);
|
||||
|
||||
/* Droplet positions */
|
||||
float div_minus_one = float(divisions - 1);
|
||||
div_minus_one = max(div_minus_one, 1.0);
|
||||
vec2 p = vec2(float(ix), float(iy)) * (1.0 / div_minus_one);
|
||||
float pos_offset = 75.0 / 100.0;
|
||||
p += (pos_offset / div_minus_one) * (t.xy * 2.0 - 1.0);
|
||||
|
||||
/* Distance calculation */
|
||||
vec2 v = uv - p;
|
||||
float min_dot = 1.0 / 1000.0;
|
||||
float d = pow(max(dot(v, v), min_dot), 7.0/10.0);
|
||||
|
||||
/* Animation */
|
||||
float anim_mult = 2.0 / 10.0;
|
||||
float n = time * speed * 5.0 * (t.w + anim_mult) - t.z * 6.0;
|
||||
float n_mult = 1.0 / 10.0;
|
||||
n *= n_mult + t.w;
|
||||
n = mod(n, 10.0 + t.z * 3.0 + 10.0);
|
||||
float min_n = 1.0 / 1000.0;
|
||||
n = max(n, min_n);
|
||||
|
||||
float x = d * 99.0;
|
||||
float two_pi_n = 2.0 * M_PI * n;
|
||||
float T = (x < two_pi_n) ? 1.0 : 0.0;
|
||||
float e = max(1.0 - (n / 10.0), 0.0);
|
||||
float min_denom = 1.0 / 1000.0;
|
||||
float F = e * x / max(two_pi_n, min_denom);
|
||||
float pi_half = M_PI * 5.0 / 10.0;
|
||||
float s = sin(x - two_pi_n - pi_half);
|
||||
s = s * 5.0/10.0 + 5.0/10.0;
|
||||
s = bias_function(s, bias_amount);
|
||||
float denom_offset = 11.0 / 10.0;
|
||||
s = (F * s) / (x + denom_offset) * T;
|
||||
float h_mult = 5.0 / 10.0;
|
||||
h += s * 100.0 * (h_mult + t.w) * intensity;
|
||||
}
|
||||
}
|
||||
|
||||
/* For drops mode, create distorted vector from height field */
|
||||
vec2 gradient = vec2(0.0);
|
||||
float eps = 1.0 / 1000.0;
|
||||
|
||||
/* Calculate gradient by sampling nearby points */
|
||||
float h_x = 0.0;
|
||||
float h_y = 0.0;
|
||||
|
||||
/* Sample x gradient */
|
||||
vec2 uv_x = (vector.xy + vec2(eps, 0.0)) * max(scale, 1.0/1000.0);
|
||||
/* Simplified height calculation for gradient */
|
||||
for (int iy = 0; iy < divisions; iy++) {
|
||||
for (int ix = 0; ix < divisions * 2; ix++) {
|
||||
if (ix >= divisions * 2) break;
|
||||
vec2 noise_coord = vec2(float(ix), float(iy)) / float(divisions);
|
||||
float hash_scale = 1031.0 / 10000.0;
|
||||
vec4 t = vec4(
|
||||
hash12(noise_coord, hash_scale),
|
||||
hash12(noise_coord + vec2(1.0/10.0, 0.0), hash_scale),
|
||||
hash12(noise_coord + vec2(0.0, 1.0/10.0), hash_scale),
|
||||
hash12(noise_coord + vec2(1.0/10.0, 1.0/10.0), hash_scale)
|
||||
);
|
||||
|
||||
float div_minus_one = max(float(divisions - 1), 1.0);
|
||||
vec2 p = vec2(float(ix), float(iy)) * (1.0 / div_minus_one);
|
||||
p += (75.0 / 100.0 / div_minus_one) * (t.xy * 2.0 - 1.0);
|
||||
|
||||
vec2 v_x = uv_x - p;
|
||||
float d_x = pow(max(dot(v_x, v_x), 1.0/1000.0), 7.0/10.0);
|
||||
|
||||
float n = time * speed * 5.0 * (t.w + 2.0/10.0) - t.z * 6.0;
|
||||
n *= 1.0/10.0 + t.w;
|
||||
n = mod(n, 10.0 + t.z * 3.0 + 10.0);
|
||||
n = max(n, 1.0/1000.0);
|
||||
|
||||
float x = d_x * 99.0;
|
||||
float two_pi_n = 2.0 * M_PI * n;
|
||||
float T = (x < two_pi_n) ? 1.0 : 0.0;
|
||||
float e = max(1.0 - (n / 10.0), 0.0);
|
||||
float F = e * x / max(two_pi_n, 1.0/1000.0);
|
||||
float s = sin(x - two_pi_n - M_PI * 5.0/10.0);
|
||||
s = s * 5.0/10.0 + 5.0/10.0;
|
||||
s = bias_function(s, bias_amount);
|
||||
s = (F * s) / (x + 11.0/10.0) * T;
|
||||
h_x += s * 100.0 * (5.0/10.0 + t.w) * intensity;
|
||||
}
|
||||
}
|
||||
|
||||
gradient.x = (h_x - h) / eps;
|
||||
distorted_vector = vector + vec3(gradient * intensity * 0.01, 0.0);
|
||||
mask = clamp(h * 1.0/100.0, 0.0, 1.0);
|
||||
|
||||
} else if (imode == 1) {
|
||||
/* RIPPLES MODE */
|
||||
int max_radius = int(detail * 3.0 + 1.0);
|
||||
max_radius = clamp(max_radius, 1, 3);
|
||||
vec2 p0 = floor(uv);
|
||||
vec2 circles = vec2(0.0);
|
||||
for (int j = -3; j <= 3; j++) {
|
||||
if (abs(j) > max_radius) continue;
|
||||
for (int i = -3; i <= 3; i++) {
|
||||
if (abs(i) > max_radius) continue;
|
||||
vec2 pi = p0 + vec2(float(i), float(j));
|
||||
float hash_scale1 = 1031.0 / 10000.0;
|
||||
float hash_scale2 = 1030.0 / 10000.0;
|
||||
float hash_scale3 = 973.0 / 10000.0;
|
||||
vec2 p = pi + hash22(pi, vec3(hash_scale1, hash_scale2, hash_scale3));
|
||||
float t = fract(speed * time + hash12(pi, hash_scale1));
|
||||
vec2 v = p - uv;
|
||||
float d = length(v) - (float(max_radius) + 1.0) * t;
|
||||
float h_val = 1.0 / 1000.0;
|
||||
float d1 = d - h_val;
|
||||
float d2 = d + h_val;
|
||||
float smooth1 = -6.0 / 10.0;
|
||||
float smooth2 = -3.0 / 10.0;
|
||||
float p1 = sin(31.0 * d1) *
|
||||
smoothstep(smooth1, smooth2, d1) *
|
||||
smoothstep(0.0, smooth2, d1);
|
||||
float p2 = sin(31.0 * d2) *
|
||||
smoothstep(smooth1, smooth2, d2) *
|
||||
smoothstep(0.0, smooth2, d2);
|
||||
float ripple_fade = (1.0 - t) * (1.0 - t);
|
||||
/* Safe vector normalization */
|
||||
vec2 norm_v = vec2(0.0, 1.0);
|
||||
float v_length = length(v);
|
||||
float min_len = 1.0 / 1000.0;
|
||||
if (v_length > min_len) {
|
||||
norm_v = v / v_length;
|
||||
}
|
||||
circles += norm_v * ((p2 - p1) / (2.0 * h_val) * ripple_fade);
|
||||
}
|
||||
}
|
||||
circles *= intensity;
|
||||
h = length(circles);
|
||||
/* Output distorted vector from ripple displacement */
|
||||
distorted_vector = vector + vec3(circles * intensity * 0.1, 0.0);
|
||||
mask = h;
|
||||
|
||||
} else if (imode == 2) {
|
||||
/* FLOW MODE - new flowing water effect */
|
||||
vec2 flow_uv = uv;
|
||||
float time_scaled = time * speed;
|
||||
|
||||
// Create flowing wave pattern
|
||||
float wave1 = sin(flow_uv.x * detail * 10.0 + time_scaled * 2.0) * 0.1;
|
||||
float wave2 = cos(flow_uv.y * detail * 8.0 + time_scaled * 1.5) * 0.15;
|
||||
|
||||
// Combine waves for flowing effect
|
||||
vec2 flow_offset = vec2(
|
||||
wave1 + sin(flow_uv.y * detail * 5.0 + time_scaled) * 0.05,
|
||||
wave2 + cos(flow_uv.x * detail * 6.0 + time_scaled * 0.8) * 0.08
|
||||
);
|
||||
|
||||
// Apply intensity scaling
|
||||
flow_offset *= intensity * 0.1;
|
||||
|
||||
distorted_vector = vector + vec3(flow_offset, 0.0);
|
||||
mask = clamp(length(flow_offset) * 10.0, 0.0, 1.0);
|
||||
|
||||
} else if (imode == 3) {
|
||||
/* CAUSTIC MODE (fixed for Blender GLSL) */
|
||||
vec2 p = uv * scale;
|
||||
float a = 1.0;
|
||||
float scale_safe = max(bias_amount, 1e-3);
|
||||
vec3 k = vec3(p.x / scale_safe * detail, p.y / scale_safe * detail, sin(time * 0.2));
|
||||
mat3 m = mat3(-2,-1,2, 3,-2,1, 1,2,2) * 0.3;
|
||||
// Repeat 3 times as in original logic
|
||||
k = m * k;
|
||||
a = min(a, length(0.5 - fract(k)));
|
||||
k = m * k;
|
||||
a = min(a, length(0.5 - fract(k)));
|
||||
k = m * k;
|
||||
a = min(a, length(0.5 - fract(k)));
|
||||
float caustic = pow(a, detail) * 25.0 * intensity;
|
||||
distorted_vector = vector;
|
||||
mask = clamp(caustic, 0.0, 1.0);
|
||||
} else {
|
||||
/* TEXTURE DISTORTION MODE */
|
||||
vec2 base_uv = uv;
|
||||
/* Generate noise texture using hash functions */
|
||||
float hash_scale = 1031.0 / 10000.0;
|
||||
vec2 noise_uv = uv * scale;
|
||||
vec2 t = vec2(
|
||||
hash12(noise_uv, hash_scale),
|
||||
hash12(noise_uv + vec2(0.1, 0.1), hash_scale)
|
||||
);
|
||||
/* Apply distortion based on detail parameter */
|
||||
if (detail > 0.5) {
|
||||
/* High detail mode - smooth flowing distortion */
|
||||
base_uv.xy += ((t.xy - 0.5) * intensity * 0.04);
|
||||
base_uv.y += time * speed * 0.08 + intensity * 0.01 * sin(time * speed * 0.4);
|
||||
} else {
|
||||
/* Low detail mode - more chaotic distortion */
|
||||
float noise = (t.x / max(t.y, 0.001)) +
|
||||
time * speed * (-0.025) +
|
||||
intensity * 0.01 * sin(time * speed);
|
||||
base_uv += vec2(noise * intensity * 0.4);
|
||||
}
|
||||
/* Calculate distortion vector */
|
||||
vec2 distortion = base_uv - uv;
|
||||
float distortion_magnitude = length(distortion);
|
||||
/* Output distorted vector */
|
||||
distorted_vector = vec3(base_uv, vector.z);
|
||||
/* Output distortion magnitude as mask */
|
||||
mask = clamp(distortion_magnitude * intensity * 10.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
@@ -1545,6 +1545,26 @@ typedef struct NodeTwirl {
|
||||
char _pad[4];
|
||||
} NodeTwirl;
|
||||
|
||||
typedef struct NodeWaterRipples {
|
||||
NodeTexBase base;
|
||||
float vector[3];
|
||||
float time;
|
||||
/** See eNodeWaterRipplesMode. */
|
||||
int mode;
|
||||
float scale;
|
||||
float intensity;
|
||||
float speed;
|
||||
float detail;
|
||||
float bias;
|
||||
} NodeWaterRipples;
|
||||
|
||||
typedef enum eNodeWaterRipplesMode {
|
||||
NODE_WATER_RIPPLES_DROPS = 0,
|
||||
NODE_WATER_RIPPLES_RIPPLES = 1,
|
||||
NODE_WATER_RIPPLES_FLOW = 2,
|
||||
NODE_WATER_RIPPLES_CAUSTIC = 3
|
||||
} eNodeWaterRipplesMode;
|
||||
|
||||
typedef struct NodeSunBeams {
|
||||
float source[2];
|
||||
|
||||
|
||||
@@ -428,6 +428,14 @@ const EnumPropertyItem rna_enum_node_sdf_op_items[] = {
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem rna_enum_node_water_ripples_mode_items[] = {
|
||||
{NODE_WATER_RIPPLES_DROPS, "DROPS", 0, "Drops", "Water droplets"},
|
||||
{NODE_WATER_RIPPLES_RIPPLES, "RIPPLES", 0, "Ripples", "Continuous ripples"},
|
||||
{NODE_WATER_RIPPLES_FLOW, "FLOW", 0, "Flow", "Flowing water"},
|
||||
{NODE_WATER_RIPPLES_CAUSTIC, "CAUSTIC", 0, "Caustic", "Caustic effect"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_node_sdf_vector_op_items[] = {
|
||||
{0, "", 0, N_("Vector Grid Ops"), ""},
|
||||
{SHD_SDF_VEC_OP_REFLECT,
|
||||
@@ -5784,6 +5792,19 @@ static void def_sh_twirl(StructRNA *srna)
|
||||
def_sh_tex(srna);
|
||||
}
|
||||
|
||||
static void def_sh_water_ripples(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
RNA_def_struct_sdna_from(srna, "NodeWaterRipples", "storage");
|
||||
def_sh_tex(srna);
|
||||
|
||||
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "mode");
|
||||
RNA_def_property_enum_items(prop, rna_enum_node_water_ripples_mode_items);
|
||||
RNA_def_property_ui_text(prop, "Mode", "Water ripples mode: Drops or Ripples");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
|
||||
}
|
||||
|
||||
static void def_sh_tex_hexagon(StructRNA *srna)
|
||||
{
|
||||
static const EnumPropertyItem prop_hexagon_coords_items[] = {
|
||||
|
||||
@@ -132,6 +132,7 @@ DefNode(ShaderNode, SH_NODE_MIX, def_sh_mix, "MIX
|
||||
DefNode(ShaderNode, SH_NODE_SHADER_INFO, def_sh_shader_info, "SHADERINFO", ShaderInfo, "Shader Info", "Separate internal lighting into multiple outputs, and allow for per-node light-groups.")
|
||||
DefNode(ShaderNode, SH_NODE_TEX_HEXAGON, def_sh_tex_hexagon, "TEX_HEXAGON", TexHexagon, "Hex Grid Texture", "" )
|
||||
DefNode(ShaderNode, SH_NODE_TWIRL, def_sh_twirl, "TWIRL", Twirl, "Twirl", "Twirl the input vector around a center point by a specified amount")
|
||||
DefNode(ShaderNode, SH_NODE_WATER_RIPPLES, def_sh_water_ripples, "WATER_RIPPLES", WaterRipples, "Water Ripples", "Generate concentric ripples simulating water surface disturbances")
|
||||
DefNode(ShaderNode, SH_NODE_SCREENSPACE_INFO, 0, "SCREENSPACEINFO", ScreenspaceInfo, "Screenspace Info", "Sample internal colour and depth buffers")
|
||||
DefNode(ShaderNode, SH_NODE_SET_DEPTH, 0, "SET_DEPTH", SetDepth, "Set Depth", "Pixel depth offset")
|
||||
DefNode(ShaderNode, SH_NODE_CURVATURE, 0, "CURVATURE", Curvature, "Curvature", "" )
|
||||
|
||||
@@ -50,6 +50,7 @@ set(SRC
|
||||
nodes/node_shader_color_ramp.cc
|
||||
nodes/node_shader_tex_hexagon.cc
|
||||
nodes/node_shader_twirl.cc
|
||||
nodes/node_shader_water_ripples.cc
|
||||
nodes/node_shader_common.cc
|
||||
nodes/node_shader_curvature.cc
|
||||
nodes/node_shader_curves.cc
|
||||
|
||||
@@ -41,6 +41,7 @@ void register_shader_nodes()
|
||||
register_node_type_sh_combxyz();
|
||||
register_node_type_sh_tex_hexagon();
|
||||
register_node_type_sh_twirl();
|
||||
register_node_type_sh_water_ripples();
|
||||
register_node_type_sh_curvature();
|
||||
register_node_type_sh_curve_float();
|
||||
register_node_type_sh_curve_rgb();
|
||||
|
||||
@@ -37,6 +37,7 @@ void register_node_type_sh_combrgb();
|
||||
void register_node_type_sh_combxyz();
|
||||
void register_node_type_sh_tex_hexagon();
|
||||
void register_node_type_sh_twirl();
|
||||
void register_node_type_sh_water_ripples();
|
||||
void register_node_type_sh_curvature();
|
||||
void register_node_type_sh_curve_float();
|
||||
void register_node_type_sh_curve_rgb();
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
// Modified node_shader_water_ripples.cc
|
||||
#include "node_util.hh"
|
||||
#include "UI_interface.hh"
|
||||
#include "UI_resources.hh"
|
||||
#include "node_shader_util.hh"
|
||||
|
||||
namespace blender::nodes::node_shader_water_ripples_cc {
|
||||
|
||||
static void node_shader_init_water_ripples(bNodeTree * /*ntree*/, bNode *node)
|
||||
{
|
||||
NodeWaterRipples *storage = MEM_cnew<NodeWaterRipples>("NodeWaterRipples");
|
||||
storage->mode = NODE_WATER_RIPPLES_DROPS;
|
||||
node->storage = storage;
|
||||
}
|
||||
|
||||
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
|
||||
{
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiItemR(col, ptr, "mode", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
|
||||
}
|
||||
|
||||
static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
// Essential inputs
|
||||
b.add_input<decl::Vector>("Vector").default_value({0.0f, 0.0f, 0.0f});
|
||||
b.add_input<decl::Float>("Time").default_value(0.0f);
|
||||
|
||||
// ADD MODE AS INPUT SOCKET - this will solve the caching issue
|
||||
b.add_input<decl::Float>("Mode").default_value(0.0f).min(0.0f).max(3.0f).available(false);
|
||||
|
||||
// Main controls
|
||||
b.add_input<decl::Float>("Scale").default_value(1.0f).min(-10.0f).max(10.0f);
|
||||
b.add_input<decl::Float>("Intensity").default_value(1.0f).min(-10.0f).max(10.0f);
|
||||
b.add_input<decl::Float>("Speed").default_value(1.0f).min(-5.0f).max(5.0f);
|
||||
b.add_input<decl::Float>("Detail").default_value(0.5f).min(0.0f).max(1.0f);
|
||||
b.add_input<decl::Float>("Bias").default_value(0.6f).min(0.01f).max(0.99f);
|
||||
|
||||
// Outputs
|
||||
b.add_output<decl::Vector>("Distorted Vector");
|
||||
b.add_output<decl::Float>("Mask");
|
||||
}
|
||||
|
||||
static int gpu_shader_water_ripples(GPUMaterial *mat,
|
||||
bNode *node,
|
||||
bNodeExecData * /*execdata*/,
|
||||
GPUNodeStack *in,
|
||||
GPUNodeStack *out)
|
||||
{
|
||||
// Don't pass mode as constant anymore - it's now an input socket
|
||||
return GPU_stack_link(mat, node, "node_water_ripples", in, out);
|
||||
}
|
||||
|
||||
static void node_update(bNodeTree * /*tree*/, bNode *node)
|
||||
{
|
||||
NodeWaterRipples *storage = (NodeWaterRipples *)node->storage;
|
||||
if (!storage) return;
|
||||
|
||||
// Set the default value of the Mode socket based on the enum
|
||||
bNodeSocket *mode_socket = bke::node_find_socket(node, SOCK_IN, "Mode");
|
||||
if (mode_socket && mode_socket->default_value) {
|
||||
bNodeSocketValueFloat *mode_val = (bNodeSocketValueFloat *)mode_socket->default_value;
|
||||
mode_val->value = (float)storage->mode;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::nodes::node_shader_water_ripples_cc
|
||||
|
||||
void register_node_type_sh_water_ripples()
|
||||
{
|
||||
namespace file_ns = blender::nodes::node_shader_water_ripples_cc;
|
||||
|
||||
static blender::bke::bNodeType ntype;
|
||||
|
||||
sh_node_type_base(&ntype, SH_NODE_WATER_RIPPLES, "Water Ripples", NODE_CLASS_TEXTURE);
|
||||
ntype.declare = file_ns::node_declare;
|
||||
ntype.gpu_fn = file_ns::gpu_shader_water_ripples;
|
||||
ntype.draw_buttons = file_ns::node_layout;
|
||||
ntype.initfunc = file_ns::node_shader_init_water_ripples;
|
||||
ntype.updatefunc = file_ns::node_update;
|
||||
|
||||
node_type_storage(
|
||||
&ntype,
|
||||
"NodeWaterRipples",
|
||||
node_free_standard_storage,
|
||||
node_copy_standard_storage);
|
||||
|
||||
node_register_type(&ntype);
|
||||
}
|
||||
Reference in New Issue
Block a user