Files
ngzz-mc/cmd/client/tint_gl.go

71 lines
1.9 KiB
Go
Raw Normal View History

//go:build gl
// 图集植被染色(渲染.md §4.1):
// 原版材质包的草顶/树叶纹理是灰度图,绿色来自生物群系染色表
// (textures/colormap/grass.png、foliage.png)。
// MVP:取染色表中心色(平原绿)对图集内对应纹理乘色;按群系逐顶点着色后置。
package main
import (
"image"
"image/color"
"image/draw"
"image/png"
"os"
"mc/internal/assets"
)
// applyAtlasTint 给图集内带染色标记的纹理乘上染色表中心色。
// 返回新图集图像(原地复制后修改);染色表缺失的键保持原样。
func applyAtlasTint(src image.Image, uv map[string]image.Rectangle, am *assets.Manager, tinted map[string][]string) image.Image {
b := src.Bounds()
dst := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
for tintName, keys := range tinted {
tr, tg, tb, ok := colormapCenter(am, tintName)
if !ok {
continue
}
for _, key := range keys {
rect, found := uv[key]
if !found {
continue
}
for y := rect.Min.Y; y < rect.Max.Y; y++ {
for x := rect.Min.X; x < rect.Max.X; x++ {
pr, pg, pb, pa := src.At(x, y).RGBA()
dst.SetRGBA(x, y, color.RGBA{
R: uint8(uint32(uint8(pr>>8)) * tr / 255),
G: uint8(uint32(uint8(pg>>8)) * tg / 255),
B: uint8(uint32(uint8(pb>>8)) * tb / 255),
A: uint8(pa >> 8),
})
}
}
}
}
return dst
}
// colormapCenter 读取染色表中心像素(0–255)。
func colormapCenter(am *assets.Manager, name string) (r, g, b uint32, ok bool) {
p, found := am.ResolveTexture("colormap/" + name)
if !found {
return 0, 0, 0, false
}
f, err := os.Open(p)
if err != nil {
return 0, 0, 0, false
}
defer f.Close()
img, err := png.Decode(f)
if err != nil {
return 0, 0, 0, false
}
cb := img.Bounds()
r, g, b, _ = img.At(cb.Min.X+cb.Dx()/2, cb.Min.Y+cb.Dy()/2).RGBA()
return r >> 8, g >> 8, b >> 8, true
}