mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
Bug fix: Consider color.Color.RGBA returns alpha-premultiplied values
This commit is contained in:
parent
d34c94aa09
commit
99434fa9d3
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package ebiten
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
@ -81,28 +80,26 @@ func Monochrome() ColorMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
// ScaleColor returns a color matrix that scales a color matrix by clr.
|
||||
func ScaleColor(clr color.Color) ColorMatrix {
|
||||
rf, gf, bf, af := rgba(clr)
|
||||
// ScaleColor returns a color matrix that scales a color matrix by the given color (r, g, b, a).
|
||||
func ScaleColor(r, g, b, a float64) ColorMatrix {
|
||||
return ColorMatrix{
|
||||
[ColorMatrixDim - 1][ColorMatrixDim]float64{
|
||||
{rf, 0, 0, 0, 0},
|
||||
{0, gf, 0, 0, 0},
|
||||
{0, 0, bf, 0, 0},
|
||||
{0, 0, 0, af, 0},
|
||||
{r, 0, 0, 0, 0},
|
||||
{0, g, 0, 0, 0},
|
||||
{0, 0, b, 0, 0},
|
||||
{0, 0, 0, a, 0},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TranslateColor returns a color matrix that translates a color matrix by clr.
|
||||
func TranslateColor(clr color.Color) ColorMatrix {
|
||||
rf, gf, bf, af := rgba(clr)
|
||||
// TranslateColor returns a color matrix that translates a color matrix by the given color (r, g, b, a).
|
||||
func TranslateColor(r, g, b, a float64) ColorMatrix {
|
||||
return ColorMatrix{
|
||||
[ColorMatrixDim - 1][ColorMatrixDim]float64{
|
||||
{1, 0, 0, 0, rf},
|
||||
{0, 1, 0, 0, gf},
|
||||
{0, 0, 1, 0, bf},
|
||||
{0, 0, 0, 1, af},
|
||||
{1, 0, 0, 0, r},
|
||||
{0, 1, 0, 0, g},
|
||||
{0, 0, 1, 0, b},
|
||||
{0, 0, 0, 1, a},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -123,11 +120,11 @@ func RotateHue(theta float64) ColorMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
func rgba(clr color.Color) (float64, float64, float64, float64) {
|
||||
r, g, b, a := clr.RGBA()
|
||||
rf := float64(r) / float64(math.MaxUint16)
|
||||
gf := float64(g) / float64(math.MaxUint16)
|
||||
bf := float64(b) / float64(math.MaxUint16)
|
||||
af := float64(a) / float64(math.MaxUint16)
|
||||
func rgba(r, g, b, a uint8) (float64, float64, float64, float64) {
|
||||
const max = math.MaxUint8
|
||||
rf := float64(r) / max
|
||||
gf := float64(g) / max
|
||||
bf := float64(b) / max
|
||||
af := float64(a) / max
|
||||
return rf, gf, bf, af
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package ebitenutil
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/internal"
|
||||
"github.com/hajimehoshi/ebiten/internal/assets"
|
||||
"image/color"
|
||||
)
|
||||
@ -34,7 +35,7 @@ func DebugPrint(r *ebiten.RenderTarget, str string) {
|
||||
defaultDebugPrintState.DebugPrint(r, str)
|
||||
}
|
||||
|
||||
func (d *debugPrintState) drawText(r *ebiten.RenderTarget, str string, x, y int, clr color.Color) {
|
||||
func (d *debugPrintState) drawText(rt *ebiten.RenderTarget, str string, x, y int, c color.Color) {
|
||||
parts := []ebiten.ImagePart{}
|
||||
locationX, locationY := 0, 0
|
||||
for _, c := range str {
|
||||
@ -53,11 +54,10 @@ func (d *debugPrintState) drawText(r *ebiten.RenderTarget, str string, x, y int,
|
||||
})
|
||||
locationX += assets.TextImageCharWidth
|
||||
}
|
||||
geom := ebiten.GeometryMatrixI()
|
||||
geom.Concat(ebiten.TranslateGeometry(float64(x)+1, float64(y)))
|
||||
clrm := ebiten.ColorMatrixI()
|
||||
clrm.Concat(ebiten.ScaleColor(clr))
|
||||
r.DrawImage(d.textTexture, parts, geom, clrm)
|
||||
geo := ebiten.TranslateGeometry(float64(x)+1, float64(y))
|
||||
r, g, b, a := internal.RGBA(c)
|
||||
clr := ebiten.ScaleColor(r, g, b, a)
|
||||
rt.DrawImage(d.textTexture, parts, geo, clr)
|
||||
}
|
||||
|
||||
func (d *debugPrintState) DebugPrint(r *ebiten.RenderTarget, str string) {
|
||||
@ -79,6 +79,6 @@ func (d *debugPrintState) DebugPrint(r *ebiten.RenderTarget, str string) {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
d.drawText(r, str, 1, d.y+1, &color.RGBA{0x00, 0x00, 0x00, 0x80})
|
||||
d.drawText(r, str, 0, d.y, &color.RGBA{0xff, 0xff, 0xff, 0xff})
|
||||
d.drawText(r, str, 1, d.y+1, color.NRGBA{0x00, 0x00, 0x00, 0x80})
|
||||
d.drawText(r, str, 0, d.y, color.NRGBA{0xff, 0xff, 0xff, 0xff})
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ func (g *Game) Update(r *ebiten.RenderTarget) error {
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
geo := ebiten.TranslateGeometry(15+float64(i)*(diff), 20)
|
||||
clr := ebiten.ScaleColor(color.RGBA{0xff, 0xff, 0xff, 0x80})
|
||||
clr := ebiten.ScaleColor(1.0, 1.0, 1.0, 0.5)
|
||||
if err := ebiten.DrawWholeImage(g.tmpRenderTarget, g.ebitenImage, geo, clr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
r.Fill(color.RGBA{0x00, 0x00, 0x80, 0xff})
|
||||
r.Fill(color.NRGBA{0x00, 0x00, 0x80, 0xff})
|
||||
for i := 0; i < 10; i++ {
|
||||
geo := ebiten.TranslateGeometry(0, float64(i)*(diff))
|
||||
clr := ebiten.ColorMatrixI()
|
||||
|
@ -19,6 +19,7 @@ package blocks
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -32,7 +33,7 @@ func textWidth(str string) int {
|
||||
return charWidth * len(str)
|
||||
}
|
||||
|
||||
func drawText(r *ebiten.RenderTarget, images *Images, str string, ox, oy, scale int, clr color.Color) {
|
||||
func drawText(rt *ebiten.RenderTarget, images *Images, str string, ox, oy, scale int, c color.Color) {
|
||||
fontImageId := images.GetImage("font")
|
||||
parts := []ebiten.ImagePart{}
|
||||
|
||||
@ -53,13 +54,19 @@ func drawText(r *ebiten.RenderTarget, images *Images, str string, ox, oy, scale
|
||||
locationX += charWidth
|
||||
}
|
||||
|
||||
geoMat := ebiten.ScaleGeometry(float64(scale), float64(scale))
|
||||
geoMat.Concat(ebiten.TranslateGeometry(float64(ox), float64(oy)))
|
||||
clrMat := ebiten.ScaleColor(clr)
|
||||
r.DrawImage(fontImageId, parts, geoMat, clrMat)
|
||||
geo := ebiten.ScaleGeometry(float64(scale), float64(scale))
|
||||
geo.Concat(ebiten.TranslateGeometry(float64(ox), float64(oy)))
|
||||
c2 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
|
||||
const max = math.MaxUint16
|
||||
r := float64(c2.R) / max
|
||||
g := float64(c2.G) / max
|
||||
b := float64(c2.B) / max
|
||||
a := float64(c2.A) / max
|
||||
clr := ebiten.ScaleColor(r, g, b, a)
|
||||
rt.DrawImage(fontImageId, parts, geo, clr)
|
||||
}
|
||||
|
||||
func drawTextWithShadow(r *ebiten.RenderTarget, images *Images, str string, x, y, scale int, clr color.Color) {
|
||||
drawText(r, images, str, x+1, y+1, scale, color.RGBA{0, 0, 0, 0x80})
|
||||
drawText(r, images, str, x, y, scale, clr)
|
||||
func drawTextWithShadow(rt *ebiten.RenderTarget, images *Images, str string, x, y, scale int, clr color.Color) {
|
||||
drawText(rt, images, str, x+1, y+1, scale, color.NRGBA{0, 0, 0, 0x80})
|
||||
drawText(rt, images, str, x, y, scale, clr)
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ func (s *GameScene) Draw(r *ebiten.RenderTarget, images *Images) {
|
||||
w, h := field.Size()
|
||||
geoMat := ebiten.ScaleGeometry(float64(fieldWidth)/float64(w), float64(fieldHeight)/float64(h))
|
||||
geoMat.Concat(ebiten.TranslateGeometry(20, 20)) // TODO: magic number?
|
||||
colorMat := ebiten.ScaleColor(color.RGBA{0, 0, 0, 0x80})
|
||||
colorMat := ebiten.ScaleColor(0.0, 0.0, 0.0, 0.5)
|
||||
ebiten.DrawWholeImage(r, field, geoMat, colorMat)
|
||||
|
||||
geoMat = ebiten.GeometryMatrixI()
|
||||
|
@ -47,7 +47,7 @@ func (s *TitleScene) Draw(r *ebiten.RenderTarget, images *Images) {
|
||||
message := "PRESS SPACE TO START"
|
||||
x := (ScreenWidth - textWidth(message)) / 2
|
||||
y := ScreenHeight - 48
|
||||
drawTextWithShadow(r, images, message, x, y, 1, color.RGBA{0x80, 0, 0, 0xff})
|
||||
drawTextWithShadow(r, images, message, x, y, 1, color.NRGBA{0x80, 0, 0, 0xff})
|
||||
}
|
||||
|
||||
func drawTitleBackground(r *ebiten.RenderTarget, images *Images, c int) {
|
||||
@ -78,5 +78,5 @@ func drawLogo(r *ebiten.RenderTarget, images *Images, str string) {
|
||||
textWidth := textWidth(str) * scale
|
||||
x := (ScreenWidth - textWidth) / 2
|
||||
y := 32
|
||||
drawTextWithShadow(r, images, str, x, y, scale, color.RGBA{0x00, 0x00, 0x80, 0xff})
|
||||
drawTextWithShadow(r, images, str, x, y, scale, color.NRGBA{0x00, 0x00, 0x80, 0xff})
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func (g *Game) Update(r *ebiten.RenderTarget) error {
|
||||
|
||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||
geo := ebiten.TranslateGeometry(float64(mx), float64(my))
|
||||
clr := ebiten.ScaleColor(color.RGBA{0xff, 0x40, 0x40, 0xff})
|
||||
clr := ebiten.ScaleColor(1.0, 0.25, 0.25, 1.0)
|
||||
theta := 2.0 * math.Pi * float64(g.count%60) / 60.0
|
||||
clr.Concat(ebiten.RotateHue(theta))
|
||||
ebiten.DrawWholeImage(g.canvasRenderTarget, g.brushRenderTarget.Image(), geo, clr)
|
||||
|
@ -53,6 +53,7 @@ const (
|
||||
)
|
||||
|
||||
// An Image represents an image to be rendered.
|
||||
// An image's pixels are stored as non alpha-premultiplied.
|
||||
type Image struct {
|
||||
glTexture *opengl.Texture
|
||||
}
|
||||
|
@ -16,6 +16,11 @@ limitations under the License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
func NextPowerOf2(x uint64) uint64 {
|
||||
x -= 1
|
||||
x |= (x >> 1)
|
||||
@ -30,3 +35,13 @@ func NextPowerOf2(x uint64) uint64 {
|
||||
func NextPowerOf2Int(size int) int {
|
||||
return int(NextPowerOf2(uint64(size)))
|
||||
}
|
||||
|
||||
func RGBA(clr color.Color) (r, g, b, a float64) {
|
||||
clr2 := color.NRGBA64Model.Convert(clr).(color.NRGBA64)
|
||||
const max = math.MaxUint16
|
||||
r = float64(clr2.R) / max
|
||||
g = float64(clr2.G) / max
|
||||
b = float64(clr2.B) / max
|
||||
a = float64(clr2.A) / max
|
||||
return
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ void main(void) {
|
||||
color0 = (color_matrix * color0) + color_matrix_translation;
|
||||
|
||||
// Photoshop-like RGBA blending
|
||||
gl_FragColor.a = color0.a + color1.a - color0.a * color1.a;
|
||||
gl_FragColor.a = color0.a + (1.0 - color0.a) * color1.a;
|
||||
gl_FragColor.rgb = (color0.a * color0.rgb + (1.0 - color0.a) * color1.a * color1.rgb) / gl_FragColor.a;
|
||||
}
|
||||
`,
|
||||
|
@ -22,7 +22,6 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||
"github.com/hajimehoshi/ebiten/internal/opengl/internal/shader"
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
type innerRenderTarget struct {
|
||||
@ -50,20 +49,15 @@ func (r *innerRenderTarget) size() (width, height int) {
|
||||
}
|
||||
|
||||
func (r *innerRenderTarget) Clear() error {
|
||||
return r.Fill(color.RGBA{0, 0, 0, 0})
|
||||
return r.Fill(color.Transparent)
|
||||
}
|
||||
|
||||
func (r *innerRenderTarget) Fill(clr color.Color) error {
|
||||
if err := r.glRenderTarget.SetAsViewport(); err != nil {
|
||||
return err
|
||||
}
|
||||
const max = math.MaxUint16
|
||||
cr, cg, cb, ca := clr.RGBA()
|
||||
rf := gl.GLclampf(float64(cr) / max)
|
||||
gf := gl.GLclampf(float64(cg) / max)
|
||||
bf := gl.GLclampf(float64(cb) / max)
|
||||
af := gl.GLclampf(float64(ca) / max)
|
||||
gl.ClearColor(rf, gf, bf, af)
|
||||
rf, gf, bf, af := internal.RGBA(clr)
|
||||
gl.ClearColor(gl.GLclampf(rf), gl.GLclampf(gf), gl.GLclampf(bf), gl.GLclampf(af))
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user