feat: add latticePattern and edgeBandPattern to TileTexture
This commit is contained in:
1 parent
4cbd72c75b
commit
1063442547
1 file changed
+162
@@ -150,3 +150,165 @@ PatternSample plankPattern(const TileSpec& spec, int tileSalt, int x, int y, int
|
||||
int board = across / boardWidth;
|
||||
int localAcross = across - board * boardWidth;
|
||||
|
||||
PatternSample out;
|
||||
if (localAcross == 0) {
|
||||
out.accentWeight = 1.0f;
|
||||
out.shade = 0.88f;
|
||||
return out;
|
||||
}
|
||||
out.shade = 0.94f + 0.12f * gridValue(tileSalt, board, spec.flipped ? 5 : 0, 31u, seed);
|
||||
if (localAcross == boardWidth - 1) out.shade *= 0.94f;
|
||||
float grain = lineNoise(tileSalt, along * (2.0f + spec.density * 5.0f) / size + board * 7.0f,
|
||||
33u, seed);
|
||||
out.accentWeight = clamp01((grain - 0.52f) * 3.2f) * 0.7f;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Two rails with rungs strung between them, or a full grid when flipped. The
|
||||
// rails sit a little inside the tile edge, which is the difference between a
|
||||
// ladder and a border, and the rungs only span the gap between them.
|
||||
PatternSample latticePattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
int barWidth = std::max(1, static_cast<int>(std::lround(size * (0.06f + spec.scale * 0.14f))));
|
||||
int spacing = std::max(barWidth * 2 + 1,
|
||||
static_cast<int>(std::lround(size * (0.22f + (1.0f - spec.density) * 0.3f))));
|
||||
int across = spec.vertical ? x : y;
|
||||
int along = spec.vertical ? y : x;
|
||||
|
||||
bool onRail = false;
|
||||
bool onCross = false;
|
||||
if (spec.flipped) {
|
||||
onRail = (across % spacing) < barWidth;
|
||||
onCross = (along % spacing) < barWidth;
|
||||
} else {
|
||||
int inset = std::max(0, size / 8);
|
||||
onRail = (across >= inset && across < inset + barWidth) ||
|
||||
(across >= size - inset - barWidth && across < size - inset);
|
||||
bool betweenRails = across >= inset && across < size - inset;
|
||||
onCross = betweenRails && (along % spacing) < barWidth;
|
||||
}
|
||||
|
||||
PatternSample out;
|
||||
if (onRail || onCross) {
|
||||
out.accentWeight = (onCross && !onRail) ? 1.0f : 0.0f;
|
||||
out.shade = 0.90f + 0.18f * gridValue(tileSalt, x, y, 41u, seed);
|
||||
return out;
|
||||
}
|
||||
out.hole = true;
|
||||
out.shade = 0.42f;
|
||||
return out;
|
||||
}
|
||||
|
||||
// A band of accent hugging one edge, its inner boundary chewed up by noise so
|
||||
// it does not read as a ruled line.
|
||||
PatternSample edgeBandPattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
float thickness = size * (0.15f + spec.scale * 0.35f);
|
||||
float depth = spec.flipped ? static_cast<float>(size - 1 - y) : static_cast<float>(y);
|
||||
float fringe = (lineNoise(tileSalt, x * 4.0f / size, 43u, seed) - 0.5f) * size * 0.16f;
|
||||
float edge = thickness + fringe;
|
||||
|
||||
PatternSample out;
|
||||
if (depth < edge) {
|
||||
out.accentWeight = 1.0f;
|
||||
out.shade = 1.0f - 0.10f * (depth / std::max(1.0f, edge));
|
||||
return out;
|
||||
}
|
||||
if (depth < edge + 1.0f) out.shade = 0.84f;
|
||||
out.accentWeight = 0.0f;
|
||||
return out;
|
||||
}
|
||||
|
||||
PatternSample growthRingsPattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
float centre = size * 0.5f;
|
||||
float dx = x + 0.5f - centre;
|
||||
float dy = y + 0.5f - centre;
|
||||
float radius = std::sqrt(dx * dx + dy * dy);
|
||||
float spacing = std::max(1.2f, size * (0.05f + spec.scale * 0.16f));
|
||||
// The warp has to stay a fraction of the ring spacing. Scaled to the tile
|
||||
// instead, it swallows tightly spaced rings and the tile goes flat.
|
||||
float warp = (fractalNoise(tileSalt, x * 3.0f / size, y * 3.0f / size, 47u, seed) - 0.5f) *
|
||||
spacing * 0.7f;
|
||||
float phase = (radius + warp) / spacing;
|
||||
float ring = std::fabs(phase - std::floor(phase) - 0.5f) * 2.0f;
|
||||
|
||||
PatternSample out;
|
||||
out.accentWeight = clamp01((1.0f - ring) * 1.4f) * spec.density;
|
||||
if (radius < spacing * 0.55f) out.accentWeight = spec.density;
|
||||
out.shade = 1.0f - 0.10f * clamp01(radius / (size * 0.7f));
|
||||
return out;
|
||||
}
|
||||
|
||||
// Round dots on a jittered cell grid: glowstone crumbs, amethyst facets, the
|
||||
// sculk's blue eyes. Only the nine surrounding cells are ever consulted.
|
||||
PatternSample dotsPattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
float cells = 2.0f + (1.0f - spec.scale) * 4.0f;
|
||||
float cellSize = size / cells;
|
||||
float fx = (x + 0.5f) / cellSize;
|
||||
float fy = (y + 0.5f) / cellSize;
|
||||
int cx = static_cast<int>(std::floor(fx));
|
||||
int cy = static_cast<int>(std::floor(fy));
|
||||
|
||||
float nearest = 8.0f;
|
||||
for (int oy = -1; oy <= 1; ++oy) {
|
||||
for (int ox = -1; ox <= 1; ++ox) {
|
||||
int gx = cx + ox;
|
||||
int gy = cy + oy;
|
||||
if (gridValue(tileSalt, gx, gy, 53u, seed) > spec.density) continue;
|
||||
float jitterX = gx + 0.25f + 0.5f * gridValue(tileSalt, gx, gy, 51u, seed);
|
||||
float jitterY = gy + 0.25f + 0.5f * gridValue(tileSalt, gx, gy, 52u, seed);
|
||||
float dx = fx - jitterX;
|
||||
float dy = fy - jitterY;
|
||||
float distance = std::sqrt(dx * dx + dy * dy);
|
||||
if (distance < nearest) nearest = distance;
|
||||
}
|
||||
}
|
||||
|
||||
float radius = 0.16f + spec.scale * 0.30f;
|
||||
PatternSample out;
|
||||
if (nearest < radius) {
|
||||
out.accentWeight = clamp01((1.0f - nearest / radius) * 1.7f);
|
||||
out.shade = 1.0f + 0.10f * out.accentWeight;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
PatternSample strataPattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
float across = spec.vertical ? static_cast<float>(x) : static_cast<float>(y);
|
||||
float along = spec.vertical ? static_cast<float>(y) : static_cast<float>(x);
|
||||
float bands = 3.0f + spec.scale * 6.0f;
|
||||
float warp = (lineNoise(tileSalt, along * 3.0f / size, 59u, seed) - 0.5f) * size * 0.12f;
|
||||
float phase = (across + warp) * bands / size;
|
||||
float within = phase - std::floor(phase);
|
||||
|
||||
PatternSample out;
|
||||
out.accentWeight = within < spec.density ? 1.0f : 0.0f;
|
||||
out.shade = 1.0f + 0.07f * std::sin(phase * twoPi);
|
||||
if (within < 0.10f) out.shade *= 0.88f;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Irregular blobs with a dark rim, which is what turns a flat colour into
|
||||
// cobble, gravel or netherrack.
|
||||
PatternSample splatterPattern(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
uint32_t seed) {
|
||||
float coarseCells = 2.0f + spec.scale * 3.0f;
|
||||
float fineCells = coarseCells * 2.6f;
|
||||
float coarse = fractalNoise(tileSalt, x * coarseCells / size, y * coarseCells / size, 61u, seed);
|
||||
float fine = fractalNoise(tileSalt, x * fineCells / size, y * fineCells / size, 67u, seed);
|
||||
float field = coarse * 0.66f + fine * 0.34f;
|
||||
float threshold = 1.0f - spec.density * 0.9f;
|
||||
|
||||
PatternSample out;
|
||||
if (field > threshold) {
|
||||
out.accentWeight = clamp01((field - threshold) * 6.0f);
|
||||
} else if (field > threshold - 0.05f) {
|
||||
out.shade = 0.80f;
|
||||
}
|
||||
out.shade *= 0.95f + 0.10f * fine;
|
||||
return out;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user