mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
parent
d2a99afa44
commit
da5f5ea327
63
blend.go
63
blend.go
@ -77,13 +77,58 @@ const (
|
||||
// BlendFactorDefault is the default factor value.
|
||||
// The actual value depends on which source or destination this value is used.
|
||||
BlendFactorDefault BlendFactor = iota
|
||||
|
||||
// BlendFactorZero is a factor:
|
||||
//
|
||||
// 0
|
||||
BlendFactorZero
|
||||
|
||||
// BlendFactorOne is a factor:
|
||||
//
|
||||
// 1
|
||||
BlendFactorOne
|
||||
|
||||
// BlendFactorSourceColor is a factor:
|
||||
//
|
||||
// (source RGBA)
|
||||
BlendFactorSourceColor
|
||||
|
||||
// BlendFactorOneMinusSourceColor is a factor:
|
||||
//
|
||||
// 1 - (source color)
|
||||
BlendFactorOneMinusSourceColor
|
||||
|
||||
// BlendFactorSourceAlpha is a factor:
|
||||
//
|
||||
// (source alpha)
|
||||
BlendFactorSourceAlpha
|
||||
BlendFactorDestinationAlpha
|
||||
|
||||
// BlendFactorOneMinusSourceAlpha is a factor:
|
||||
//
|
||||
// 1 - (source alpha)
|
||||
BlendFactorOneMinusSourceAlpha
|
||||
BlendFactorOneMinusDestinationAlpha
|
||||
|
||||
// BlendFactorDestinationColor is a factor:
|
||||
//
|
||||
// (destination RGBA)
|
||||
BlendFactorDestinationColor
|
||||
|
||||
// BlendFactorOneMinusDestinationColor is a factor:
|
||||
//
|
||||
// 1 - (destination RGBA)
|
||||
BlendFactorOneMinusDestinationColor
|
||||
|
||||
// BlendFactorDestinationAlpha is a factor:
|
||||
//
|
||||
// (destination alpha)
|
||||
BlendFactorDestinationAlpha
|
||||
|
||||
// BlendFactorOneMinusDestinationAlpha is a factor:
|
||||
//
|
||||
// 1 - (destination alpha)
|
||||
BlendFactorOneMinusDestinationAlpha
|
||||
|
||||
// TODO: Add BlendFactorSourceAlphaSaturated. This might not work well on some platforms like Steam SDK (#2382).
|
||||
)
|
||||
|
||||
func (b BlendFactor) internalBlendFactor(source bool) graphicsdriver.BlendFactor {
|
||||
@ -98,16 +143,22 @@ func (b BlendFactor) internalBlendFactor(source bool) graphicsdriver.BlendFactor
|
||||
return graphicsdriver.BlendFactorZero
|
||||
case BlendFactorOne:
|
||||
return graphicsdriver.BlendFactorOne
|
||||
case BlendFactorSourceColor:
|
||||
return graphicsdriver.BlendFactorSourceColor
|
||||
case BlendFactorOneMinusSourceColor:
|
||||
return graphicsdriver.BlendFactorOneMinusSourceColor
|
||||
case BlendFactorSourceAlpha:
|
||||
return graphicsdriver.BlendFactorSourceAlpha
|
||||
case BlendFactorDestinationAlpha:
|
||||
return graphicsdriver.BlendFactorDestinationAlpha
|
||||
case BlendFactorOneMinusSourceAlpha:
|
||||
return graphicsdriver.BlendFactorOneMinusSourceAlpha
|
||||
case BlendFactorOneMinusDestinationAlpha:
|
||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha
|
||||
case BlendFactorDestinationColor:
|
||||
return graphicsdriver.BlendFactorDestinationColor
|
||||
case BlendFactorOneMinusDestinationColor:
|
||||
return graphicsdriver.BlendFactorOneMinusDestinationColor
|
||||
case BlendFactorDestinationAlpha:
|
||||
return graphicsdriver.BlendFactorDestinationAlpha
|
||||
case BlendFactorOneMinusDestinationAlpha:
|
||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha
|
||||
default:
|
||||
panic(fmt.Sprintf("ebiten: invalid blend factor: %d", b))
|
||||
}
|
||||
|
208
image_test.go
208
image_test.go
@ -3647,3 +3647,211 @@ func TestImageBlendOperation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageBlendFactor(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)
|
||||
}
|
||||
colorToFloats := func(r, g, b, a byte) (float64, float64, float64, float64) {
|
||||
return float64(r) / 0xff, float64(g) / 0xff, float64(b) / 0xff, float64(a) / 0xff
|
||||
}
|
||||
clamp := func(x int) byte {
|
||||
if x > 255 {
|
||||
return 255
|
||||
}
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
return byte(x)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
factors := []ebiten.BlendFactor{
|
||||
ebiten.BlendFactorZero,
|
||||
ebiten.BlendFactorOne,
|
||||
ebiten.BlendFactorSourceColor,
|
||||
ebiten.BlendFactorOneMinusSourceColor,
|
||||
ebiten.BlendFactorSourceAlpha,
|
||||
ebiten.BlendFactorOneMinusSourceAlpha,
|
||||
ebiten.BlendFactorDestinationColor,
|
||||
ebiten.BlendFactorOneMinusDestinationColor,
|
||||
ebiten.BlendFactorDestinationAlpha,
|
||||
ebiten.BlendFactorOneMinusDestinationAlpha,
|
||||
}
|
||||
for _, srcRGBFactor := range factors {
|
||||
for _, srcAlphaFactor := range factors {
|
||||
for _, dstRGBFactor := range factors {
|
||||
for _, dstAlphaFactor := range factors {
|
||||
// Reset the destination state.
|
||||
dst.WritePixels(dstPix)
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.Blend = ebiten.Blend{
|
||||
BlendFactorSourceRGB: srcRGBFactor,
|
||||
BlendFactorSourceAlpha: srcAlphaFactor,
|
||||
BlendFactorDestinationRGB: dstRGBFactor,
|
||||
BlendFactorDestinationAlpha: dstAlphaFactor,
|
||||
BlendOperationRGB: ebiten.BlendOperationAdd,
|
||||
BlendOperationAlpha: ebiten.BlendOperationAdd,
|
||||
}
|
||||
dst.DrawImage(src, op)
|
||||
for i := 0; i < w; i++ {
|
||||
got := dst.At(i, 0).(color.RGBA)
|
||||
|
||||
sr, sg, sb, sa := colorToFloats(srcColor(i))
|
||||
dr, dg, db, da := colorToFloats(dstColor(i))
|
||||
|
||||
var r, g, b, a float64
|
||||
|
||||
switch srcRGBFactor {
|
||||
case ebiten.BlendFactorZero:
|
||||
r += 0 * sr
|
||||
g += 0 * sg
|
||||
b += 0 * sb
|
||||
case ebiten.BlendFactorOne:
|
||||
r += 1 * sr
|
||||
g += 1 * sg
|
||||
b += 1 * sb
|
||||
case ebiten.BlendFactorSourceColor:
|
||||
r += sr * sr
|
||||
g += sg * sg
|
||||
b += sb * sb
|
||||
case ebiten.BlendFactorOneMinusSourceColor:
|
||||
r += (1 - sr) * sr
|
||||
g += (1 - sg) * sg
|
||||
b += (1 - sb) * sb
|
||||
case ebiten.BlendFactorSourceAlpha:
|
||||
r += sa * sr
|
||||
g += sa * sg
|
||||
b += sa * sb
|
||||
case ebiten.BlendFactorOneMinusSourceAlpha:
|
||||
r += (1 - sa) * sr
|
||||
g += (1 - sa) * sg
|
||||
b += (1 - sa) * sb
|
||||
case ebiten.BlendFactorDestinationColor:
|
||||
r += dr * sr
|
||||
g += dg * sg
|
||||
b += db * sb
|
||||
case ebiten.BlendFactorOneMinusDestinationColor:
|
||||
r += (1 - dr) * sr
|
||||
g += (1 - dg) * sg
|
||||
b += (1 - db) * sb
|
||||
case ebiten.BlendFactorDestinationAlpha:
|
||||
r += da * sr
|
||||
g += da * sg
|
||||
b += da * sb
|
||||
case ebiten.BlendFactorOneMinusDestinationAlpha:
|
||||
r += (1 - da) * sr
|
||||
g += (1 - da) * sg
|
||||
b += (1 - da) * sb
|
||||
}
|
||||
switch srcAlphaFactor {
|
||||
case ebiten.BlendFactorZero:
|
||||
a += 0 * sa
|
||||
case ebiten.BlendFactorOne:
|
||||
a += 1 * sa
|
||||
case ebiten.BlendFactorSourceColor, ebiten.BlendFactorSourceAlpha:
|
||||
a += sa * sa
|
||||
case ebiten.BlendFactorOneMinusSourceColor, ebiten.BlendFactorOneMinusSourceAlpha:
|
||||
a += (1 - sa) * sa
|
||||
case ebiten.BlendFactorDestinationColor, ebiten.BlendFactorDestinationAlpha:
|
||||
a += da * sa
|
||||
case ebiten.BlendFactorOneMinusDestinationColor, ebiten.BlendFactorOneMinusDestinationAlpha:
|
||||
a += (1 - da) * sa
|
||||
}
|
||||
|
||||
switch dstRGBFactor {
|
||||
case ebiten.BlendFactorZero:
|
||||
r += 0 * dr
|
||||
g += 0 * dg
|
||||
b += 0 * db
|
||||
case ebiten.BlendFactorOne:
|
||||
r += 1 * dr
|
||||
g += 1 * dg
|
||||
b += 1 * db
|
||||
case ebiten.BlendFactorSourceColor:
|
||||
r += sr * dr
|
||||
g += sg * dg
|
||||
b += sb * db
|
||||
case ebiten.BlendFactorOneMinusSourceColor:
|
||||
r += (1 - sr) * dr
|
||||
g += (1 - sg) * dg
|
||||
b += (1 - sb) * db
|
||||
case ebiten.BlendFactorSourceAlpha:
|
||||
r += sa * dr
|
||||
g += sa * dg
|
||||
b += sa * db
|
||||
case ebiten.BlendFactorOneMinusSourceAlpha:
|
||||
r += (1 - sa) * dr
|
||||
g += (1 - sa) * dg
|
||||
b += (1 - sa) * db
|
||||
case ebiten.BlendFactorDestinationColor:
|
||||
r += dr * dr
|
||||
g += dg * dg
|
||||
b += db * db
|
||||
case ebiten.BlendFactorOneMinusDestinationColor:
|
||||
r += (1 - dr) * dr
|
||||
g += (1 - dg) * dg
|
||||
b += (1 - db) * db
|
||||
case ebiten.BlendFactorDestinationAlpha:
|
||||
r += da * dr
|
||||
g += da * dg
|
||||
b += da * db
|
||||
case ebiten.BlendFactorOneMinusDestinationAlpha:
|
||||
r += (1 - da) * dr
|
||||
g += (1 - da) * dg
|
||||
b += (1 - da) * db
|
||||
}
|
||||
switch dstAlphaFactor {
|
||||
case ebiten.BlendFactorZero:
|
||||
a += 0 * da
|
||||
case ebiten.BlendFactorOne:
|
||||
a += 1 * da
|
||||
case ebiten.BlendFactorSourceColor, ebiten.BlendFactorSourceAlpha:
|
||||
a += sa * da
|
||||
case ebiten.BlendFactorOneMinusSourceColor, ebiten.BlendFactorOneMinusSourceAlpha:
|
||||
a += (1 - sa) * da
|
||||
case ebiten.BlendFactorDestinationColor, ebiten.BlendFactorDestinationAlpha:
|
||||
a += da * da
|
||||
case ebiten.BlendFactorOneMinusDestinationColor, ebiten.BlendFactorOneMinusDestinationAlpha:
|
||||
a += (1 - da) * da
|
||||
}
|
||||
|
||||
want := color.RGBA{
|
||||
R: clamp(int(r * 0xff)),
|
||||
G: clamp(int(g * 0xff)),
|
||||
B: clamp(int(b * 0xff)),
|
||||
A: clamp(int(a * 0xff)),
|
||||
}
|
||||
if !sameColors(got, want, 1) {
|
||||
t.Errorf("dst.At(%d, 0): factors: %d, %d, %d, %d: got: %v, want: %v", i, srcRGBFactor, srcAlphaFactor, dstRGBFactor, dstAlphaFactor, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,15 @@ type BlendFactor byte
|
||||
const (
|
||||
BlendFactorZero BlendFactor = iota
|
||||
BlendFactorOne
|
||||
BlendFactorSourceColor
|
||||
BlendFactorOneMinusSourceColor
|
||||
BlendFactorSourceAlpha
|
||||
BlendFactorDestinationAlpha
|
||||
BlendFactorOneMinusSourceAlpha
|
||||
BlendFactorOneMinusDestinationAlpha
|
||||
BlendFactorDestinationColor
|
||||
BlendFactorOneMinusDestinationColor
|
||||
BlendFactorDestinationAlpha
|
||||
BlendFactorOneMinusDestinationAlpha
|
||||
BlendFactorSourceAlphaSaturated
|
||||
)
|
||||
|
||||
type BlendOperation byte
|
||||
|
@ -26,26 +26,44 @@ import (
|
||||
const numDescriptorsPerFrame = 32
|
||||
|
||||
func blendFactorToBlend(f graphicsdriver.BlendFactor, alpha bool) _D3D12_BLEND {
|
||||
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
||||
|
||||
switch f {
|
||||
case graphicsdriver.BlendFactorZero:
|
||||
return _D3D12_BLEND_ZERO
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
return _D3D12_BLEND_ONE
|
||||
case graphicsdriver.BlendFactorSourceColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_SRC_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusSourceColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_INV_SRC_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_INV_SRC_COLOR
|
||||
case graphicsdriver.BlendFactorSourceAlpha:
|
||||
return _D3D12_BLEND_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
|
||||
return _D3D12_BLEND_INV_SRC_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
// D3D12_RENDER_TARGET_BLEND_DESC's *BlendAlpha members don't allow *_COLOR values.
|
||||
// See https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_render_target_blend_desc.
|
||||
if alpha {
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationColor:
|
||||
if alpha {
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
}
|
||||
return _D3D12_BLEND_INV_DEST_COLOR
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return _D3D12_BLEND_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return _D3D12_BLEND_INV_DEST_ALPHA
|
||||
case graphicsdriver.BlendFactorSourceAlphaSaturated:
|
||||
return _D3D12_BLEND_SRC_ALPHA_SAT
|
||||
default:
|
||||
panic(fmt.Sprintf("directx: invalid blend factor: %d", f))
|
||||
}
|
||||
|
@ -306,16 +306,24 @@ func blendFactorToMetalBlendFactor(c graphicsdriver.BlendFactor) mtl.BlendFactor
|
||||
return mtl.BlendFactorZero
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
return mtl.BlendFactorOne
|
||||
case graphicsdriver.BlendFactorSourceColor:
|
||||
return mtl.BlendFactorSourceColor
|
||||
case graphicsdriver.BlendFactorOneMinusSourceColor:
|
||||
return mtl.BlendFactorOneMinusSourceColor
|
||||
case graphicsdriver.BlendFactorSourceAlpha:
|
||||
return mtl.BlendFactorSourceAlpha
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return mtl.BlendFactorDestinationAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
|
||||
return mtl.BlendFactorOneMinusSourceAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return mtl.BlendFactorOneMinusDestinationAlpha
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
return mtl.BlendFactorDestinationColor
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationColor:
|
||||
return mtl.BlendFactorOneMinusDestinationColor
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return mtl.BlendFactorDestinationAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return mtl.BlendFactorOneMinusDestinationAlpha
|
||||
case graphicsdriver.BlendFactorSourceAlphaSaturated:
|
||||
return mtl.BlendFactorSourceAlphaSaturated
|
||||
default:
|
||||
panic(fmt.Sprintf("metal: invalid blend factor: %d", c))
|
||||
}
|
||||
|
@ -24,12 +24,16 @@ import (
|
||||
type blendFactor int
|
||||
|
||||
const (
|
||||
glDstAlpha blendFactor = 0x0304
|
||||
glDstColor blendFactor = 0x0306
|
||||
glDstAlpha blendFactor = 0x304
|
||||
glDstColor blendFactor = 0x306
|
||||
glOne blendFactor = 1
|
||||
glOneMinusDstAlpha blendFactor = 0x0305
|
||||
glOneMinusSrcAlpha blendFactor = 0x0303
|
||||
glSrcAlpha blendFactor = 0x0302
|
||||
glOneMinusDstAlpha blendFactor = 0x305
|
||||
glOneMinusDstColor blendFactor = 0x307
|
||||
glOneMinusSrcAlpha blendFactor = 0x303
|
||||
glOneMinusSrcColor blendFactor = 0x301
|
||||
glSrcAlpha blendFactor = 0x302
|
||||
glSrcAlphaSaturate blendFactor = 0x308
|
||||
glSrcColor blendFactor = 0x300
|
||||
glZero blendFactor = 0
|
||||
)
|
||||
|
||||
@ -47,16 +51,24 @@ func convertBlendFactor(f graphicsdriver.BlendFactor) blendFactor {
|
||||
return glZero
|
||||
case graphicsdriver.BlendFactorOne:
|
||||
return glOne
|
||||
case graphicsdriver.BlendFactorSourceColor:
|
||||
return glSrcColor
|
||||
case graphicsdriver.BlendFactorOneMinusSourceColor:
|
||||
return glOneMinusSrcColor
|
||||
case graphicsdriver.BlendFactorSourceAlpha:
|
||||
return glSrcAlpha
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return glDstAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusSourceAlpha:
|
||||
return glOneMinusSrcAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return glOneMinusDstAlpha
|
||||
case graphicsdriver.BlendFactorDestinationColor:
|
||||
return glDstColor
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationColor:
|
||||
return glOneMinusDstColor
|
||||
case graphicsdriver.BlendFactorDestinationAlpha:
|
||||
return glDstAlpha
|
||||
case graphicsdriver.BlendFactorOneMinusDestinationAlpha:
|
||||
return glOneMinusDstAlpha
|
||||
case graphicsdriver.BlendFactorSourceAlphaSaturated:
|
||||
return glSrcAlphaSaturate
|
||||
default:
|
||||
panic(fmt.Sprintf("opengl: invalid blend factor %d", f))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user