layer strength

This commit is contained in:
Connor
2026-02-23 23:07:10 +09:00
parent 1e6a8d4f60
commit 1b7fd1c7f8
10 changed files with 725 additions and 230 deletions

View File

@@ -295,7 +295,7 @@ public:
QueryRangeNode(int32_t mnX, int32_t mnY, int32_t mxX, int32_t mxY, int32_t id)
: minX(mnX), minY(mnY), maxX(mxX), maxY(mxY), tileID(id) {}
Type GetOutputType() const override { return Type::Int; }
Type GetOutputType() const override { return Type::Float; }
std::vector<Type> GetInputTypes() const override { return {}; }
std::string GetName() const override { return "QueryRange"; }
Value Evaluate(const EvalContext& ctx, const std::vector<Value>&) const override {
@@ -304,7 +304,7 @@ public:
for (int32_t dx = minX; dx <= maxX; ++dx)
if (ctx.GetPrevTile(ctx.worldX + dx, ctx.worldY + dy) == tileID)
++count;
return Value::MakeInt(count);
return Value::MakeFloat(static_cast<float>(count));
}
};
@@ -381,6 +381,16 @@ public:
Value Evaluate(const EvalContext& ctx, const std::vector<Value>&) const override { return Value::MakeFloat(ctx.worldY); };
};
/// Outputs the current layer's blending strength, set by the world compositor.
/// Returns 1.0 when running outside a layered world (normal graph evaluation).
class LayerStrengthNode : public Node {
public:
Type GetOutputType() const override { return Type::Float; }
std::vector<Type> GetInputTypes() const override { return {}; }
std::string GetName() const override { return "LayerStrength"; }
Value Evaluate(const EvalContext& ctx, const std::vector<Value>&) const override { return Value::MakeFloat(ctx.layerStrength); }
};
// ─────────────────────────────── Abs / Negate ────────────────────────────────
/// |a| (Float)
@@ -501,6 +511,30 @@ public:
// ─────────────────────────────── Extended math nodes ─────────────────────────
/// floor(a) (Float)
class FloorNode : public Node {
public:
Type GetOutputType() const override { return Type::Float; }
std::vector<Type> GetInputTypes() const override { return { Type::Float }; }
std::string GetName() const override { return "Floor"; }
Value Evaluate(const EvalContext&, const std::vector<Value>& in) const override {
DEV_ASSERT(in.size() == 1);
return Value::MakeFloat(std::floor(in[0].AsFloat()));
}
};
/// ceil(a) (Float)
class CeilNode : public Node {
public:
Type GetOutputType() const override { return Type::Float; }
std::vector<Type> GetInputTypes() const override { return { Type::Float }; }
std::string GetName() const override { return "Ceil"; }
Value Evaluate(const EvalContext&, const std::vector<Value>& in) const override {
DEV_ASSERT(in.size() == 1);
return Value::MakeFloat(std::ceil(in[0].AsFloat()));
}
};
/// sqrt(a), clamped to 0 for negative inputs (Float)
class SqrtNode : public Node {
public:
@@ -605,6 +639,28 @@ public:
// Each noise node reads worldX/Y and seed from EvalContext; no graph inputs.
// Output is a Float in [-1, 1].
//
// RandomNode is the exception: it produces spatially incoherent white noise
// via a hash of (seed, worldX, worldY), output in [0, 1].
/// Spatially incoherent hash-based random value in [0, 1].
/// Each (seed, worldX, worldY) triple produces an independent value — no
/// smoothing, no spatial correlation. (Float)
class RandomNode : public Node {
public:
Type GetOutputType() const override { return Type::Float; }
std::vector<Type> GetInputTypes() const override { return {}; }
std::string GetName() const override { return "Random"; }
Value Evaluate(const EvalContext& ctx, const std::vector<Value>&) const override {
// Mix seed, x, y with Knuth multiplicative hashes then finalise.
uint32_t h = static_cast<uint32_t>(ctx.seed)
^ (static_cast<uint32_t>(ctx.worldX) * 2654435761u)
^ (static_cast<uint32_t>(ctx.worldY) * 2246822519u);
h ^= h >> 16;
h *= 0x45d9f3bu;
h ^= h >> 16;
return Value::MakeFloat((h & 0xFFFFFFu) / static_cast<float>(0x1000000u));
}
};
// A new FastNoiseLite object is constructed per evaluation so that the seed
// from the context is applied correctly across every cell.

View File

@@ -44,6 +44,11 @@ struct EvalContext {
int32_t prevWidth { 0 };
int32_t prevHeight { 0 };
// ── Layer blending strength ────────────────────────────────────────────
// Set by the world layer compositor before calling Evaluate().
// 1.0 = this layer is fully active; 0.0 = this layer has no influence.
float layerStrength { 1.0f };
/// Query the previous pass at an absolute world position.
/// Returns 0 (AIR / empty) when no previous pass or position is out of bounds.
inline int32_t GetPrevTile(int32_t x, int32_t y) const noexcept;