High-res ore textures: gold, silver, ruby and diamond as lumps in the earth, no veins

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-07 21:32:00 +01:00
1 parent 9df16607ed
commit 50f8af15c7
31 files changed
+58 -32

No files matched your search

+19 -6
View File
@@ -40,12 +40,6 @@ Solid packed brown earth seen from above, soil with small stones, roots and dark
Hard dark blue-grey bedrock seen from above, angular rock facets and deep cracks, very solid and impenetrable.
```
## gold: T_GOLD (gold seam)
```text
A uniform all-over pattern of brown earth crossed by many thick glittering veins of bright yellow gold ore with large shining gold nuggets, the gold covering about a third of the surface, evenly spread from edge to edge.
```
## water: T_WATER
```text
@@ -74,3 +68,22 @@ python3 tools/make_tile.py <name>-raw.png <name> --size 256 --colors 48 --band 2
```
`<name>-256.png` is copied to `assets/textures/<name>-256.png`.
## Gold, silver, ruby and diamond: lumps without veins (2026-11-07)
Made from the earth picture so the soil matches: `fal-ai/nano-banana-pro/edit` with
`earth-raw.png` as the reference image (`aspect_ratio: 1:1`, `resolution: 1K`, one image each).
The prompt template, `{ore}` per kind:
```text
Keep this exact seamless tileable earth texture (same colours, same soil, same style, same top-down view) and embed {ore} scattered in the soil: about twelve separate lumps of different sizes, partly buried, spread evenly over the whole image including near the edges. No veins, no lines, no cracks filled with ore, no streaks - only separate lumps. The texture must stay seamless across all four edges. No text.
```
- gold: `chunky nuggets of shining yellow gold`
- silver: `chunky nuggets of bright shining silver ore`
- ruby: `chunky raw red ruby crystals`
- diamond: `chunky raw clear pale-blue diamond crystals`
Gold has four variants (`--size 128` and `--size 256` like the others). Silver, ruby and diamond
have two variants: one seamless tile for both (`--size 64 --colors 32 --band 8` and
`--size 128 --colors 48 --band 14`), copied to `assets/textures/<name>.png` and `<name>-128.png`.
Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 KiB

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

+37 -24
View File
@@ -331,25 +331,33 @@ fn earth_px(x: i32, y: i32, v: u32) -> Color {
// The high-res style's atlases: the same cells as the 16x16 atlas, HD_TILE (64) or HD_TILE2 (128)
// texels each; the world shows the 128 one close up, where a tile gets that many pixels (two
// levels like the sprites: neither loses pixels nor flickers). Cells without an own texture are
// the 16x16 ones scaled up. HD_TILES: generated textures (see art/generated/textures/), each a
// seamless 2x2 block of tiles for the four variants of a kind (variant k = quarter k % 2, k / 2);
// the world lays the quarters out by the tiles' positions (see hd_tile), so a floor repeats only
// every two tiles and has no seams.
// the 16x16 ones scaled up. HD_TILES: generated textures (see art/generated/textures/): for kinds
// with four variants a seamless 2x2 block of tiles (variant k = quarter k % 2, k / 2; the world
// lays the quarters out by the tiles' positions, see hd_tile, so a floor repeats only every two
// tiles and has no seams), for kinds with two variants one seamless tile for both.
pub const HD_TILE: u32 = 64;
pub const HD_TILE2: u32 = 128;
const HD_TILES: [(u32, &[u8], &[u8]); 7] = [
(T_FLOOR, include_bytes!("../assets/textures/floor.png"), include_bytes!("../assets/textures/floor-256.png")),
(T_CLAIM, include_bytes!("../assets/textures/claimed.png"), include_bytes!("../assets/textures/claimed-256.png")),
(T_EARTH, include_bytes!("../assets/textures/earth.png"), include_bytes!("../assets/textures/earth-256.png")),
(T_ROCK, include_bytes!("../assets/textures/rock.png"), include_bytes!("../assets/textures/rock-256.png")),
(T_GOLD, include_bytes!("../assets/textures/gold.png"), include_bytes!("../assets/textures/gold-256.png")),
(T_WATER, include_bytes!("../assets/textures/water.png"), include_bytes!("../assets/textures/water-256.png")),
(T_LAVA, include_bytes!("../assets/textures/lava.png"), include_bytes!("../assets/textures/lava-256.png")),
// (first cell, variants, 64x64 level, 128x128 level)
const HD_TILES: [(u32, u32, &[u8], &[u8]); 10] = [
(T_FLOOR, 4, include_bytes!("../assets/textures/floor.png"), include_bytes!("../assets/textures/floor-256.png")),
(T_CLAIM, 4, include_bytes!("../assets/textures/claimed.png"), include_bytes!("../assets/textures/claimed-256.png")),
(T_EARTH, 4, include_bytes!("../assets/textures/earth.png"), include_bytes!("../assets/textures/earth-256.png")),
(T_ROCK, 4, include_bytes!("../assets/textures/rock.png"), include_bytes!("../assets/textures/rock-256.png")),
(T_GOLD, 4, include_bytes!("../assets/textures/gold.png"), include_bytes!("../assets/textures/gold-256.png")),
(T_WATER, 4, include_bytes!("../assets/textures/water.png"), include_bytes!("../assets/textures/water-256.png")),
(T_LAVA, 4, include_bytes!("../assets/textures/lava.png"), include_bytes!("../assets/textures/lava-256.png")),
(T_SILVER, 2, include_bytes!("../assets/textures/silver.png"), include_bytes!("../assets/textures/silver-128.png")),
(T_RUBY, 2, include_bytes!("../assets/textures/ruby.png"), include_bytes!("../assets/textures/ruby-128.png")),
(T_DIAMOND, 2, include_bytes!("../assets/textures/diamond.png"), include_bytes!("../assets/textures/diamond-128.png")),
];
// whether a cell has a generated high-res texture (its variants are laid out by position)
pub fn hd_tile(id: u32) -> bool {
HD_TILES.iter().any(|&(base, _, _)| id / 4 * 4 == base)
// the cell a tile at (x, z) shows in the high-res style: generated textures with four variants
// are laid out by the position (see HD_TILES), everything else stays
pub fn hd_tile(id: u32, x: i32, z: i32) -> u32 {
match HD_TILES.iter().find(|&&(base, n, _, _)| (base..base + n).contains(&id)) {
Some(&(base, 4, _, _)) => base + (x & 1) as u32 + (z & 1) as u32 * 2,
_ => id,
}
}
// a high-res atlas with `tile` x `tile` texel cells (HD_TILE or HD_TILE2)
@@ -363,10 +371,10 @@ fn gen_hd_atlas(tile: u32) -> Image {
img.set_pixel(x, y, small.get_pixel(x / k, y / k));
}
}
for &(base, png, png2) in HD_TILES.iter() {
for &(base, n, png, png2) in HD_TILES.iter() {
let src = Image::from_file_with_format(if tile == HD_TILE2 { png2 } else { png }, Some(ImageFormat::Png)).expect("hd tile");
for v in 0..4 {
let (sx, sy) = ((v % 2) * tile, (v / 2) * tile);
for v in 0..n {
let (sx, sy) = if n == 4 { ((v % 2) * tile, (v / 2) * tile) } else { (0, 0) };
let id = base + v;
let (ox, oy) = ((id % ATLAS_COLS) * tile, (id / ATLAS_COLS) * tile);
for y in 0..tile {
@@ -2711,18 +2719,23 @@ mod hd_atlas_tests {
assert_eq!(px(&hd, (cx + x) * k + 2, (cy + y) * k + 1), px(&small, cx + x, cy + y));
}
// the generated ones: the quarters of their 2x2 sheet
for &(base, png, png2) in HD_TILES.iter() {
for &(base, n, png, png2) in HD_TILES.iter() {
let src = Image::from_file_with_format(if tile == HD_TILE2 { png2 } else { png }, Some(ImageFormat::Png)).unwrap();
assert_eq!((src.width as u32, src.height as u32), (2 * tile, 2 * tile));
for v in 0..4 {
let side = if n == 4 { 2 * tile } else { tile };
assert_eq!((src.width as u32, src.height as u32), (side, side));
for v in 0..n {
let id = base + v;
assert!(hd_tile(id));
let (ox, oy) = ((id % ATLAS_COLS) * tile, (id / ATLAS_COLS) * tile);
assert_eq!(px(&hd, ox + 7, oy + 40), px(&src, (v % 2) * tile + 7, (v / 2) * tile + 40));
let (sx, sy) = if n == 4 { ((v % 2) * tile, (v / 2) * tile) } else { (0, 0) };
assert_eq!(px(&hd, ox + 7, oy + 40), px(&src, sx + 7, sy + 40));
}
}
}
assert!(!hd_tile(T_TREASURY));
// four variants by position, two variants keep theirs, others stay
assert_eq!(hd_tile(T_FLOOR + 3, 0, 0), T_FLOOR);
assert_eq!(hd_tile(T_FLOOR, 1, 1), T_FLOOR + 3);
assert_eq!(hd_tile(T_RUBY + 1, 1, 0), T_RUBY + 1);
assert_eq!(hd_tile(T_TREASURY + 2, 1, 0), T_TREASURY + 2);
}
}
+2 -2
View File
@@ -810,8 +810,8 @@ fn build_chunk(map: &Map, amb: &[f32], glow: &[f32], cx: i32, cz: i32, atlas: &T
if t.kind == Kind::Mushroom && t.res & MUSH_GROVE != 0 {
tex = crate::gfx::T_MOSS + (t.var as u32 & 3);
}
if hd && crate::gfx::hd_tile(tex) {
tex = tex / 4 * 4 + (x & 1) as u32 + (z & 1) as u32 * 2;
if hd {
tex = crate::gfx::hd_tile(tex, x, z);
}
let (ua, ub) = cell_uv(tex);
let (xf, zf) = (x as f32, z as f32);