71 lines
1.9 KiB
Go
71 lines
1.9 KiB
Go
|
|
//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
|
|||
|
|
}
|