You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
2.3 KiB
69 lines
2.3 KiB
public partial class ReplacePalette : Node3D |
|
{ |
|
readonly struct TextureInfo(float min, float max) |
|
{ |
|
public float MinBrightness { get; } = min; |
|
public float MaxBrightness { get; } = max; |
|
} |
|
|
|
static Shader _paletteShader; |
|
static Dictionary<Texture2D, TextureInfo> _textureCache = []; |
|
|
|
[Export] public Texture2D Palette { get; set; } |
|
|
|
public override void _Ready() |
|
{ |
|
_paletteShader ??= Load<Shader>("res://assets/shaders/palette_swap.gdshader"); |
|
ReplaceShaderRecursive(this, Palette); |
|
} |
|
|
|
static void ReplaceShaderRecursive(Node node, Texture2D palette) |
|
{ |
|
if (node is MeshInstance3D mesh) { |
|
var oldMaterial = (StandardMaterial3D)mesh.Mesh.SurfaceGetMaterial(0); |
|
var texture = oldMaterial.AlbedoTexture; |
|
var info = GetOrCreateTextureInfo(texture); |
|
|
|
var material = new ShaderMaterial { Shader = _paletteShader }; |
|
material.SetShaderParameter("palette", palette); |
|
material.SetShaderParameter("albedo_texture", texture); |
|
material.SetShaderParameter("min_brightness", info.MinBrightness); |
|
material.SetShaderParameter("max_brightness", info.MaxBrightness); |
|
mesh.MaterialOverride = material; |
|
} |
|
|
|
foreach (var child in node.GetChildren()) |
|
ReplaceShaderRecursive(child, palette); |
|
} |
|
|
|
static TextureInfo GetOrCreateTextureInfo(Texture2D texture) |
|
{ |
|
if (!_textureCache.TryGetValue(texture, out var info)) { |
|
var minBrightness = 1.0f; |
|
var maxBrightness = 0.0f; |
|
|
|
var image = texture.GetImage(); |
|
image.Convert(Image.Format.Rgba8); |
|
var data = image.GetData().AsSpan(); |
|
for (var i = 0; i < data.Length; i += 4) { |
|
var rgba = data.Slice(i, 4); |
|
if (rgba[3] <= byte.MaxValue / 2) continue; |
|
var brightness = Max(rgba[0], Max(rgba[1], rgba[2])) / (float)byte.MaxValue; |
|
minBrightness = Min(minBrightness, brightness); |
|
maxBrightness = Max(maxBrightness, brightness); |
|
} |
|
// for (var x = 0; x < image.GetWidth(); x++) |
|
// for (var y = 0; y < image.GetHeight(); y++) { |
|
// var color = image.GetPixel(x, y); |
|
// // var brightness = Max(color.R, Max(color.G, color.B)); |
|
// color.ToHsv(out _, out _, out var brightness); |
|
// minBrightness = Min(minBrightness, brightness); |
|
// maxBrightness = Max(maxBrightness, brightness); |
|
// } |
|
|
|
info = new(minBrightness, maxBrightness); |
|
_textureCache.Add(texture, info); |
|
} |
|
return info; |
|
} |
|
}
|
|
|