Added smoothstep

This commit is contained in:
Marc Gilleron 2020-04-05 19:53:07 +01:00
parent 9ce0ded22e
commit f73e566535
6 changed files with 60 additions and 0 deletions

View File

@ -706,6 +706,7 @@ void VoxelGeneratorGraph::_bind_methods() {
BIND_ENUM_CONSTANT(NODE_CLAMP);
BIND_ENUM_CONSTANT(NODE_MIX);
BIND_ENUM_CONSTANT(NODE_REMAP);
BIND_ENUM_CONSTANT(NODE_SMOOTHSTEP);
BIND_ENUM_CONSTANT(NODE_CURVE);
BIND_ENUM_CONSTANT(NODE_NOISE_2D);
BIND_ENUM_CONSTANT(NODE_NOISE_3D);

View File

@ -32,6 +32,7 @@ public:
NODE_CLAMP,
NODE_MIX,
NODE_REMAP,
NODE_SMOOTHSTEP,
NODE_CURVE,
NODE_NOISE_2D,
NODE_NOISE_3D,

View File

@ -181,6 +181,14 @@ VoxelGraphNodeDB::VoxelGraphNodeDB() {
t.params.push_back(Param("min1", Variant::REAL, -1.f));
t.params.push_back(Param("max1", Variant::REAL, 1.f));
}
{
NodeType &t = types[VoxelGeneratorGraph::NODE_SMOOTHSTEP];
t.name = "Smoothstep";
t.inputs.push_back(Port("x"));
t.outputs.push_back(Port("out"));
t.params.push_back(Param("edge0", Variant::REAL, 0.f));
t.params.push_back(Param("edge1", Variant::REAL, 1.f));
}
{
NodeType &t = types[VoxelGeneratorGraph::NODE_CURVE];
t.name = "Curve";

View File

@ -267,6 +267,13 @@ void VoxelGraphRuntime::compile(const ProgramGraph &graph) {
append(program, max1 - min1);
} break;
case VoxelGeneratorGraph::NODE_SMOOTHSTEP: {
float edge0 = node->params[0].operator float();
float edge1 = node->params[1].operator float();
append(program, edge0);
append(program, edge1);
} break;
} // switch special params
#ifdef VOXEL_DEBUG_GRAPH_PROG_SENTINEL
@ -355,6 +362,13 @@ struct PNodeRemap {
float p_m1;
};
struct PNodeSmoothstep {
uint16_t a_x;
uint16_t a_out;
float p_edge0;
float p_edge1;
};
struct PNodeCurve {
uint16_t a_in;
uint16_t a_out;
@ -586,6 +600,11 @@ float VoxelGraphRuntime::generate_single(const Vector3i &position) {
memory[n.a_out] = ((memory[n.a_x] - n.p_c0) * n.p_m0) * n.p_m1 + n.p_c1;
} break;
case VoxelGeneratorGraph::NODE_SMOOTHSTEP: {
const PNodeSmoothstep &n = read<PNodeSmoothstep>(_program, pc);
memory[n.a_out] = smoothstep(n.p_edge0, n.p_edge1, memory[n.a_x]);
} break;
case VoxelGeneratorGraph::NODE_CURVE: {
const PNodeCurve &n = read<PNodeCurve>(_program, pc);
memory[n.a_out] = n.p_curve->interpolate_baked(memory[n.a_in]);
@ -831,6 +850,14 @@ Interval VoxelGraphRuntime::analyze_range(Vector3i min_pos, Vector3i max_pos) {
max_memory[n.a_out] = r.max;
} break;
case VoxelGeneratorGraph::NODE_SMOOTHSTEP: {
const PNodeSmoothstep &n = read<PNodeSmoothstep>(_program, pc);
Interval x(min_memory[n.a_x], max_memory[n.a_x]);
Interval r = smoothstep(n.p_edge0, n.p_edge1, x);
min_memory[n.a_out] = r.min;
max_memory[n.a_out] = r.max;
} break;
case VoxelGeneratorGraph::NODE_CURVE: {
const PNodeCurve &n = read<PNodeCurve>(_program, pc);
if (min_memory[n.a_in] == max_memory[n.a_in]) {

View File

@ -205,4 +205,18 @@ inline Interval wrapf(const Interval &x, const Interval &d) {
return x - (d * floor(x / d));
}
inline Interval smoothstep(float p_from, float p_to, Interval p_weight) {
if (Math::is_equal_approx(p_from, p_to)) {
return Interval::from_single_value(p_from);
}
// Smoothstep is monotonic
float v0 = smoothstep(p_from, p_to, p_weight.min);
float v1 = smoothstep(p_from, p_to, p_weight.max);
if (v0 <= v1) {
return Interval(v0, v1);
} else {
return Interval(v1, v0);
}
}
#endif // INTERVAL_H

View File

@ -203,6 +203,15 @@ inline float wrapf(float x, float d) {
return Math::is_zero_approx(d) ? 0.f : x - (d * Math::floor(x / d));
}
// Similar to Math::smoothstep but doesn't use macro to clamp
inline float smoothstep(float p_from, float p_to, float p_weight) {
if (Math::is_equal_approx(p_from, p_to)) {
return p_from;
}
float x = clamp((p_weight - p_from) / (p_to - p_from), 0.0f, 1.0f);
return x * x * (3.0f - 2.0f * x);
}
#if TOOLS_ENABLED
namespace VoxelDebug {
void create_debug_box_mesh();