mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
parent
7018e7dfb1
commit
567e2fa04c
18
blend.go
18
blend.go
@ -200,6 +200,20 @@ const (
|
|||||||
// c_out = (BlendFactorDestinationRGB) × c_dst - (BlendFactorSourceRGB) × c_src
|
// c_out = (BlendFactorDestinationRGB) × c_dst - (BlendFactorSourceRGB) × c_src
|
||||||
// α_out = (BlendFactorDestinationAlpha) × α_dst - (BlendFactorSourceAlpha) × α_src
|
// α_out = (BlendFactorDestinationAlpha) × α_dst - (BlendFactorSourceAlpha) × α_src
|
||||||
BlendOperationReverseSubtract
|
BlendOperationReverseSubtract
|
||||||
|
|
||||||
|
// BlendOperationMin represents a minimum function for the source and destination color.
|
||||||
|
// If BlendOperationMin is specified, blend factors are not used.
|
||||||
|
//
|
||||||
|
// c_out = min(c_dst, c_src)
|
||||||
|
// α_out = min(α_dst, α_src)
|
||||||
|
BlendOperationMin
|
||||||
|
|
||||||
|
// BlendOperationMax represents a maximum function for the source and destination color.
|
||||||
|
// If BlendOperationMax is specified, blend factors are not used.
|
||||||
|
//
|
||||||
|
// c_out = max(c_dst, c_src)
|
||||||
|
// α_out = max(α_dst, α_src)
|
||||||
|
BlendOperationMax
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b BlendOperation) internalBlendOperation() graphicsdriver.BlendOperation {
|
func (b BlendOperation) internalBlendOperation() graphicsdriver.BlendOperation {
|
||||||
@ -210,6 +224,10 @@ func (b BlendOperation) internalBlendOperation() graphicsdriver.BlendOperation {
|
|||||||
return graphicsdriver.BlendOperationSubtract
|
return graphicsdriver.BlendOperationSubtract
|
||||||
case BlendOperationReverseSubtract:
|
case BlendOperationReverseSubtract:
|
||||||
return graphicsdriver.BlendOperationReverseSubtract
|
return graphicsdriver.BlendOperationReverseSubtract
|
||||||
|
case BlendOperationMin:
|
||||||
|
return graphicsdriver.BlendOperationMin
|
||||||
|
case BlendOperationMax:
|
||||||
|
return graphicsdriver.BlendOperationMax
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("ebiten: invalid blend operation: %d", b))
|
panic(fmt.Sprintf("ebiten: invalid blend operation: %d", b))
|
||||||
}
|
}
|
||||||
|
@ -335,13 +335,26 @@ func TestImageDispose(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func min(a, b int) int {
|
type ordered interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Use the built-in function min from Go 1.21.
|
||||||
|
func min[T ordered](a, b T) T {
|
||||||
if a < b {
|
if a < b {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Use the built-in function max from Go 1.21.
|
||||||
|
func max[T ordered](a, b T) T {
|
||||||
|
if a < b {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
func TestImageBlendLighter(t *testing.T) {
|
func TestImageBlendLighter(t *testing.T) {
|
||||||
img0, _, err := openEbitenImage()
|
img0, _, err := openEbitenImage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -3687,6 +3700,87 @@ func TestImageBlendOperation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImageBlendOperationMinAndMax(t *testing.T) {
|
||||||
|
const w, h = 16, 1
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
src := ebiten.NewImage(w, h)
|
||||||
|
|
||||||
|
dstColor := func(i int) (byte, byte, byte, byte) {
|
||||||
|
return byte(4 * i * 17), byte(4*i*17 + 1), byte(4*i*17 + 2), byte(4*i*17 + 3)
|
||||||
|
}
|
||||||
|
srcColor := func(i int) (byte, byte, byte, byte) {
|
||||||
|
return byte(4 * i * 13), byte(4*i*13 + 1), byte(4*i*13 + 2), byte(4*i*13 + 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
dstPix := make([]byte, 4*w*h)
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
r, g, b, a := dstColor(i)
|
||||||
|
dstPix[4*i] = r
|
||||||
|
dstPix[4*i+1] = g
|
||||||
|
dstPix[4*i+2] = b
|
||||||
|
dstPix[4*i+3] = a
|
||||||
|
}
|
||||||
|
srcPix := make([]byte, 4*w*h)
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
r, g, b, a := srcColor(i)
|
||||||
|
srcPix[4*i] = r
|
||||||
|
srcPix[4*i+1] = g
|
||||||
|
srcPix[4*i+2] = b
|
||||||
|
srcPix[4*i+3] = a
|
||||||
|
}
|
||||||
|
src.WritePixels(srcPix)
|
||||||
|
|
||||||
|
operations := []ebiten.BlendOperation{
|
||||||
|
ebiten.BlendOperationMin,
|
||||||
|
ebiten.BlendOperationMax,
|
||||||
|
}
|
||||||
|
for _, rgbOp := range operations {
|
||||||
|
for _, alphaOp := range operations {
|
||||||
|
// Reset the destination state.
|
||||||
|
dst.WritePixels(dstPix)
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
// Use the default blend factors, and confirm that the factors are ignored.
|
||||||
|
op.Blend = ebiten.Blend{
|
||||||
|
BlendFactorSourceRGB: ebiten.BlendFactorDefault,
|
||||||
|
BlendFactorSourceAlpha: ebiten.BlendFactorDefault,
|
||||||
|
BlendFactorDestinationRGB: ebiten.BlendFactorDefault,
|
||||||
|
BlendFactorDestinationAlpha: ebiten.BlendFactorDefault,
|
||||||
|
BlendOperationRGB: rgbOp,
|
||||||
|
BlendOperationAlpha: alphaOp,
|
||||||
|
}
|
||||||
|
dst.DrawImage(src, op)
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, 0).(color.RGBA)
|
||||||
|
|
||||||
|
sr, sg, sb, sa := srcColor(i)
|
||||||
|
dr, dg, db, da := dstColor(i)
|
||||||
|
|
||||||
|
var want color.RGBA
|
||||||
|
switch rgbOp {
|
||||||
|
case ebiten.BlendOperationMin:
|
||||||
|
want.R = min(sr, dr)
|
||||||
|
want.G = min(sg, dg)
|
||||||
|
want.B = min(sb, db)
|
||||||
|
case ebiten.BlendOperationMax:
|
||||||
|
want.R = max(sr, dr)
|
||||||
|
want.G = max(sg, dg)
|
||||||
|
want.B = max(sb, db)
|
||||||
|
}
|
||||||
|
switch alphaOp {
|
||||||
|
case ebiten.BlendOperationMin:
|
||||||
|
want.A = min(sa, da)
|
||||||
|
case ebiten.BlendOperationMax:
|
||||||
|
want.A = max(sa, da)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sameColors(got, want, 1) {
|
||||||
|
t.Errorf("dst.At(%d, 0): operations: %d, %d: got: %v, want: %v", i, rgbOp, alphaOp, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestImageBlendFactor(t *testing.T) {
|
func TestImageBlendFactor(t *testing.T) {
|
||||||
if skipTooSlowTests(t) {
|
if skipTooSlowTests(t) {
|
||||||
return
|
return
|
||||||
|
@ -45,6 +45,8 @@ const (
|
|||||||
BlendOperationAdd BlendOperation = iota
|
BlendOperationAdd BlendOperation = iota
|
||||||
BlendOperationSubtract
|
BlendOperationSubtract
|
||||||
BlendOperationReverseSubtract
|
BlendOperationReverseSubtract
|
||||||
|
BlendOperationMin
|
||||||
|
BlendOperationMax
|
||||||
)
|
)
|
||||||
|
|
||||||
var BlendSourceOver = Blend{
|
var BlendSourceOver = Blend{
|
||||||
|
@ -106,6 +106,10 @@ func blendOperationToBlendOp11(o graphicsdriver.BlendOperation) _D3D11_BLEND_OP
|
|||||||
return _D3D11_BLEND_OP_SUBTRACT
|
return _D3D11_BLEND_OP_SUBTRACT
|
||||||
case graphicsdriver.BlendOperationReverseSubtract:
|
case graphicsdriver.BlendOperationReverseSubtract:
|
||||||
return _D3D11_BLEND_OP_REV_SUBTRACT
|
return _D3D11_BLEND_OP_REV_SUBTRACT
|
||||||
|
case graphicsdriver.BlendOperationMin:
|
||||||
|
return _D3D11_BLEND_OP_MIN
|
||||||
|
case graphicsdriver.BlendOperationMax:
|
||||||
|
return _D3D11_BLEND_OP_MAX
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,10 @@ func blendOperationToBlendOp12(o graphicsdriver.BlendOperation) _D3D12_BLEND_OP
|
|||||||
return _D3D12_BLEND_OP_SUBTRACT
|
return _D3D12_BLEND_OP_SUBTRACT
|
||||||
case graphicsdriver.BlendOperationReverseSubtract:
|
case graphicsdriver.BlendOperationReverseSubtract:
|
||||||
return _D3D12_BLEND_OP_REV_SUBTRACT
|
return _D3D12_BLEND_OP_REV_SUBTRACT
|
||||||
|
case graphicsdriver.BlendOperationMin:
|
||||||
|
return _D3D12_BLEND_OP_MIN
|
||||||
|
case graphicsdriver.BlendOperationMax:
|
||||||
|
return _D3D12_BLEND_OP_MAX
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
panic(fmt.Sprintf("directx: invalid blend operation: %d", o))
|
||||||
}
|
}
|
||||||
|
@ -381,6 +381,10 @@ func blendOperationToMetalBlendOperation(o graphicsdriver.BlendOperation) mtl.Bl
|
|||||||
return mtl.BlendOperationSubtract
|
return mtl.BlendOperationSubtract
|
||||||
case graphicsdriver.BlendOperationReverseSubtract:
|
case graphicsdriver.BlendOperationReverseSubtract:
|
||||||
return mtl.BlendOperationReverseSubtract
|
return mtl.BlendOperationReverseSubtract
|
||||||
|
case graphicsdriver.BlendOperationMin:
|
||||||
|
return mtl.BlendOperationMin
|
||||||
|
case graphicsdriver.BlendOperationMax:
|
||||||
|
return mtl.BlendOperationMax
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("metal: invalid blend operation: %d", o))
|
panic(fmt.Sprintf("metal: invalid blend operation: %d", o))
|
||||||
}
|
}
|
||||||
|
@ -67,6 +67,10 @@ func convertBlendOperation(o graphicsdriver.BlendOperation) blendOperation {
|
|||||||
return gl.FUNC_SUBTRACT
|
return gl.FUNC_SUBTRACT
|
||||||
case graphicsdriver.BlendOperationReverseSubtract:
|
case graphicsdriver.BlendOperationReverseSubtract:
|
||||||
return gl.FUNC_REVERSE_SUBTRACT
|
return gl.FUNC_REVERSE_SUBTRACT
|
||||||
|
case graphicsdriver.BlendOperationMin:
|
||||||
|
return gl.MIN
|
||||||
|
case graphicsdriver.BlendOperationMax:
|
||||||
|
return gl.MAX
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("opengl: invalid blend operation %d", o))
|
panic(fmt.Sprintf("opengl: invalid blend operation %d", o))
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,9 @@ const (
|
|||||||
INVERT = 0x150A
|
INVERT = 0x150A
|
||||||
KEEP = 0x1E00
|
KEEP = 0x1E00
|
||||||
LINK_STATUS = 0x8B82
|
LINK_STATUS = 0x8B82
|
||||||
|
MAX = 0x8008
|
||||||
MAX_TEXTURE_SIZE = 0x0D33
|
MAX_TEXTURE_SIZE = 0x0D33
|
||||||
|
MIN = 0x8007
|
||||||
NEAREST = 0x2600
|
NEAREST = 0x2600
|
||||||
NO_ERROR = 0
|
NO_ERROR = 0
|
||||||
NOTEQUAL = 0x0205
|
NOTEQUAL = 0x0205
|
||||||
|
Loading…
Reference in New Issue
Block a user