ebiten: add Blend and deprecate CompositeMode

Updates #2382
This commit is contained in:
Hajime Hoshi 2022-10-16 20:02:42 +09:00
parent bd0d43f98f
commit b79495761e
9 changed files with 369 additions and 75 deletions

254
blend.go Normal file
View File

@ -0,0 +1,254 @@
// Copyright 2022 The Ebitengine Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ebiten
import (
"fmt"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
)
// Blend is a blending way of the source color and the destination color.
//
// The default (zero) value is source-over (regular alpha blending).
type Blend struct {
// BlendFactorSourceColor is a factor for source RGB values.
BlendFactorSourceColor BlendFactor
// BlendFactorSourceAlpha is a factor for source alpha values.
BlendFactorSourceAlpha BlendFactor
// BlendFactorDestinationColor is a factor for destination RGB values.
BlendFactorDestinationColor BlendFactor
// BlendFactorDestinationAlpha is a factor for destination apha values.
BlendFactorDestinationAlpha BlendFactor
// BlendOperationColor is an operation for source and destination RGB values.
BlendOperationColor BlendOperation
// BlendOperationAlpha is an operation for source and destination alpha values.
BlendOperationAlpha BlendOperation
}
func (b Blend) internalBlend() graphicsdriver.Blend {
return graphicsdriver.Blend{
BlendFactorSourceColor: b.BlendFactorSourceColor.internalBlendFactor(true),
BlendFactorSourceAlpha: b.BlendFactorSourceAlpha.internalBlendFactor(true),
BlendFactorDestinationColor: b.BlendFactorDestinationColor.internalBlendFactor(false),
BlendFactorDestinationAlpha: b.BlendFactorDestinationAlpha.internalBlendFactor(false),
BlendOperationColor: b.BlendOperationColor.internalBlendOperation(),
BlendOperationAlpha: b.BlendOperationAlpha.internalBlendOperation(),
}
}
// BlendFactor is a factor for source and destination color values.
type BlendFactor byte
const (
// BlendFactorDefault is the default factor value.
// The actual value depends on which source or destination this value is used.
BlendFactorDefault BlendFactor = iota
BlendFactorZero
BlendFactorOne
BlendFactorSourceAlpha
BlendFactorDestinationAlpha
BlendFactorOneMinusSourceAlpha
BlendFactorOneMinusDestinationAlpha
BlendFactorDestinationColor
)
func (b BlendFactor) internalBlendFactor(source bool) graphicsdriver.BlendFactor {
switch b {
case BlendFactorDefault:
// The default is the source-over composition (regular alpha blending).
if source {
return graphicsdriver.BlendFactorOne
}
return graphicsdriver.BlendFactorOneMinusSourceAlpha
case BlendFactorZero:
return graphicsdriver.BlendFactorZero
case BlendFactorOne:
return graphicsdriver.BlendFactorOne
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
default:
panic(fmt.Sprintf("ebiten: invalid blend factor: %d", b))
}
}
// BlendFactor is an operation for source and destination color values.
type BlendOperation byte
const (
// BlendOperationAdd represents adding the source and destination color.
// c_out = factor_src × c_src + factor_dst × c_dst
BlendOperationAdd BlendOperation = iota
)
func (b BlendOperation) internalBlendOperation() graphicsdriver.BlendOperation {
switch b {
case BlendOperationAdd:
return graphicsdriver.BlendOperationAdd
default:
panic(fmt.Sprintf("ebiten: invalid blend operation: %d", b))
}
}
// This name convention follows CSS compositing: https://drafts.fxtf.org/compositing-2/.
//
// In the comments,
// c_src, c_dst and c_out represent alpha-premultiplied RGB values of source, destination and output respectively. α_src and α_dst represent alpha values of source and destination respectively.
var (
// BlendSourceOver represents the regular alpha blending.
// c_out = c_src + c_dst × (1 - α_src)
BlendSourceOver = Blend{
BlendFactorSourceColor: BlendFactorOne,
BlendFactorSourceAlpha: BlendFactorOne,
BlendFactorDestinationColor: BlendFactorOneMinusSourceAlpha,
BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = 0
BlendClear = Blend{
BlendFactorSourceColor: BlendFactorZero,
BlendFactorSourceAlpha: BlendFactorZero,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src
BlendCopy = Blend{
BlendFactorSourceColor: BlendFactorOne,
BlendFactorSourceAlpha: BlendFactorOne,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_dst
BlendDestination = Blend{
BlendFactorSourceColor: BlendFactorZero,
BlendFactorSourceAlpha: BlendFactorZero,
BlendFactorDestinationColor: BlendFactorOne,
BlendFactorDestinationAlpha: BlendFactorOne,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × (1 - α_dst) + c_dst
BlendDestinationOver = Blend{
BlendFactorSourceColor: BlendFactorOneMinusDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
BlendFactorDestinationColor: BlendFactorOne,
BlendFactorDestinationAlpha: BlendFactorOne,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × α_dst
BlendSourceIn = Blend{
BlendFactorSourceColor: BlendFactorDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorDestinationAlpha,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_dst × α_src
BlendDestinationIn = Blend{
BlendFactorSourceColor: BlendFactorZero,
BlendFactorSourceAlpha: BlendFactorZero,
BlendFactorDestinationColor: BlendFactorSourceAlpha,
BlendFactorDestinationAlpha: BlendFactorSourceAlpha,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × (1 - α_dst)
BlendSourceOut = Blend{
BlendFactorSourceColor: BlendFactorOneMinusDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_dst × (1 - α_src)
BlendDestinationOut = Blend{
BlendFactorSourceColor: BlendFactorOneMinusDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × α_dst + c_dst × (1 - α_src)
BlendSourceAtop = Blend{
BlendFactorSourceColor: BlendFactorDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorDestinationAlpha,
BlendFactorDestinationColor: BlendFactorOneMinusSourceAlpha,
BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × (1 - α_dst) + c_dst × α_src
BlendDestinationAtop = Blend{
BlendFactorSourceColor: BlendFactorOneMinusDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
BlendFactorDestinationColor: BlendFactorSourceAlpha,
BlendFactorDestinationAlpha: BlendFactorSourceAlpha,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
BlendXor = Blend{
BlendFactorSourceColor: BlendFactorOneMinusDestinationAlpha,
BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
BlendFactorDestinationColor: BlendFactorOneMinusSourceAlpha,
BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
// Sum of source and destination (a.k.a. 'plus' or 'additive')
// c_out = c_src + c_dst
BlendLighter = Blend{
BlendFactorSourceColor: BlendFactorOne,
BlendFactorSourceAlpha: BlendFactorOne,
BlendFactorDestinationColor: BlendFactorOne,
BlendFactorDestinationAlpha: BlendFactorOne,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
)

View File

@ -52,16 +52,16 @@ func (g *Game) Draw(screen *ebiten.Image) {
screen.Fill(color.NRGBA{0x00, 0x40, 0x80, 0xff})
// Draw the image with 'Source Alpha' composite mode (default).
// Draw the image with 'Source Over' blend mode (default).
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(ox, oy)
screen.DrawImage(ebitenImage, op)
// Draw the image with 'Lighter (a.k.a Additive)' composite mode.
// Draw the image with 'Lighter (a.k.a Additive)' blend mode.
op = &ebiten.DrawImageOptions{}
w, _ := ebitenImage.Size()
op.GeoM.Translate(ox+float64(w), oy)
op.CompositeMode = ebiten.CompositeModeLighter
op.Blend = ebiten.BlendLighter
screen.DrawImage(ebitenImage, op)
}

View File

@ -62,15 +62,15 @@ func (g *Game) Draw(screen *ebiten.Image) {
for i := -3; i <= 3; i++ {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(i), 244+float64(j))
// This is a blur based on the CompositerModeSourceOver composition mode,
// This is a blur based on the source-over blend mode,
// which is basically (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). ColorM acts
// on unpremultiplied colors, but all Ebitengine internal colors are
// premultiplied, meaning this mode is regular alpha blending,
// computing each destination pixel as srcPix * alpha + dstPix * (1 - alpha).
//
// This means that the final color is affected by the destination color when CompositeModeSourceOver is used.
// This composite mode is the default mode. See how this is calculated at the doc:
// https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#CompositeMode
// This means that the final color is affected by the destination color when BlendSourceOver is used.
// This blend mode is the default mode. See how this is calculated at the doc:
// https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#Blend
//
// So if using the same alpha every time, the end result will sure be biased towards the last layer.
//

View File

@ -122,11 +122,11 @@ func (g *Game) Draw(screen *ebiten.Image) {
// Reset the maskedFgImage.
maskedFgImage.Fill(color.White)
op := &ebiten.DrawImageOptions{}
op.CompositeMode = ebiten.CompositeModeCopy
op.Blend = ebiten.BlendCopy
op.GeoM.Translate(float64(g.spotLightX), float64(g.spotLightY))
maskedFgImage.DrawImage(spotLightImage, op)
// Use 'source-in' composite mode so that the source image (fgImage) is used but the alpha
// Use 'source-in' blend mode so that the source image (fgImage) is used but the alpha
// is determined by the destination image (maskedFgImage).
//
// The result image is the source image with the destination alpha. In maskedFgImage, alpha
@ -136,7 +136,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
//
// See also https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin.
op = &ebiten.DrawImageOptions{}
op.CompositeMode = ebiten.CompositeModeSourceIn
op.Blend = ebiten.BlendSourceIn
maskedFgImage.DrawImage(fgImage, op)
screen.Fill(color.RGBA{0x00, 0x00, 0x80, 0xff})

View File

@ -234,7 +234,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
// Subtract ray triangles from shadow
opt := &ebiten.DrawTrianglesOptions{}
opt.Address = ebiten.AddressRepeat
opt.CompositeMode = ebiten.CompositeModeSourceOut
opt.Blend = ebiten.BlendSourceOut
for i, line := range rays {
nextLine := rays[(i+1)%len(rays)]

View File

@ -18,7 +18,6 @@ import (
"fmt"
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
"github.com/hajimehoshi/ebiten/v2/internal/ui"
)
@ -34,101 +33,94 @@ const (
)
// CompositeMode represents Porter-Duff composition mode.
//
// Deprecated: as of v2.5. Use Blend instead.
type CompositeMode int
// This name convention follows CSS compositing: https://drafts.fxtf.org/compositing-2/.
//
// In the comments,
// c_src, c_dst and c_out represent alpha-premultiplied RGB values of source, destination and output respectively. α_src and α_dst represent alpha values of source and destination respectively.
const (
// Regular alpha blending
// c_out = c_src + c_dst × (1 - α_src)
CompositeModeSourceOver CompositeMode = iota
// CompositeModeCustom indicates to refer Blend.
CompositeModeCustom CompositeMode = iota
// c_out = 0
// Deprecated: as of v2.5. Use BlendSourceOver instead.
CompositeModeSourceOver
// Deprecated: as of v2.5. Use BlendClear instead.
CompositeModeClear
// c_out = c_src
// Deprecated: as of v2.5. Use BlendCopy instead.
CompositeModeCopy
// c_out = c_dst
// Deprecated: as of v2.5. Use BlendDestination instead.
CompositeModeDestination
// c_out = c_src × (1 - α_dst) + c_dst
// Deprecated: as of v2.5. Use BlendDestinationOver instead.
CompositeModeDestinationOver
// c_out = c_src × α_dst
// Deprecated: as of v2.5. Use BlendSourceIn instead.
CompositeModeSourceIn
// c_out = c_dst × α_src
// Deprecated: as of v2.5. Use BlendDestinationIn instead.
CompositeModeDestinationIn
// c_out = c_src × (1 - α_dst)
// Deprecated: as of v2.5. Use BlendSourceOut instead.
CompositeModeSourceOut
// c_out = c_dst × (1 - α_src)
// Deprecated: as of v2.5. Use BlendDestinationOut instead.
CompositeModeDestinationOut
// c_out = c_src × α_dst + c_dst × (1 - α_src)
// Deprecated: as of v2.5. Use BlendSourceAtop instead.
CompositeModeSourceAtop
// c_out = c_src × (1 - α_dst) + c_dst × α_src
// Deprecated: as of v2.5. Use BlendDestinationAtop instead.
CompositeModeDestinationAtop
// c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
// Deprecated: as of v2.5. Use BlendXor instead.
CompositeModeXor
// Sum of source and destination (a.k.a. 'plus' or 'additive')
// c_out = c_src + c_dst
// Deprecated: as of v2.5. Use BlendLighter instead.
CompositeModeLighter
// The product of source and destination (a.k.a 'multiply blend mode')
// c_out = c_src * c_dst
// Deprecated: as of v2.5. Use Blend with BlendFactorDestinationColor and BlendFactorZero instead.
CompositeModeMultiply
)
func (c CompositeMode) blend() graphicsdriver.Blend {
src, dst := c.blendFactors()
return graphicsdriver.Blend{
BlendFactorSourceColor: src,
BlendFactorSourceAlpha: src,
BlendFactorDestinationColor: dst,
BlendFactorDestinationAlpha: dst,
BlendOperationColor: graphicsdriver.BlendOperationAdd,
BlendOperationAlpha: graphicsdriver.BlendOperationAdd,
}
}
func (c CompositeMode) blendFactors() (src graphicsdriver.BlendFactor, dst graphicsdriver.BlendFactor) {
func (c CompositeMode) blend() Blend {
switch c {
case CompositeModeSourceOver:
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOneMinusSourceAlpha
return BlendSourceOver
case CompositeModeClear:
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorZero
return BlendClear
case CompositeModeCopy:
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorZero
return BlendCopy
case CompositeModeDestination:
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOne
return BlendDestination
case CompositeModeDestinationOver:
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOne
return BlendDestinationOver
case CompositeModeSourceIn:
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorZero
return BlendSourceIn
case CompositeModeDestinationIn:
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorSourceAlpha
return BlendDestinationIn
case CompositeModeSourceOut:
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorZero
return BlendSourceOut
case CompositeModeDestinationOut:
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOneMinusSourceAlpha
return BlendDestinationOut
case CompositeModeSourceAtop:
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
return BlendSourceAtop
case CompositeModeDestinationAtop:
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorSourceAlpha
return BlendDestinationAtop
case CompositeModeXor:
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
return BlendXor
case CompositeModeLighter:
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOne
return BlendLighter
case CompositeModeMultiply:
return graphicsdriver.BlendFactorDestinationColor, graphicsdriver.BlendFactorZero
return Blend{
BlendFactorSourceColor: BlendFactorDestinationColor,
BlendFactorSourceAlpha: BlendFactorDestinationColor,
BlendFactorDestinationColor: BlendFactorZero,
BlendFactorDestinationAlpha: BlendFactorZero,
BlendOperationColor: BlendOperationAdd,
BlendOperationAlpha: BlendOperationAdd,
}
default:
panic(fmt.Sprintf("ebiten: invalid composite mode: %d", c))
}

View File

@ -115,9 +115,16 @@ type DrawImageOptions struct {
ColorM ColorM
// CompositeMode is a composite mode to draw.
// The default (zero) value is regular alpha blending.
// The default (zero) value is CompositeModeCustom (Blend is used).
//
// Deprecated: as of v2.5. Use Blend instead.
CompositeMode CompositeMode
// Blend is a blending way of the source color and the destination color.
// Blend is used only when CompositeMode is CompositeModeCustom.
// The default (zero) value is the regular alpha blending.
Blend Blend
// Filter is a type of texture filter.
// The default (zero) value is FilterNearest.
Filter Filter
@ -187,7 +194,7 @@ func (i *Image) adjustedRegion() graphicsdriver.Region {
// - If only (*ColorM).Scale is applied to a ColorM, the ColorM has only
// diagonal elements. The other ColorM functions might modify the other
// elements.
// - All CompositeMode values are same
// - All CompositeMode/Blend values are same
// - All Filter values are same
//
// Even when all the above conditions are satisfied, multiple draw commands can
@ -215,7 +222,12 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
options = &DrawImageOptions{}
}
blend := options.CompositeMode.blend()
var blend graphicsdriver.Blend
if options.CompositeMode == CompositeModeCustom {
blend = options.Blend.internalBlend()
} else {
blend = options.CompositeMode.blend().internalBlend()
}
filter := builtinshader.Filter(options.Filter)
if offsetX, offsetY := i.adjustPosition(0, 0); offsetX != 0 || offsetY != 0 {
@ -327,9 +339,16 @@ type DrawTrianglesOptions struct {
ColorScaleFormat ColorScaleFormat
// CompositeMode is a composite mode to draw.
// The default (zero) value is regular alpha blending.
// The default (zero) value is CompositeModeCustom (Blend is used).
//
// Deprecated: as of v2.5. Use Blend instead.
CompositeMode CompositeMode
// Blend is a blending way of the source color and the destination color.
// Blend is used only when CompositeMode is CompositeModeCustom.
// The default (zero) value is the regular alpha blending.
Blend Blend
// Filter is a type of texture filter.
// The default (zero) value is FilterNearest.
Filter Filter
@ -396,7 +415,12 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
options = &DrawTrianglesOptions{}
}
blend := options.CompositeMode.blend()
var blend graphicsdriver.Blend
if options.CompositeMode == CompositeModeCustom {
blend = options.Blend.internalBlend()
} else {
blend = options.CompositeMode.blend().internalBlend()
}
address := builtinshader.Address(options.Address)
var sr graphicsdriver.Region
@ -461,9 +485,16 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
type DrawTrianglesShaderOptions struct {
// CompositeMode is a composite mode to draw.
// The default (zero) value is regular alpha blending.
// The default (zero) value is CompositeModeCustom (Blend is used).
//
// Deprecated: as of v2.5. Use Blend instead.
CompositeMode CompositeMode
// Blend is a blending way of the source color and the destination color.
// Blend is used only when CompositeMode is CompositeModeCustom.
// The default (zero) value is the regular alpha blending.
Blend Blend
// Uniforms is a set of uniform variables for the shader.
// The keys are the names of the uniform variables.
// The values must be float or []float.
@ -525,7 +556,12 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
options = &DrawTrianglesShaderOptions{}
}
blend := options.CompositeMode.blend()
var blend graphicsdriver.Blend
if options.CompositeMode == CompositeModeCustom {
blend = options.Blend.internalBlend()
} else {
blend = options.CompositeMode.blend().internalBlend()
}
vs := graphics.Vertices(len(vertices))
dst := i
@ -604,9 +640,16 @@ type DrawRectShaderOptions struct {
ColorScale ColorScale
// CompositeMode is a composite mode to draw.
// The default (zero) value is regular alpha blending.
// The default (zero) value is CompositeModeCustom (Blend is used).
//
// Deprecated: as of v2.5. Use Blend instead.
CompositeMode CompositeMode
// Blend is a blending way of the source color and the destination color.
// Blend is used only when CompositeMode is CompositeModeCustom.
// The default (zero) value is the regular alpha blending.
Blend Blend
// Uniforms is a set of uniform variables for the shader.
// The keys are the names of the uniform variables.
// The values must be float or []float.
@ -645,7 +688,12 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
options = &DrawRectShaderOptions{}
}
blend := options.CompositeMode.blend()
var blend graphicsdriver.Blend
if options.CompositeMode == CompositeModeCustom {
blend = options.Blend.internalBlend()
} else {
blend = options.CompositeMode.blend().internalBlend()
}
var imgs [graphics.ShaderImageCount]*ui.Image
for i, img := range options.Images {

View File

@ -342,7 +342,7 @@ func min(a, b int) int {
return b
}
func TestImageCompositeModeLighter(t *testing.T) {
func TestImageBlendLighter(t *testing.T) {
img0, _, err := openEbitenImage()
if err != nil {
t.Fatal(err)
@ -353,7 +353,7 @@ func TestImageCompositeModeLighter(t *testing.T) {
img1 := ebiten.NewImage(w, h)
img1.Fill(color.RGBA{0x01, 0x02, 0x03, 0x04})
op := &ebiten.DrawImageOptions{}
op.CompositeMode = ebiten.CompositeModeLighter
op.Blend = ebiten.BlendLighter
img1.DrawImage(img0, op)
for j := 0; j < img1.Bounds().Size().Y; j++ {
for i := 0; i < img1.Bounds().Size().X; i++ {
@ -2343,7 +2343,7 @@ func TestImageColorMCopy(t *testing.T) {
for k := 0; k < 256; k++ {
op := &ebiten.DrawImageOptions{}
op.ColorM.Translate(1, 1, 1, float64(k)/0xff)
op.CompositeMode = ebiten.CompositeModeCopy
op.Blend = ebiten.BlendCopy
dst.DrawImage(src, op)
for j := 0; j < h; j++ {

View File

@ -48,7 +48,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
g.dst = ebiten.NewImage(w, h)
op := &ebiten.DrawRectShaderOptions{}
op.CompositeMode = ebiten.CompositeModeCopy
op.Blend = ebiten.BlendCopy
op.Uniforms = map[string]interface{}{
"Color": []float32{1, 1, 1, 1},
}
@ -78,7 +78,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
}
op := &ebiten.DrawRectShaderOptions{}
op.CompositeMode = ebiten.CompositeModeCopy
op.Blend = ebiten.BlendCopy
op.Uniforms = map[string]interface{}{
"Dummy": float32(0),
"R": float32(0.5),