mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
parent
bd0d43f98f
commit
b79495761e
254
blend.go
Normal file
254
blend.go
Normal 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,
|
||||||
|
}
|
||||||
|
)
|
@ -52,16 +52,16 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
|
|
||||||
screen.Fill(color.NRGBA{0x00, 0x40, 0x80, 0xff})
|
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 := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(ox, oy)
|
op.GeoM.Translate(ox, oy)
|
||||||
screen.DrawImage(ebitenImage, op)
|
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{}
|
op = &ebiten.DrawImageOptions{}
|
||||||
w, _ := ebitenImage.Size()
|
w, _ := ebitenImage.Size()
|
||||||
op.GeoM.Translate(ox+float64(w), oy)
|
op.GeoM.Translate(ox+float64(w), oy)
|
||||||
op.CompositeMode = ebiten.CompositeModeLighter
|
op.Blend = ebiten.BlendLighter
|
||||||
screen.DrawImage(ebitenImage, op)
|
screen.DrawImage(ebitenImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +62,15 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
for i := -3; i <= 3; i++ {
|
for i := -3; i <= 3; i++ {
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(float64(i), 244+float64(j))
|
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
|
// which is basically (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). ColorM acts
|
||||||
// on unpremultiplied colors, but all Ebitengine internal colors are
|
// on unpremultiplied colors, but all Ebitengine internal colors are
|
||||||
// premultiplied, meaning this mode is regular alpha blending,
|
// premultiplied, meaning this mode is regular alpha blending,
|
||||||
// computing each destination pixel as srcPix * alpha + dstPix * (1 - alpha).
|
// 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 means that the final color is affected by the destination color when BlendSourceOver is used.
|
||||||
// This composite mode is the default mode. See how this is calculated at the doc:
|
// This blend mode is the default mode. See how this is calculated at the doc:
|
||||||
// https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#CompositeMode
|
// 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.
|
// So if using the same alpha every time, the end result will sure be biased towards the last layer.
|
||||||
//
|
//
|
||||||
|
@ -122,11 +122,11 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
// Reset the maskedFgImage.
|
// Reset the maskedFgImage.
|
||||||
maskedFgImage.Fill(color.White)
|
maskedFgImage.Fill(color.White)
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.CompositeMode = ebiten.CompositeModeCopy
|
op.Blend = ebiten.BlendCopy
|
||||||
op.GeoM.Translate(float64(g.spotLightX), float64(g.spotLightY))
|
op.GeoM.Translate(float64(g.spotLightX), float64(g.spotLightY))
|
||||||
maskedFgImage.DrawImage(spotLightImage, op)
|
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).
|
// is determined by the destination image (maskedFgImage).
|
||||||
//
|
//
|
||||||
// The result image is the source image with the destination alpha. In maskedFgImage, alpha
|
// 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.
|
// See also https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators_srcin.
|
||||||
op = &ebiten.DrawImageOptions{}
|
op = &ebiten.DrawImageOptions{}
|
||||||
op.CompositeMode = ebiten.CompositeModeSourceIn
|
op.Blend = ebiten.BlendSourceIn
|
||||||
maskedFgImage.DrawImage(fgImage, op)
|
maskedFgImage.DrawImage(fgImage, op)
|
||||||
|
|
||||||
screen.Fill(color.RGBA{0x00, 0x00, 0x80, 0xff})
|
screen.Fill(color.RGBA{0x00, 0x00, 0x80, 0xff})
|
||||||
|
@ -234,7 +234,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
// Subtract ray triangles from shadow
|
// Subtract ray triangles from shadow
|
||||||
opt := &ebiten.DrawTrianglesOptions{}
|
opt := &ebiten.DrawTrianglesOptions{}
|
||||||
opt.Address = ebiten.AddressRepeat
|
opt.Address = ebiten.AddressRepeat
|
||||||
opt.CompositeMode = ebiten.CompositeModeSourceOut
|
opt.Blend = ebiten.BlendSourceOut
|
||||||
for i, line := range rays {
|
for i, line := range rays {
|
||||||
nextLine := rays[(i+1)%len(rays)]
|
nextLine := rays[(i+1)%len(rays)]
|
||||||
|
|
||||||
|
92
graphics.go
92
graphics.go
@ -18,7 +18,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
"github.com/hajimehoshi/ebiten/v2/internal/builtinshader"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,101 +33,94 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CompositeMode represents Porter-Duff composition mode.
|
// CompositeMode represents Porter-Duff composition mode.
|
||||||
|
//
|
||||||
|
// Deprecated: as of v2.5. Use Blend instead.
|
||||||
type CompositeMode int
|
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 (
|
const (
|
||||||
// Regular alpha blending
|
// CompositeModeCustom indicates to refer Blend.
|
||||||
// c_out = c_src + c_dst × (1 - α_src)
|
CompositeModeCustom CompositeMode = iota
|
||||||
CompositeModeSourceOver CompositeMode = iota
|
|
||||||
|
|
||||||
// c_out = 0
|
// Deprecated: as of v2.5. Use BlendSourceOver instead.
|
||||||
|
CompositeModeSourceOver
|
||||||
|
|
||||||
|
// Deprecated: as of v2.5. Use BlendClear instead.
|
||||||
CompositeModeClear
|
CompositeModeClear
|
||||||
|
|
||||||
// c_out = c_src
|
// Deprecated: as of v2.5. Use BlendCopy instead.
|
||||||
CompositeModeCopy
|
CompositeModeCopy
|
||||||
|
|
||||||
// c_out = c_dst
|
// Deprecated: as of v2.5. Use BlendDestination instead.
|
||||||
CompositeModeDestination
|
CompositeModeDestination
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst
|
// Deprecated: as of v2.5. Use BlendDestinationOver instead.
|
||||||
CompositeModeDestinationOver
|
CompositeModeDestinationOver
|
||||||
|
|
||||||
// c_out = c_src × α_dst
|
// Deprecated: as of v2.5. Use BlendSourceIn instead.
|
||||||
CompositeModeSourceIn
|
CompositeModeSourceIn
|
||||||
|
|
||||||
// c_out = c_dst × α_src
|
// Deprecated: as of v2.5. Use BlendDestinationIn instead.
|
||||||
CompositeModeDestinationIn
|
CompositeModeDestinationIn
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst)
|
// Deprecated: as of v2.5. Use BlendSourceOut instead.
|
||||||
CompositeModeSourceOut
|
CompositeModeSourceOut
|
||||||
|
|
||||||
// c_out = c_dst × (1 - α_src)
|
// Deprecated: as of v2.5. Use BlendDestinationOut instead.
|
||||||
CompositeModeDestinationOut
|
CompositeModeDestinationOut
|
||||||
|
|
||||||
// c_out = c_src × α_dst + c_dst × (1 - α_src)
|
// Deprecated: as of v2.5. Use BlendSourceAtop instead.
|
||||||
CompositeModeSourceAtop
|
CompositeModeSourceAtop
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst × α_src
|
// Deprecated: as of v2.5. Use BlendDestinationAtop instead.
|
||||||
CompositeModeDestinationAtop
|
CompositeModeDestinationAtop
|
||||||
|
|
||||||
// c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
|
// Deprecated: as of v2.5. Use BlendXor instead.
|
||||||
CompositeModeXor
|
CompositeModeXor
|
||||||
|
|
||||||
// Sum of source and destination (a.k.a. 'plus' or 'additive')
|
// Deprecated: as of v2.5. Use BlendLighter instead.
|
||||||
// c_out = c_src + c_dst
|
|
||||||
CompositeModeLighter
|
CompositeModeLighter
|
||||||
|
|
||||||
// The product of source and destination (a.k.a 'multiply blend mode')
|
// Deprecated: as of v2.5. Use Blend with BlendFactorDestinationColor and BlendFactorZero instead.
|
||||||
// c_out = c_src * c_dst
|
|
||||||
CompositeModeMultiply
|
CompositeModeMultiply
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c CompositeMode) blend() graphicsdriver.Blend {
|
func (c CompositeMode) blend() 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) {
|
|
||||||
switch c {
|
switch c {
|
||||||
case CompositeModeSourceOver:
|
case CompositeModeSourceOver:
|
||||||
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
return BlendSourceOver
|
||||||
case CompositeModeClear:
|
case CompositeModeClear:
|
||||||
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorZero
|
return BlendClear
|
||||||
case CompositeModeCopy:
|
case CompositeModeCopy:
|
||||||
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorZero
|
return BlendCopy
|
||||||
case CompositeModeDestination:
|
case CompositeModeDestination:
|
||||||
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOne
|
return BlendDestination
|
||||||
case CompositeModeDestinationOver:
|
case CompositeModeDestinationOver:
|
||||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOne
|
return BlendDestinationOver
|
||||||
case CompositeModeSourceIn:
|
case CompositeModeSourceIn:
|
||||||
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorZero
|
return BlendSourceIn
|
||||||
case CompositeModeDestinationIn:
|
case CompositeModeDestinationIn:
|
||||||
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorSourceAlpha
|
return BlendDestinationIn
|
||||||
case CompositeModeSourceOut:
|
case CompositeModeSourceOut:
|
||||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorZero
|
return BlendSourceOut
|
||||||
case CompositeModeDestinationOut:
|
case CompositeModeDestinationOut:
|
||||||
return graphicsdriver.BlendFactorZero, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
return BlendDestinationOut
|
||||||
case CompositeModeSourceAtop:
|
case CompositeModeSourceAtop:
|
||||||
return graphicsdriver.BlendFactorDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
return BlendSourceAtop
|
||||||
case CompositeModeDestinationAtop:
|
case CompositeModeDestinationAtop:
|
||||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorSourceAlpha
|
return BlendDestinationAtop
|
||||||
case CompositeModeXor:
|
case CompositeModeXor:
|
||||||
return graphicsdriver.BlendFactorOneMinusDestinationAlpha, graphicsdriver.BlendFactorOneMinusSourceAlpha
|
return BlendXor
|
||||||
case CompositeModeLighter:
|
case CompositeModeLighter:
|
||||||
return graphicsdriver.BlendFactorOne, graphicsdriver.BlendFactorOne
|
return BlendLighter
|
||||||
case CompositeModeMultiply:
|
case CompositeModeMultiply:
|
||||||
return graphicsdriver.BlendFactorDestinationColor, graphicsdriver.BlendFactorZero
|
return Blend{
|
||||||
|
BlendFactorSourceColor: BlendFactorDestinationColor,
|
||||||
|
BlendFactorSourceAlpha: BlendFactorDestinationColor,
|
||||||
|
BlendFactorDestinationColor: BlendFactorZero,
|
||||||
|
BlendFactorDestinationAlpha: BlendFactorZero,
|
||||||
|
BlendOperationColor: BlendOperationAdd,
|
||||||
|
BlendOperationAlpha: BlendOperationAdd,
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("ebiten: invalid composite mode: %d", c))
|
panic(fmt.Sprintf("ebiten: invalid composite mode: %d", c))
|
||||||
}
|
}
|
||||||
|
66
image.go
66
image.go
@ -115,9 +115,16 @@ type DrawImageOptions struct {
|
|||||||
ColorM ColorM
|
ColorM ColorM
|
||||||
|
|
||||||
// CompositeMode is a composite mode to draw.
|
// 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
|
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.
|
// Filter is a type of texture filter.
|
||||||
// The default (zero) value is FilterNearest.
|
// The default (zero) value is FilterNearest.
|
||||||
Filter Filter
|
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
|
// - If only (*ColorM).Scale is applied to a ColorM, the ColorM has only
|
||||||
// diagonal elements. The other ColorM functions might modify the other
|
// diagonal elements. The other ColorM functions might modify the other
|
||||||
// elements.
|
// elements.
|
||||||
// - All CompositeMode values are same
|
// - All CompositeMode/Blend values are same
|
||||||
// - All Filter values are same
|
// - All Filter values are same
|
||||||
//
|
//
|
||||||
// Even when all the above conditions are satisfied, multiple draw commands can
|
// 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{}
|
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)
|
filter := builtinshader.Filter(options.Filter)
|
||||||
|
|
||||||
if offsetX, offsetY := i.adjustPosition(0, 0); offsetX != 0 || offsetY != 0 {
|
if offsetX, offsetY := i.adjustPosition(0, 0); offsetX != 0 || offsetY != 0 {
|
||||||
@ -327,9 +339,16 @@ type DrawTrianglesOptions struct {
|
|||||||
ColorScaleFormat ColorScaleFormat
|
ColorScaleFormat ColorScaleFormat
|
||||||
|
|
||||||
// CompositeMode is a composite mode to draw.
|
// 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
|
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.
|
// Filter is a type of texture filter.
|
||||||
// The default (zero) value is FilterNearest.
|
// The default (zero) value is FilterNearest.
|
||||||
Filter Filter
|
Filter Filter
|
||||||
@ -396,7 +415,12 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
options = &DrawTrianglesOptions{}
|
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)
|
address := builtinshader.Address(options.Address)
|
||||||
var sr graphicsdriver.Region
|
var sr graphicsdriver.Region
|
||||||
@ -461,9 +485,16 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||||
type DrawTrianglesShaderOptions struct {
|
type DrawTrianglesShaderOptions struct {
|
||||||
// CompositeMode is a composite mode to draw.
|
// 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
|
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.
|
// Uniforms is a set of uniform variables for the shader.
|
||||||
// The keys are the names of the uniform variables.
|
// The keys are the names of the uniform variables.
|
||||||
// The values must be float or []float.
|
// The values must be float or []float.
|
||||||
@ -525,7 +556,12 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
options = &DrawTrianglesShaderOptions{}
|
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))
|
vs := graphics.Vertices(len(vertices))
|
||||||
dst := i
|
dst := i
|
||||||
@ -604,9 +640,16 @@ type DrawRectShaderOptions struct {
|
|||||||
ColorScale ColorScale
|
ColorScale ColorScale
|
||||||
|
|
||||||
// CompositeMode is a composite mode to draw.
|
// 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
|
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.
|
// Uniforms is a set of uniform variables for the shader.
|
||||||
// The keys are the names of the uniform variables.
|
// The keys are the names of the uniform variables.
|
||||||
// The values must be float or []float.
|
// The values must be float or []float.
|
||||||
@ -645,7 +688,12 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
options = &DrawRectShaderOptions{}
|
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
|
var imgs [graphics.ShaderImageCount]*ui.Image
|
||||||
for i, img := range options.Images {
|
for i, img := range options.Images {
|
||||||
|
@ -342,7 +342,7 @@ func min(a, b int) int {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImageCompositeModeLighter(t *testing.T) {
|
func TestImageBlendLighter(t *testing.T) {
|
||||||
img0, _, err := openEbitenImage()
|
img0, _, err := openEbitenImage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -353,7 +353,7 @@ func TestImageCompositeModeLighter(t *testing.T) {
|
|||||||
img1 := ebiten.NewImage(w, h)
|
img1 := ebiten.NewImage(w, h)
|
||||||
img1.Fill(color.RGBA{0x01, 0x02, 0x03, 0x04})
|
img1.Fill(color.RGBA{0x01, 0x02, 0x03, 0x04})
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.CompositeMode = ebiten.CompositeModeLighter
|
op.Blend = ebiten.BlendLighter
|
||||||
img1.DrawImage(img0, op)
|
img1.DrawImage(img0, op)
|
||||||
for j := 0; j < img1.Bounds().Size().Y; j++ {
|
for j := 0; j < img1.Bounds().Size().Y; j++ {
|
||||||
for i := 0; i < img1.Bounds().Size().X; i++ {
|
for i := 0; i < img1.Bounds().Size().X; i++ {
|
||||||
@ -2343,7 +2343,7 @@ func TestImageColorMCopy(t *testing.T) {
|
|||||||
for k := 0; k < 256; k++ {
|
for k := 0; k < 256; k++ {
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.ColorM.Translate(1, 1, 1, float64(k)/0xff)
|
op.ColorM.Translate(1, 1, 1, float64(k)/0xff)
|
||||||
op.CompositeMode = ebiten.CompositeModeCopy
|
op.Blend = ebiten.BlendCopy
|
||||||
dst.DrawImage(src, op)
|
dst.DrawImage(src, op)
|
||||||
|
|
||||||
for j := 0; j < h; j++ {
|
for j := 0; j < h; j++ {
|
||||||
|
4
internal/processtest/testdata/issue1753.go
vendored
4
internal/processtest/testdata/issue1753.go
vendored
@ -48,7 +48,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
g.dst = ebiten.NewImage(w, h)
|
g.dst = ebiten.NewImage(w, h)
|
||||||
|
|
||||||
op := &ebiten.DrawRectShaderOptions{}
|
op := &ebiten.DrawRectShaderOptions{}
|
||||||
op.CompositeMode = ebiten.CompositeModeCopy
|
op.Blend = ebiten.BlendCopy
|
||||||
op.Uniforms = map[string]interface{}{
|
op.Uniforms = map[string]interface{}{
|
||||||
"Color": []float32{1, 1, 1, 1},
|
"Color": []float32{1, 1, 1, 1},
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
op := &ebiten.DrawRectShaderOptions{}
|
op := &ebiten.DrawRectShaderOptions{}
|
||||||
op.CompositeMode = ebiten.CompositeModeCopy
|
op.Blend = ebiten.BlendCopy
|
||||||
op.Uniforms = map[string]interface{}{
|
op.Uniforms = map[string]interface{}{
|
||||||
"Dummy": float32(0),
|
"Dummy": float32(0),
|
||||||
"R": float32(0.5),
|
"R": float32(0.5),
|
||||||
|
Loading…
Reference in New Issue
Block a user