123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // 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 final color is calculated like this:
- //
- // c_src: source RGB values
- // c_dst: destination RGB values
- // c_out: result RGB values
- // α_src: source alpha values
- // α_dst: destination alpha values
- // α_out: result alpha values
- //
- // c_out = BlendOperationRGB((BlendFactorSourceRGB) × c_src, (BlendFactorDestinationRGB) × c_dst)
- // α_out = BlendOperationAlpha((BlendFactorSourceAlpha) × α_src, (BlendFactorDestinationAlpha) × α_dst)
- //
- // A blend factor is a factor for source and color destination color values.
- // The default is source-over (regular alpha blending).
- //
- // A blend operation is a binary operator of a source color and a destination color.
- // The default is adding.
- type Blend struct {
- // BlendFactorSourceRGB is a factor for source RGB values.
- BlendFactorSourceRGB BlendFactor
- // BlendFactorSourceAlpha is a factor for source alpha values.
- BlendFactorSourceAlpha BlendFactor
- // BlendFactorDestinationRGB is a factor for destination RGB values.
- BlendFactorDestinationRGB BlendFactor
- // BlendFactorDestinationAlpha is a factor for destination alpha values.
- BlendFactorDestinationAlpha BlendFactor
- // BlendOperationRGB is an operation for source and destination RGB values.
- BlendOperationRGB BlendOperation
- // BlendOperationAlpha is an operation for source and destination alpha values.
- BlendOperationAlpha BlendOperation
- }
- var (
- defaultBlendInternalBlend = graphicsdriver.Blend{
- BlendFactorSourceRGB: BlendFactorDefault.internalBlendFactor(true),
- BlendFactorSourceAlpha: BlendFactorDefault.internalBlendFactor(true),
- BlendFactorDestinationRGB: BlendFactorDefault.internalBlendFactor(false),
- BlendFactorDestinationAlpha: BlendFactorDefault.internalBlendFactor(false),
- BlendOperationRGB: BlendOperationAdd.internalBlendOperation(),
- BlendOperationAlpha: BlendOperationAdd.internalBlendOperation(),
- }
- )
- func (b Blend) internalBlend() graphicsdriver.Blend {
- // A shortcut for the most common blend.
- if b == (Blend{}) {
- return defaultBlendInternalBlend
- }
- return graphicsdriver.Blend{
- BlendFactorSourceRGB: b.BlendFactorSourceRGB.internalBlendFactor(true),
- BlendFactorSourceAlpha: b.BlendFactorSourceAlpha.internalBlendFactor(true),
- BlendFactorDestinationRGB: b.BlendFactorDestinationRGB.internalBlendFactor(false),
- BlendFactorDestinationAlpha: b.BlendFactorDestinationAlpha.internalBlendFactor(false),
- BlendOperationRGB: b.BlendOperationRGB.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 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
- // BlendFactorOneMinusSourceAlpha is a factor:
- //
- // 1 - (source alpha)
- BlendFactorOneMinusSourceAlpha
- // 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 {
- 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 BlendFactorSourceColor:
- return graphicsdriver.BlendFactorSourceColor
- case BlendFactorOneMinusSourceColor:
- return graphicsdriver.BlendFactorOneMinusSourceColor
- case BlendFactorSourceAlpha:
- return graphicsdriver.BlendFactorSourceAlpha
- case BlendFactorOneMinusSourceAlpha:
- return graphicsdriver.BlendFactorOneMinusSourceAlpha
- 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))
- }
- }
- // BlendOperation is an operation for source and destination color values.
- type BlendOperation byte
- const (
- // BlendOperationAdd represents adding the source and destination color.
- //
- // c_out = (BlendFactorSourceRGB) × c_src + (BlendFactorDestinationRGB) × c_dst
- // α_out = (BlendFactorSourceAlpha) × α_src + (BlendFactorDestinationAlpha) × α_dst
- BlendOperationAdd BlendOperation = iota
- // BlendOperationSubtract represents subtracting the source and destination color.
- //
- // c_out = (BlendFactorSourceRGB) × c_src - (BlendFactorDestinationRGB) × c_dst
- // α_out = (BlendFactorSourceAlpha) × α_src - (BlendFactorDestinationAlpha) × α_dst
- BlendOperationSubtract
- // BlendOperationReverseSubtract represents subtracting the source and destination color in a reversed order.
- //
- // c_out = (BlendFactorDestinationRGB) × c_dst - (BlendFactorSourceRGB) × c_src
- // α_out = (BlendFactorDestinationAlpha) × α_dst - (BlendFactorSourceAlpha) × α_src
- 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 {
- switch b {
- case BlendOperationAdd:
- return graphicsdriver.BlendOperationAdd
- case BlendOperationSubtract:
- return graphicsdriver.BlendOperationSubtract
- case BlendOperationReverseSubtract:
- return graphicsdriver.BlendOperationReverseSubtract
- case BlendOperationMin:
- return graphicsdriver.BlendOperationMin
- case BlendOperationMax:
- return graphicsdriver.BlendOperationMax
- 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 is a preset Blend for the regular alpha blending.
- //
- // c_out = c_src + c_dst × (1 - α_src)
- // α_out = α_src + α_dst × (1 - α_src)
- BlendSourceOver = Blend{
- BlendFactorSourceRGB: BlendFactorOne,
- BlendFactorSourceAlpha: BlendFactorOne,
- BlendFactorDestinationRGB: BlendFactorOneMinusSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendClear is a preset Blend for Porter Duff's 'clear'.
- //
- // c_out = 0
- // α_out = 0
- BlendClear = Blend{
- BlendFactorSourceRGB: BlendFactorZero,
- BlendFactorSourceAlpha: BlendFactorZero,
- BlendFactorDestinationRGB: BlendFactorZero,
- BlendFactorDestinationAlpha: BlendFactorZero,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendCopy is a preset Blend for Porter Duff's 'copy'.
- //
- // c_out = c_src
- // α_out = α_src
- BlendCopy = Blend{
- BlendFactorSourceRGB: BlendFactorOne,
- BlendFactorSourceAlpha: BlendFactorOne,
- BlendFactorDestinationRGB: BlendFactorZero,
- BlendFactorDestinationAlpha: BlendFactorZero,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendDestination is a preset Blend for Porter Duff's 'destination'.
- //
- // c_out = c_dst
- // α_out = α_dst
- BlendDestination = Blend{
- BlendFactorSourceRGB: BlendFactorZero,
- BlendFactorSourceAlpha: BlendFactorZero,
- BlendFactorDestinationRGB: BlendFactorOne,
- BlendFactorDestinationAlpha: BlendFactorOne,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendDestinationOver is a preset Blend for Porter Duff's 'destination-over'.
- //
- // c_out = c_src × (1 - α_dst) + c_dst
- // α_out = α_src × (1 - α_dst) + α_dst
- BlendDestinationOver = Blend{
- BlendFactorSourceRGB: BlendFactorOneMinusDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorOne,
- BlendFactorDestinationAlpha: BlendFactorOne,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendSourceIn is a preset Blend for Porter Duff's 'source-in'.
- //
- // c_out = c_src × α_dst
- // α_out = α_src × α_dst
- BlendSourceIn = Blend{
- BlendFactorSourceRGB: BlendFactorDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorZero,
- BlendFactorDestinationAlpha: BlendFactorZero,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendDestinationIn is a preset Blend for Porter Duff's 'destination-in'.
- //
- // c_out = c_dst × α_src
- // α_out = α_dst × α_src
- BlendDestinationIn = Blend{
- BlendFactorSourceRGB: BlendFactorZero,
- BlendFactorSourceAlpha: BlendFactorZero,
- BlendFactorDestinationRGB: BlendFactorSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendSourceOut is a preset Blend for Porter Duff's 'source-out'.
- //
- // c_out = c_src × (1 - α_dst)
- // α_out = α_src × (1 - α_dst)
- BlendSourceOut = Blend{
- BlendFactorSourceRGB: BlendFactorOneMinusDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorZero,
- BlendFactorDestinationAlpha: BlendFactorZero,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendDestinationOut is a preset Blend for Porter Duff's 'destination-out'.
- //
- // c_out = c_dst × (1 - α_src)
- // α_out = α_dst × (1 - α_src)
- BlendDestinationOut = Blend{
- BlendFactorSourceRGB: BlendFactorZero,
- BlendFactorSourceAlpha: BlendFactorZero,
- BlendFactorDestinationRGB: BlendFactorOneMinusSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendSourceAtop is a preset Blend for Porter Duff's 'source-atop'.
- //
- // c_out = c_src × α_dst + c_dst × (1 - α_src)
- // α_out = α_src × α_dst + α_dst × (1 - α_src)
- BlendSourceAtop = Blend{
- BlendFactorSourceRGB: BlendFactorDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorOneMinusSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendDestinationAtop is a preset Blend for Porter Duff's 'destination-atop'.
- //
- // c_out = c_src × (1 - α_dst) + c_dst × α_src
- // α_out = α_src × (1 - α_dst) + α_dst × α_src
- BlendDestinationAtop = Blend{
- BlendFactorSourceRGB: BlendFactorOneMinusDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendXor is a preset Blend for Porter Duff's 'xor'.
- //
- // c_out = c_src × (1 - α_dst) + c_dst × (1 - α_src)
- // α_out = α_src × (1 - α_dst) + α_dst × (1 - α_src)
- BlendXor = Blend{
- BlendFactorSourceRGB: BlendFactorOneMinusDestinationAlpha,
- BlendFactorSourceAlpha: BlendFactorOneMinusDestinationAlpha,
- BlendFactorDestinationRGB: BlendFactorOneMinusSourceAlpha,
- BlendFactorDestinationAlpha: BlendFactorOneMinusSourceAlpha,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- // BlendLighter is a preset Blend for Porter Duff's 'lighter'.
- // This is sum of source and destination (a.k.a. 'plus' or 'additive')
- //
- // c_out = c_src + c_dst
- // α_out = α_src + α_dst
- BlendLighter = Blend{
- BlendFactorSourceRGB: BlendFactorOne,
- BlendFactorSourceAlpha: BlendFactorOne,
- BlendFactorDestinationRGB: BlendFactorOne,
- BlendFactorDestinationAlpha: BlendFactorOne,
- BlendOperationRGB: BlendOperationAdd,
- BlendOperationAlpha: BlendOperationAdd,
- }
- )
|