feat(textures): atlas blocs tileable + UV mapping Chunk.gd (supprime vertex colors)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Floppyrj45
2026-04-19 18:09:47 +02:00
parent 37a2458c36
commit 52dc661e7b
4 changed files with 325 additions and 41 deletions

View File

@@ -10,72 +10,120 @@ enum BlockType {
KELP = 6,
WRECK_WOOD = 7,
ICE = 8,
BEDROCK = 9
BEDROCK = 9,
GLOW_CORAL_CYAN = 10,
GLOW_CORAL_VIOLET = 11,
LAVA_VENT = 12
}
# Atlas is 4x4 tiles, each tile = 0.25 of atlas width/height
const ATLAS_TILE_SIZE: Vector2 = Vector2(0.25, 0.25)
const _BLOCKS: Dictionary = {
BlockType.AIR: {
"name": "Air",
"color": Color(0.0, 0.0, 0.0, 0.0),
"hardness": 0.0,
"drops": []
"drops": [],
"atlas_uv": Vector2(0.0, 0.0) # unused, AIR not rendered
},
BlockType.WATER: {
"name": "Eau",
"color": Color(0.1, 0.4, 0.8, 0.6),
"hardness": 0.0,
"drops": []
"drops": [],
"atlas_uv": Vector2(0.0, 0.0) # unused, WATER not solid
},
BlockType.SAND: {
"name": "Sable",
"color": Color(0.76, 0.70, 0.50, 1.0),
"hardness": 0.5,
"drops": [BlockType.SAND]
"drops": [BlockType.SAND],
"atlas_uv": Vector2(0.0, 0.0) # row 0, col 0
},
BlockType.ROCK: {
"name": "Roche",
"color": Color(0.45, 0.45, 0.45, 1.0),
"hardness": 2.0,
"drops": [BlockType.ROCK]
"drops": [BlockType.ROCK],
"atlas_uv": Vector2(0.25, 0.0) # row 0, col 1
},
BlockType.CORAL_RED: {
"name": "Corail Rouge",
"color": Color(0.90, 0.25, 0.20, 1.0),
"hardness": 0.3,
"drops": [BlockType.CORAL_RED]
"drops": [BlockType.CORAL_RED],
"atlas_uv": Vector2(0.5, 0.0) # row 0, col 2
},
BlockType.CORAL_BLUE: {
"name": "Corail Bleu",
"color": Color(0.20, 0.50, 0.95, 1.0),
"hardness": 0.3,
"drops": [BlockType.CORAL_BLUE]
"drops": [BlockType.CORAL_BLUE],
"atlas_uv": Vector2(0.75, 0.0) # row 0, col 3
},
BlockType.KELP: {
"name": "Algue",
"color": Color(0.15, 0.60, 0.20, 1.0),
"hardness": 0.1,
"drops": [BlockType.KELP]
"drops": [BlockType.KELP],
"atlas_uv": Vector2(0.0, 0.25) # row 1, col 0
},
BlockType.WRECK_WOOD: {
"name": "Bois d'Épave",
"color": Color(0.35, 0.22, 0.12, 1.0),
"hardness": 1.0,
"drops": [BlockType.WRECK_WOOD]
"drops": [BlockType.WRECK_WOOD],
"atlas_uv": Vector2(0.25, 0.25) # row 1, col 1
},
BlockType.ICE: {
"name": "Glace",
"color": Color(0.75, 0.90, 1.0, 0.85),
"hardness": 0.8,
"drops": []
"drops": [],
"atlas_uv": Vector2(0.5, 0.25) # row 1, col 2
},
BlockType.BEDROCK: {
"name": "Bedrock",
"color": Color(0.15, 0.15, 0.15, 1.0),
"hardness": -1.0,
"drops": []
"drops": [],
"atlas_uv": Vector2(0.75, 0.25) # row 1, col 3
},
BlockType.GLOW_CORAL_CYAN: {
"name": "Corail Bio Cyan",
"color": Color(0.2, 0.8, 1.0, 1.0),
"hardness": 0.3,
"drops": [BlockType.GLOW_CORAL_CYAN],
"atlas_uv": Vector2(0.0, 0.5), # row 2, col 0
"emission": Color(0.2, 0.8, 1.0),
"emission_energy": 3.0
},
BlockType.GLOW_CORAL_VIOLET: {
"name": "Corail Bio Violet",
"color": Color(0.7, 0.3, 0.9, 1.0),
"hardness": 0.3,
"drops": [BlockType.GLOW_CORAL_VIOLET],
"atlas_uv": Vector2(0.25, 0.5), # row 2, col 1
"emission": Color(0.7, 0.3, 0.9),
"emission_energy": 3.0
},
BlockType.LAVA_VENT: {
"name": "Cheminée Hydrothermale",
"color": Color(1.0, 0.5, 0.1, 1.0),
"hardness": 3.0,
"drops": [BlockType.LAVA_VENT],
"atlas_uv": Vector2(0.5, 0.5), # row 2, col 2
"emission": Color(1.0, 0.5, 0.1),
"emission_energy": 3.0
}
}
func get_atlas_uv(id: int) -> Vector2:
if _BLOCKS.has(id):
return _BLOCKS[id]["atlas_uv"]
return Vector2(0.0, 0.0)
func is_solid(id: int) -> bool:
if id == BlockType.AIR or id == BlockType.WATER or id == BlockType.KELP:
return false
@@ -100,3 +148,18 @@ func get_drops(id: int) -> Array:
if _BLOCKS.has(id):
return _BLOCKS[id]["drops"]
return []
func is_emissive(id: int) -> bool:
if _BLOCKS.has(id):
return _BLOCKS[id].has("emission")
return false
func get_emission_color(id: int) -> Color:
if _BLOCKS.has(id) and _BLOCKS[id].has("emission"):
return _BLOCKS[id]["emission"]
return Color(0.0, 0.0, 0.0)
func get_emission_energy(id: int) -> float:
if _BLOCKS.has(id) and _BLOCKS[id].has("emission_energy"):
return _BLOCKS[id]["emission_energy"]
return 1.0

