mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
parent
bb6430d3ba
commit
6cdabf09d1
12
image.go
12
image.go
@ -587,6 +587,9 @@ var _ [len(DrawTrianglesShaderOptions{}.Images) - graphics.ShaderImageCount]stru
|
|||||||
//
|
//
|
||||||
// If a specified uniform variable's length or type doesn't match with an expected one, DrawTrianglesShader panics.
|
// If a specified uniform variable's length or type doesn't match with an expected one, DrawTrianglesShader panics.
|
||||||
//
|
//
|
||||||
|
// Even if a result is an invalid color as a premultiplied-alpha color, i.e. an alpha value exceeds other color values,
|
||||||
|
// the value is kept and is not clamped.
|
||||||
|
//
|
||||||
// When the image i is disposed, DrawTrianglesShader does nothing.
|
// When the image i is disposed, DrawTrianglesShader does nothing.
|
||||||
func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesShaderOptions) {
|
func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader *Shader, options *DrawTrianglesShaderOptions) {
|
||||||
i.copyCheck()
|
i.copyCheck()
|
||||||
@ -742,6 +745,9 @@ var _ [len(DrawRectShaderOptions{}.Images)]struct{} = [graphics.ShaderImageCount
|
|||||||
// If no source images are specified, imageSrc0Size returns a valid size only when the unit is pixels,
|
// If no source images are specified, imageSrc0Size returns a valid size only when the unit is pixels,
|
||||||
// but always returns 0 when the unit is texels (default).
|
// but always returns 0 when the unit is texels (default).
|
||||||
//
|
//
|
||||||
|
// Even if a result is an invalid color as a premultiplied-alpha color, i.e. an alpha value exceeds other color values,
|
||||||
|
// the value is kept and is not clamped.
|
||||||
|
//
|
||||||
// When the image i is disposed, DrawRectShader does nothing.
|
// When the image i is disposed, DrawRectShader does nothing.
|
||||||
func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawRectShaderOptions) {
|
func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawRectShaderOptions) {
|
||||||
i.copyCheck()
|
i.copyCheck()
|
||||||
@ -954,6 +960,9 @@ func (i *Image) at(x, y int) (r, g, b, a byte) {
|
|||||||
//
|
//
|
||||||
// Set implements the standard draw.Image's Set.
|
// Set implements the standard draw.Image's Set.
|
||||||
//
|
//
|
||||||
|
// Even if a result is an invalid color as a premultiplied-alpha color, i.e. an alpha value exceeds other color values,
|
||||||
|
// the value is kept and is not clamped.
|
||||||
|
//
|
||||||
// If the image is disposed, Set does nothing.
|
// If the image is disposed, Set does nothing.
|
||||||
func (i *Image) Set(x, y int, clr color.Color) {
|
func (i *Image) Set(x, y int, clr color.Color) {
|
||||||
i.copyCheck()
|
i.copyCheck()
|
||||||
@ -1028,6 +1037,9 @@ func (i *Image) Deallocate() {
|
|||||||
//
|
//
|
||||||
// WritePixels also works on a sub-image.
|
// WritePixels also works on a sub-image.
|
||||||
//
|
//
|
||||||
|
// Even if a result is an invalid color as a premultiplied-alpha color, i.e. an alpha value exceeds other color values,
|
||||||
|
// the value is kept and is not clamped.
|
||||||
|
//
|
||||||
// When the image is disposed, WritePixels does nothing.
|
// When the image is disposed, WritePixels does nothing.
|
||||||
func (i *Image) WritePixels(pixels []byte) {
|
func (i *Image) WritePixels(pixels []byte) {
|
||||||
i.copyCheck()
|
i.copyCheck()
|
||||||
|
@ -4582,3 +4582,44 @@ func TestImageDrawImageAfterDeallocation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #2798
|
||||||
|
func TestImageInvalidPremultipliedAlphaColor(t *testing.T) {
|
||||||
|
// This test checks the rendering result when Set and WritePixels use an invalid premultiplied alpha color.
|
||||||
|
// The result values are kept and not clamped.
|
||||||
|
|
||||||
|
const (
|
||||||
|
w = 16
|
||||||
|
h = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
dst.Set(0, 0, color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x40})
|
||||||
|
dst.Set(0, 1, color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x00})
|
||||||
|
if got, want := dst.At(0, 0).(color.RGBA), (color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x40}); got != want {
|
||||||
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
|
}
|
||||||
|
if got, want := dst.At(0, 1).(color.RGBA), (color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x00}); got != want {
|
||||||
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
pix := make([]byte, 4*w*h)
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
pix[4*(j*16+i)] = byte(i)
|
||||||
|
pix[4*(j*16+i)+1] = byte(j)
|
||||||
|
pix[4*(j*16+i)+2] = 0x80
|
||||||
|
pix[4*(j*16+i)+3] = byte(i - j)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst.WritePixels(pix)
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, j)
|
||||||
|
want := color.RGBA{R: byte(i), G: byte(j), B: 0x80, A: byte(i - j)}
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2429,3 +2429,61 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue #2798
|
||||||
|
func TestShaderInvalidPremultipliedAlphaColor(t *testing.T) {
|
||||||
|
// This test checks the rendering result when the shader returns an invalid premultiplied alpha color.
|
||||||
|
// The result values are kept and not clamped.
|
||||||
|
|
||||||
|
const w, h = 16, 16
|
||||||
|
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
s, err := ebiten.NewShader([]byte(`//kage:unit pixels
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
||||||
|
return vec4(1, 0.75, 0.5, 0.25)
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.DrawRectShader(w, h, s, nil)
|
||||||
|
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, j).(color.RGBA)
|
||||||
|
want := color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0x40}
|
||||||
|
if !sameColors(got, want, 2) {
|
||||||
|
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.Clear()
|
||||||
|
s, err = ebiten.NewShader([]byte(`//kage:unit pixels
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
||||||
|
return vec4(1, 0.75, 0.5, 0)
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.DrawRectShader(w, h, s, nil)
|
||||||
|
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, j).(color.RGBA)
|
||||||
|
want := color.RGBA{R: 0xff, G: 0xc0, B: 0x80, A: 0}
|
||||||
|
if !sameColors(got, want, 2) {
|
||||||
|
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user