feat: extend TileTexture
This commit is contained in:
1 parent
cdbcb1e701
commit
35cc9ae4b7
1 file changed
+126
@@ -458,3 +458,129 @@ float materialGrain(const TileSpec& spec, int tileSalt, int x, int y, int size,
|
||||
float amount = spec.noise;
|
||||
if (amount <= 0.0f) return 1.0f;
|
||||
|
||||
float shape = 0.0f;
|
||||
switch (spec.material) {
|
||||
case TileMaterial::Stone: {
|
||||
float speck = gridValue(tileSalt, x, y, 101u, seed) * 2.0f - 1.0f;
|
||||
float mottle =
|
||||
fractalNoise(tileSalt, x * 4.0f / size, y * 4.0f / size, 103u, seed) * 2.0f - 1.0f;
|
||||
shape = speck * 0.70f + mottle * 0.55f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Soil: {
|
||||
float clump =
|
||||
fractalNoise(tileSalt, x * 5.0f / size, y * 5.0f / size, 107u, seed) * 2.0f - 1.0f;
|
||||
float crumb = gridValue(tileSalt, x, y, 109u, seed) * 2.0f - 1.0f;
|
||||
shape = clump * 0.90f + crumb * 0.45f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Wood: {
|
||||
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 ring = lineNoise(tileSalt, across * 6.0f / size, 113u, seed) * 2.0f - 1.0f;
|
||||
float fibre =
|
||||
valueNoise(tileSalt, along * 3.0f / size, across * 9.0f / size, 127u, seed) * 2.0f -
|
||||
1.0f;
|
||||
shape = ring * 0.65f + fibre * 0.55f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Foliage: {
|
||||
float cluster = fractalNoise(tileSalt, x * 6.0f / size, y * 6.0f / size, 131u, seed);
|
||||
float fleck = gridValue(tileSalt, x, y, 137u, seed) * 2.0f - 1.0f;
|
||||
shape = (cluster < 0.44f ? -0.95f : 0.40f) + fleck * 0.45f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Metal: {
|
||||
float sheen = std::cos((x + y) * 0.5f / size * twoPi) * 0.85f;
|
||||
float scratch = gridValue(tileSalt, x, y * 3, 139u, seed) > 0.88f ? -0.95f : 0.0f;
|
||||
shape = sheen + scratch + (gridValue(tileSalt, x, y, 149u, seed) * 2.0f - 1.0f) * 0.25f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Crystal: {
|
||||
float facet =
|
||||
valueNoise(tileSalt, (x + y) * 2.5f / size, (x - y) * 2.5f / size, 151u, seed);
|
||||
shape = (facet - 0.5f) * 2.4f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Fabric: {
|
||||
float weave = ((x / 2) + (y / 2)) % 2 == 0 ? 0.75f : -0.75f;
|
||||
shape = weave + (gridValue(tileSalt, x, y, 157u, seed) * 2.0f - 1.0f) * 0.40f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Fluid: {
|
||||
float swell = std::sin((y * 2.0f / size + x * 0.35f / size) * twoPi);
|
||||
shape = swell * 0.80f + (gridValue(tileSalt, x, y, 163u, seed) * 2.0f - 1.0f) * 0.35f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Light: {
|
||||
float half = size * 0.5f;
|
||||
float dx = (x + 0.5f - half) / half;
|
||||
float dy = (y + 0.5f - half) / half;
|
||||
float glow = 1.0f - clamp01(std::sqrt(dx * dx + dy * dy));
|
||||
shape = glow * 1.7f - 0.65f + (gridValue(tileSalt, x, y, 167u, seed) * 2.0f - 1.0f) * 0.3f;
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Organic: {
|
||||
float soft = fractalNoise(tileSalt, x * 3.0f / size, y * 3.0f / size, 173u, seed);
|
||||
float pore = gridValue(tileSalt, x, y, 179u, seed);
|
||||
shape = (soft - 0.5f) * 1.9f + (pore > 0.92f ? -0.85f : 0.0f);
|
||||
break;
|
||||
}
|
||||
case TileMaterial::Count: break;
|
||||
}
|
||||
return std::max(0.0f, 1.0f + amount * shape);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TileSampler::TileSampler(const TileTextureParams& params) : settings(params) {}
|
||||
|
||||
TileSampler::TileSampler(const TileTextureParams& params, const TilePalette& palette)
|
||||
: settings(params), table(palette) {}
|
||||
|
||||
TilePixel TileSampler::pixelOf(const TileSpec& spec, int tileSalt, int x, int y) const {
|
||||
int size = settings.tileSize;
|
||||
PatternSample pattern = samplePattern(spec, tileSalt, x, y, size, settings.noiseSeed);
|
||||
TileRgb blended = mixRgb(spec.base, spec.accent, pattern.accentWeight);
|
||||
|
||||
float brightness = pattern.shade * materialGrain(spec, tileSalt, x, y, size, settings.noiseSeed);
|
||||
// The old atlas darkened the first row and column so block edges stayed
|
||||
// legible against each other. Cheap, and every tile still needs it.
|
||||
if (x == 0 || y == 0) brightness *= 0.86f;
|
||||
|
||||
float red = blended.r * brightness;
|
||||
float green = blended.g * brightness;
|
||||
float blue = blended.b * brightness;
|
||||
|
||||
red = spec.base.r + (red - spec.base.r) * settings.contrast;
|
||||
green = spec.base.g + (green - spec.base.g) * settings.contrast;
|
||||
blue = spec.base.b + (blue - spec.base.b) * settings.contrast;
|
||||
|
||||
TilePixel out;
|
||||
out.r = toByte(red);
|
||||
out.g = toByte(green);
|
||||
out.b = toByte(blue);
|
||||
out.a = (spec.cutout && pattern.hole) ? 0 : 255;
|
||||
return out;
|
||||
}
|
||||
|
||||
TilePixel TileSampler::pixelAt(int tile, int x, int y) const {
|
||||
return pixelOf(table.specFor(tile), tile, x, y);
|
||||
}
|
||||
|
||||
void TileSampler::writeTile(int tile, uint8_t* rgba) const {
|
||||
const TileSpec& spec = table.specFor(tile);
|
||||
int size = settings.tileSize;
|
||||
for (int y = 0; y < size; ++y) {
|
||||
for (int x = 0; x < size; ++x) {
|
||||
TilePixel texel = pixelOf(spec, tile, x, y);
|
||||
std::size_t offset = (static_cast<std::size_t>(y) * size + x) * 4;
|
||||
rgba[offset + 0] = texel.r;
|
||||
rgba[offset + 1] = texel.g;
|
||||
rgba[offset + 2] = texel.b;
|
||||
rgba[offset + 3] = texel.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace vf
|
||||
Reference in new issue
Block a user