View File

@@ -7,6 +7,16 @@ var _blocks: PackedInt32Array = PackedInt32Array()
var _mesh_instance: MeshInstance3D = null
var _static_body: StaticBody3D = null
static var shared_material: StandardMaterial3D = null
static func _init_material() -> void:
if shared_material == null:
shared_material = StandardMaterial3D.new()
shared_material.albedo_texture = load("res://assets/textures/block_atlas.png")
shared_material.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST_WITH_MIPMAPS
shared_material.vertex_color_use_as_albedo = false
shared_material.shading_mode = BaseMaterial3D.SHADING_MODE_PER_VERTEX
func _ready() -> void:
if _blocks.size() == 0:
_blocks.resize(4096)
@@ -32,11 +42,16 @@ func generate_mesh() -> void:
_static_body.queue_free()
_static_body = null
_init_material()
var st: SurfaceTool = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
var has_faces: bool = false
var tile_w: float = BlockDatabase.ATLAS_TILE_SIZE.x
var tile_h: float = BlockDatabase.ATLAS_TILE_SIZE.y
for x: int in range(CHUNK_SIZE):
for y: int in range(CHUNK_SIZE):
for z: int in range(CHUNK_SIZE):
@@ -44,25 +59,25 @@ func generate_mesh() -> void:
if not BlockDatabase.is_solid(block_id):
continue
var color: Color = BlockDatabase.get_color(block_id)
var uv_tl: Vector2 = BlockDatabase.get_atlas_uv(block_id)
if not _is_opaque_at(x, y + 1, z):
_add_face_top(st, x, y, z, color)
_add_face_top(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not _is_opaque_at(x, y - 1, z):
_add_face_bottom(st, x, y, z, color)
_add_face_bottom(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not _is_opaque_at(x + 1, y, z):
_add_face_right(st, x, y, z, color)
_add_face_right(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not _is_opaque_at(x - 1, y, z):
_add_face_left(st, x, y, z, color)
_add_face_left(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not _is_opaque_at(x, y, z + 1):
_add_face_front(st, x, y, z, color)
_add_face_front(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not _is_opaque_at(x, y, z - 1):
_add_face_back(st, x, y, z, color)
_add_face_back(st, x, y, z, uv_tl, tile_w, tile_h)
has_faces = true
if not has_faces:
@@ -70,15 +85,11 @@ func generate_mesh() -> void:
st.generate_normals()
var mat: StandardMaterial3D = StandardMaterial3D.new()
mat.vertex_color_use_as_albedo = true
mat.shading_mode = BaseMaterial3D.SHADING_MODE_PER_VERTEX
st.set_material(mat)
var mesh: ArrayMesh = st.commit()
_mesh_instance = MeshInstance3D.new()
_mesh_instance.mesh = mesh
_mesh_instance.material_override = shared_material
add_child(_mesh_instance)
var shape: ConcavePolygonShape3D = ConcavePolygonShape3D.new()
@@ -96,80 +107,109 @@ func _is_opaque_at(x: int, y: int, z: int) -> bool:
return false
return BlockDatabase.is_solid(get_block(x, y, z))
func _add_face_top(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
# UV layout for a quad: TL, TR, BR, BL
# Face vertices are added as two triangles: TL-TR-BR and TL-BR-BL
func _add_face_top(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
# tri 1
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy + 1.0, fz))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
st.set_color(color)
# tri 2
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy + 1.0, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
func _add_face_bottom(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
func _add_face_bottom(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy, fz))
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy, fz))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx, fy, fz))
func _add_face_right(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
func _add_face_right(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx + 1.0, fy, fz))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx + 1.0, fy, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
func _add_face_left(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
func _add_face_left(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx, fy, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz))
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
func _add_face_front(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
func _add_face_front(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx + 1.0, fy, fz + 1.0))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz + 1.0))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz + 1.0))
func _add_face_back(st: SurfaceTool, x: int, y: int, z: int, color: Color) -> void:
func _add_face_back(st: SurfaceTool, x: int, y: int, z: int, uv_tl: Vector2, tw: float, th: float) -> void:
var fx: float = float(x)
var fy: float = float(y)
var fz: float = float(z)
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz))
st.set_uv(uv_tl + Vector2(tw, 0.0))
st.add_vertex(Vector3(fx + 1.0, fy, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
st.set_color(color)
st.set_uv(uv_tl)
st.add_vertex(Vector3(fx, fy, fz))
st.set_uv(uv_tl + Vector2(tw, th))
st.add_vertex(Vector3(fx + 1.0, fy + 1.0, fz))
st.set_uv(uv_tl + Vector2(0.0, th))
st.add_vertex(Vector3(fx, fy + 1.0, fz))