Godot 4.3中如何确保PNG图片保持原始颜色不被修改?
Godot 4.3中加载PNG时颜色失真,如何保证颜色完全一致?
问题背景
我制作了一张地图PNG,每个国家区域使用唯一的纯色(比如France = #00bbd4、Italy = #ff3131),通过Sprite2D的Texture属性加载后,原本单一颜色的区域出现了约30种相似色,导致我基于颜色匹配的地图逻辑完全失效。
我用regions.txt维护颜色与国家的对应关系:
{ "#00bbd4" : "France", "#ff3131" : "Italy", "#f1c30f" : "Spain", "#00cc00" : "Berber" }
处理图片的main.gd代码如下:
extends Node2D @onready var mapImage = $Sprite2D func _ready(): load_regions() func _process(delta): pass func load_regions(): var image = mapImage.get_texture().get_image() var pixel_color_dict = get_pixel_color_dict(image) var regions_dict = import_file("res://Map_data/regions.txt") for region_color in regions_dict: var region = load("res://Scenes/Region_Area.tscn").instantiate() region.region_name = regions_dict[region_color] region.set_name(region_color) get_node("Regions").add_child(region) var polygons = get_polygons(image, region_color, pixel_color_dict) for polygon in polygons: var region_collision = CollisionPolygon2D.new() var region_polygon = Polygon2D.new() region_collision.polygon = polygon region_polygon.polygon = polygon region.add_child(region_collision) region.add_child(region_polygon) mapImage.queue_free() func get_pixel_color_dict(image): var pixel_color_dict = {} for y in range(image.get_height()): for x in range(image.get_width()): var pixel_color = "#" + str(image.get_pixel(int(x), int(y)).to_html(false)) if pixel_color not in pixel_color_dict: pixel_color_dict[pixel_color] = [] pixel_color_dict[pixel_color].append(Vector2(x,y)) return pixel_color_dict func get_polygons(image, region_color, pixel_color_dict): var targetImage = Image.create(image.get_size().x,image.get_size().y, false, Image.FORMAT_RGBA8) for value in pixel_color_dict[region_color]: targetImage.set_pixel(value.x,value.y, "#ffffff") var bitmap = BitMap.new() bitmap.create_from_image_alpha(targetImage) var polygons = bitmap.opaque_to_polygons(Rect2(Vector2(0,0), bitmap.get_size()), 0.1) return polygons #Import JSON files and converts to lists or dictionary func import_file(filepath): var file = FileAccess.open(filepath, FileAccess.READ) if file != null: return JSON.parse_string(file.get_as_text().replace("_", " ")) else: print("Failed to open file:", filepath) return null
解决方案
1. 修改PNG的导入设置
Godot默认的纹理压缩、颜色优化是导致颜色失真的核心原因。选中你的PNG文件,在导入面板中调整以下参数:
- 压缩模式:设置为
Uncompressed(完全不压缩) - 格式:选择
RGBA8(与代码中使用的格式一致,保证每个颜色通道8位精度) - 启用mipmaps:取消勾选(mipmap生成会引入颜色模糊)
- 颜色空间:根据原始图片格式选择
sRGB或Linear,避免自动颜色空间转换 - 过滤:设置为
Nearest(禁用纹理插值采样,保证像素颜色完全一致)
设置完成后点击重新导入,让Godot应用新参数。
2. 直接加载原始图片文件(绕过纹理导入)
如果导入设置调整后仍有问题,可以直接读取原始PNG文件,完全跳过Godot的纹理优化流程:
# 替换原代码中从Sprite2D获取image的逻辑 var image = Image.load_from_file("res://path/to/your/map.png") # 确保格式统一为RGBA8 if image.get_format() != Image.FORMAT_RGBA8: image.convert(Image.FORMAT_RGBA8)
3. 颜色匹配容错处理(备选方案)
如果无法完全消除颜色偏差,可以在颜色匹配时加入容差判断,允许RGB通道小范围差值:
# 替换原get_pixel_color_dict函数,加入容差逻辑 func get_pixel_color_dict(image, tolerance: int = 1): var pixel_color_dict = {} for y in range(image.get_height()): for x in range(image.get_width()): var pixel = image.get_pixel(x, y) var rgb = [int(pixel.r * 255), int(pixel.g * 255), int(pixel.b * 255)] var matched_key = null # 遍历已有颜色,寻找容差范围内的匹配 for key in pixel_color_dict: var target_rgb = [ int(key[1:3], 16), int(key[3:5], 16), int(key[5:7], 16) ] var diff = abs(rgb[0]-target_rgb[0]) + abs(rgb[1]-target_rgb[1]) + abs(rgb[2]-target_rgb[2]) if diff <= tolerance * 3: matched_key = key break if matched_key: pixel_color_dict[matched_key].append(Vector2(x,y)) else: var pixel_color = "#" + str(pixel.to_html(false)) pixel_color_dict[pixel_color] = [Vector2(x,y)] return pixel_color_dict
内容的提问来源于stack exchange,提问作者Mike Twain




