2022-10-16 13:02:42 +02:00
// 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 {
2022-10-16 17:49:56 +02:00
// BlendFactorSourceRGB is a factor for source RGB values.
BlendFactorSourceRGB BlendFactor
2022-10-16 13:02:42 +02:00
// BlendFactorSourceAlpha is a factor for source alpha values.
BlendFactorSourceAlpha BlendFactor
2022-10-16 17:49:56 +02:00
// BlendFactorDestinationRGB is a factor for destination RGB values.
BlendFactorDestinationRGB BlendFactor
2022-10-16 13:02:42 +02:00
// BlendFactorDestinationAlpha is a factor for destination apha values.
BlendFactorDestinationAlpha BlendFactor
2022-10-16 17:49:56 +02:00
// BlendOperationRGB is an operation for source and destination RGB values.
BlendOperationRGB BlendOperation
2022-10-16 13:02:42 +02:00
// BlendOperationAlpha is an operation for source and destination alpha values.
BlendOperationAlpha BlendOperation
}
func ( b Blend ) internalBlend ( ) graphicsdriver . Blend {
return graphicsdriver . Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : b . BlendFactorSourceRGB . internalBlendFactor ( true ) ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : b . BlendFactorSourceAlpha . internalBlendFactor ( true ) ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : b . BlendFactorDestinationRGB . internalBlendFactor ( false ) ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : b . BlendFactorDestinationAlpha . internalBlendFactor ( false ) ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : b . BlendOperationRGB . internalBlendOperation ( ) ,
2022-10-16 13:02:42 +02:00
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
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB
2022-10-16 13:02:42 +02:00
)
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
2022-10-16 17:49:56 +02:00
case BlendFactorDestinationRGB :
return graphicsdriver . BlendFactorDestinationRGB
2022-10-16 13:02:42 +02:00
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
2022-10-16 16:33:16 +02:00
// BlendOperationSubtract represents subtracting the source and destination color.
// c_out = factor_src × c_src - factor_dst × c_dst
BlendOperationSubtract
// BlendOperationReverseSubtract represents subtracting the source and destination color in a reversed order.
// c_out = factor_dst × c_dst - factor_src × c_src
BlendOperationReverseSubtract
2022-10-16 13:02:42 +02:00
)
func ( b BlendOperation ) internalBlendOperation ( ) graphicsdriver . BlendOperation {
switch b {
case BlendOperationAdd :
return graphicsdriver . BlendOperationAdd
2022-10-16 16:33:16 +02:00
case BlendOperationSubtract :
return graphicsdriver . BlendOperationSubtract
case BlendOperationReverseSubtract :
return graphicsdriver . BlendOperationReverseSubtract
2022-10-16 13:02:42 +02:00
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 {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOneMinusSourceAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOneMinusSourceAlpha ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = 0
BlendClear = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src
BlendCopy = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_dst
BlendDestination = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × (1 - α _dst) + c_dst
BlendDestinationOver = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × α _dst
BlendSourceIn = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_dst × α _src
BlendDestinationIn = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorSourceAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorSourceAlpha ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × (1 - α _dst)
BlendSourceOut = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_dst × (1 - α _src)
BlendDestinationOut = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorZero ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorZero ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × α _dst + c_dst × (1 - α _src)
BlendSourceAtop = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOneMinusSourceAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOneMinusSourceAlpha ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × (1 - α _dst) + c_dst × α _src
BlendDestinationAtop = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorSourceAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorSourceAlpha ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// c_out = c_src × (1 - α _dst) + c_dst × (1 - α _src)
BlendXor = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOneMinusDestinationAlpha ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOneMinusSourceAlpha ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOneMinusSourceAlpha ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
// Sum of source and destination (a.k.a. 'plus' or 'additive')
// c_out = c_src + c_dst
BlendLighter = Blend {
2022-10-16 17:49:56 +02:00
BlendFactorSourceRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorSourceAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendFactorDestinationRGB : BlendFactorOne ,
2022-10-16 13:02:42 +02:00
BlendFactorDestinationAlpha : BlendFactorOne ,
2022-10-16 17:49:56 +02:00
BlendOperationRGB : BlendOperationAdd ,
2022-10-16 13:02:42 +02:00
BlendOperationAlpha : BlendOperationAdd ,
}
)