mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-13 22:47:26 +01:00
internal/affine: Refactoring: Make ColorM interface
This commit is contained in:
parent
5f03f4f195
commit
21aa96f9f5
31
colorm.go
31
colorm.go
@ -32,42 +32,49 @@ const ColorMDim = affine.ColorMDim
|
|||||||
//
|
//
|
||||||
// The initial value is identity.
|
// The initial value is identity.
|
||||||
type ColorM struct {
|
type ColorM struct {
|
||||||
impl *affine.ColorM
|
impl affine.ColorM
|
||||||
|
|
||||||
_ [0]func() // Marks as non-comparable.
|
_ [0]func() // Marks as non-comparable.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ColorM) affineColorM() affine.ColorM {
|
||||||
|
if c.impl != nil {
|
||||||
|
return c.impl
|
||||||
|
}
|
||||||
|
return affine.ColorMIdentity{}
|
||||||
|
}
|
||||||
|
|
||||||
// String returns a string representation of ColorM.
|
// String returns a string representation of ColorM.
|
||||||
func (c *ColorM) String() string {
|
func (c *ColorM) String() string {
|
||||||
return c.impl.String()
|
return affine.ColorMString(c.affineColorM())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset resets the ColorM as identity.
|
// Reset resets the ColorM as identity.
|
||||||
func (c *ColorM) Reset() {
|
func (c *ColorM) Reset() {
|
||||||
c.impl = nil
|
c.impl = affine.ColorMIdentity{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply pre-multiplies a vector (r, g, b, a, 1) by the matrix
|
// Apply pre-multiplies a vector (r, g, b, a, 1) by the matrix
|
||||||
// where r, g, b, and a are clr's values in straight-alpha format.
|
// where r, g, b, and a are clr's values in straight-alpha format.
|
||||||
// In other words, Apply calculates ColorM * (r, g, b, a, 1)^T.
|
// In other words, Apply calculates ColorM * (r, g, b, a, 1)^T.
|
||||||
func (c *ColorM) Apply(clr color.Color) color.Color {
|
func (c *ColorM) Apply(clr color.Color) color.Color {
|
||||||
return c.impl.Apply(clr)
|
return c.affineColorM().Apply(clr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat multiplies a color matrix with the other color matrix.
|
// Concat multiplies a color matrix with the other color matrix.
|
||||||
// This is same as muptiplying the matrix other and the matrix c in this order.
|
// This is same as muptiplying the matrix other and the matrix c in this order.
|
||||||
func (c *ColorM) Concat(other ColorM) {
|
func (c *ColorM) Concat(other ColorM) {
|
||||||
c.impl = c.impl.Concat(other.impl)
|
c.impl = c.affineColorM().Concat(other.impl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale scales the matrix by (r, g, b, a).
|
// Scale scales the matrix by (r, g, b, a).
|
||||||
func (c *ColorM) Scale(r, g, b, a float64) {
|
func (c *ColorM) Scale(r, g, b, a float64) {
|
||||||
c.impl = c.impl.Scale(float32(r), float32(g), float32(b), float32(a))
|
c.impl = c.affineColorM().Scale(float32(r), float32(g), float32(b), float32(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate translates the matrix by (r, g, b, a).
|
// Translate translates the matrix by (r, g, b, a).
|
||||||
func (c *ColorM) Translate(r, g, b, a float64) {
|
func (c *ColorM) Translate(r, g, b, a float64) {
|
||||||
c.impl = c.impl.Translate(float32(r), float32(g), float32(b), float32(a))
|
c.impl = c.affineColorM().Translate(float32(r), float32(g), float32(b), float32(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RotateHue rotates the hue.
|
// RotateHue rotates the hue.
|
||||||
@ -83,27 +90,27 @@ func (c *ColorM) RotateHue(theta float64) {
|
|||||||
//
|
//
|
||||||
// This conversion uses RGB to/from YCrCb conversion.
|
// This conversion uses RGB to/from YCrCb conversion.
|
||||||
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) {
|
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) {
|
||||||
c.impl = c.impl.ChangeHSV(hueTheta, float32(saturationScale), float32(valueScale))
|
c.impl = affine.ChangeHSV(c.affineColorM(), hueTheta, float32(saturationScale), float32(valueScale))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Element returns a value of a matrix at (i, j).
|
// Element returns a value of a matrix at (i, j).
|
||||||
func (c *ColorM) Element(i, j int) float64 {
|
func (c *ColorM) Element(i, j int) float64 {
|
||||||
return float64(c.impl.Element(i, j))
|
return float64(affine.ColorMElement(c.affineColorM(), i, j))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetElement sets an element at (i, j).
|
// SetElement sets an element at (i, j).
|
||||||
func (c *ColorM) SetElement(i, j int, element float64) {
|
func (c *ColorM) SetElement(i, j int, element float64) {
|
||||||
c.impl = c.impl.SetElement(i, j, float32(element))
|
c.impl = affine.ColorMSetElement(c.affineColorM(), i, j, float32(element))
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsInvertible returns a boolean value indicating
|
// IsInvertible returns a boolean value indicating
|
||||||
// whether the matrix c is invertible or not.
|
// whether the matrix c is invertible or not.
|
||||||
func (c *ColorM) IsInvertible() bool {
|
func (c *ColorM) IsInvertible() bool {
|
||||||
return c.impl.IsInvertible()
|
return c.affineColorM().IsInvertible()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert inverts the matrix.
|
// Invert inverts the matrix.
|
||||||
// If c is not invertible, Invert panics.
|
// If c is not invertible, Invert panics.
|
||||||
func (c *ColorM) Invert() {
|
func (c *ColorM) Invert() {
|
||||||
c.impl = c.impl.Invert()
|
c.impl = c.affineColorM().Invert()
|
||||||
}
|
}
|
||||||
|
11
image.go
11
image.go
@ -19,6 +19,7 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
||||||
@ -213,7 +214,8 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) {
|
|||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, canSkipMipmap(options.GeoM, filter))
|
|
||||||
|
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, canSkipMipmap(options.GeoM, filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertex represents a vertex passed to DrawTriangles.
|
// Vertex represents a vertex passed to DrawTriangles.
|
||||||
@ -362,7 +364,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
|
|
||||||
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
srcs := [graphics.ShaderImageNum]*mipmap.Mipmap{img.mipmap}
|
||||||
|
|
||||||
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.impl, mode, filter, address, dstRegion, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, options.EvenOdd, false)
|
i.mipmap.DrawTriangles(srcs, vs, is, options.ColorM.affineColorM(), mode, filter, address, dstRegion, sr, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, options.EvenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
// DrawTrianglesShaderOptions represents options for DrawTrianglesShader.
|
||||||
@ -511,7 +513,8 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
}
|
}
|
||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
us := shader.convertUniforms(options.Uniforms)
|
||||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, options.EvenOdd, false)
|
|
||||||
|
i.mipmap.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, options.EvenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawRectShaderOptions represents options for DrawRectShader.
|
// DrawRectShaderOptions represents options for DrawRectShader.
|
||||||
@ -623,7 +626,7 @@ func (i *Image) DrawRectShader(width, height int, shader *Shader, options *DrawR
|
|||||||
}
|
}
|
||||||
|
|
||||||
us := shader.convertUniforms(options.Uniforms)
|
us := shader.convertUniforms(options.Uniforms)
|
||||||
i.mipmap.DrawTriangles(imgs, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, false, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
i.mipmap.DrawTriangles(imgs, vs, is, affine.ColorMIdentity{}, mode, driver.FilterNearest, driver.AddressUnsafe, dstRegion, sr, offsets, shader.shader, us, false, canSkipMipmap(options.GeoM, driver.FilterNearest))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubImage returns an image representing the portion of the image p visible through r.
|
// SubImage returns an image representing the portion of the image p visible through r.
|
||||||
|
@ -36,33 +36,41 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// A ColorM represents a matrix to transform coloring when rendering an image.
|
// ColorM represents a matrix to transform coloring when rendering an image.
|
||||||
//
|
//
|
||||||
// A ColorM is applied to the source alpha color
|
// ColorM is applied to the source alpha color
|
||||||
// while an Image's pixels' format is alpha premultiplied.
|
// while an Image's pixels' format is alpha premultiplied.
|
||||||
// Before applying a matrix, a color is un-multiplied, and after applying the matrix,
|
// Before applying a matrix, a color is un-multiplied, and after applying the matrix,
|
||||||
// the color is multiplied again.
|
// the color is multiplied again.
|
||||||
//
|
type ColorM interface {
|
||||||
// The nil and initial value is identity.
|
|
||||||
type ColorM struct {
|
|
||||||
impl colorMImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
type colorMImpl interface {
|
|
||||||
IsIdentity() bool
|
IsIdentity() bool
|
||||||
ScaleOnly() bool
|
ScaleOnly() bool
|
||||||
UnsafeScaleElements() *[4]float32
|
UnsafeScaleElements() *[4]float32
|
||||||
UnsafeElements() (*[16]float32, *[4]float32)
|
UnsafeElements() (*[16]float32, *[4]float32)
|
||||||
Apply(r, g, b, a float32) color.Color
|
Apply(clr color.Color) color.Color
|
||||||
|
|
||||||
|
// IsInvertible returns a boolean value indicating
|
||||||
|
// whether the matrix c is invertible or not.
|
||||||
IsInvertible() bool
|
IsInvertible() bool
|
||||||
Invert() *ColorM
|
|
||||||
Equals(other *ColorM) bool
|
// Invert inverts the matrix.
|
||||||
Concat(other *ColorM) *ColorM
|
// If c is not invertible, Invert panics.
|
||||||
Scale(r, g, b, a float32) *ColorM
|
Invert() ColorM
|
||||||
Translate(r, g, b, a float32) *ColorM
|
|
||||||
|
Equals(other ColorM) bool
|
||||||
|
|
||||||
|
// Concat multiplies a color matrix with the other color matrix.
|
||||||
|
// This is same as muptiplying the matrix other and the matrix c in this order.
|
||||||
|
Concat(other ColorM) ColorM
|
||||||
|
|
||||||
|
// Scale scales the matrix by (r, g, b, a).
|
||||||
|
Scale(r, g, b, a float32) ColorM
|
||||||
|
|
||||||
|
// Translate translates the matrix by (r, g, b, a).
|
||||||
|
Translate(r, g, b, a float32) ColorM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) String() string {
|
func ColorMString(c ColorM) string {
|
||||||
b, t := c.UnsafeElements()
|
b, t := c.UnsafeElements()
|
||||||
return fmt.Sprintf("[[%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f]]",
|
return fmt.Sprintf("[[%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f], [%f, %f, %f, %f, %f]]",
|
||||||
b[0], b[4], b[8], b[12], t[0],
|
b[0], b[4], b[8], b[12], t[0],
|
||||||
@ -71,6 +79,8 @@ func (c *ColorM) String() string {
|
|||||||
b[3], b[7], b[11], b[15], t[3])
|
b[3], b[7], b[11], b[15], t[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ColorMIdentity struct{}
|
||||||
|
|
||||||
type colorMImplScale struct {
|
type colorMImplScale struct {
|
||||||
scale [4]float32
|
scale [4]float32
|
||||||
}
|
}
|
||||||
@ -90,15 +100,9 @@ func clamp(x float32) float32 {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) isIdentity() bool {
|
func (c ColorMIdentity) IsIdentity() bool {
|
||||||
if c == nil {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if c.impl == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return c.impl.IsIdentity()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) IsIdentity() bool {
|
func (c *colorMImplScale) IsIdentity() bool {
|
||||||
return c.scale == [4]float32{1, 1, 1, 1}
|
return c.scale == [4]float32{1, 1, 1, 1}
|
||||||
@ -108,12 +112,9 @@ func (c *colorMImplBodyTranslate) IsIdentity() bool {
|
|||||||
return c.body == colorMIdentityBody && c.translate == colorMIdentityTranslate
|
return c.body == colorMIdentityBody && c.translate == colorMIdentityTranslate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) ScaleOnly() bool {
|
func (c ColorMIdentity) ScaleOnly() bool {
|
||||||
if c.isIdentity() {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return c.impl.ScaleOnly()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) ScaleOnly() bool {
|
func (c *colorMImplScale) ScaleOnly() bool {
|
||||||
return true
|
return true
|
||||||
@ -164,6 +165,10 @@ func (c *colorMImplBodyTranslate) ScaleOnly() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c ColorMIdentity) UnsafeScaleElements() *[4]float32 {
|
||||||
|
return &[...]float32{1, 1, 1, 1}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) UnsafeScaleElements() *[4]float32 {
|
func (c *colorMImplScale) UnsafeScaleElements() *[4]float32 {
|
||||||
return &c.scale
|
return &c.scale
|
||||||
}
|
}
|
||||||
@ -172,11 +177,7 @@ func (c *colorMImplBodyTranslate) UnsafeScaleElements() *[4]float32 {
|
|||||||
return &[...]float32{c.body[0], c.body[5], c.body[10], c.body[15]}
|
return &[...]float32{c.body[0], c.body[5], c.body[10], c.body[15]}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) Apply(clr color.Color) color.Color {
|
func colorToFloat32s(clr color.Color) (float32, float32, float32, float32) {
|
||||||
if c.isIdentity() {
|
|
||||||
return clr
|
|
||||||
}
|
|
||||||
|
|
||||||
r, g, b, a := clr.RGBA()
|
r, g, b, a := clr.RGBA()
|
||||||
rf, gf, bf, af := float32(0.0), float32(0.0), float32(0.0), float32(0.0)
|
rf, gf, bf, af := float32(0.0), float32(0.0), float32(0.0), float32(0.0)
|
||||||
// Unmultiply alpha
|
// Unmultiply alpha
|
||||||
@ -186,10 +187,21 @@ func (c *ColorM) Apply(clr color.Color) color.Color {
|
|||||||
bf = float32(b) / float32(a)
|
bf = float32(b) / float32(a)
|
||||||
af = float32(a) / 0xffff
|
af = float32(a) / 0xffff
|
||||||
}
|
}
|
||||||
return c.impl.Apply(rf, gf, bf, af)
|
return rf, gf, bf, af
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Apply(rf, gf, bf, af float32) color.Color {
|
func (c ColorMIdentity) Apply(clr color.Color) color.Color {
|
||||||
|
rf, gf, bf, af := colorToFloat32s(clr)
|
||||||
|
return color.NRGBA64{
|
||||||
|
R: uint16(rf * 0xffff),
|
||||||
|
G: uint16(gf * 0xffff),
|
||||||
|
B: uint16(bf * 0xffff),
|
||||||
|
A: uint16(af * 0xffff),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *colorMImplScale) Apply(clr color.Color) color.Color {
|
||||||
|
rf, gf, bf, af := colorToFloat32s(clr)
|
||||||
rf *= c.scale[0]
|
rf *= c.scale[0]
|
||||||
gf *= c.scale[1]
|
gf *= c.scale[1]
|
||||||
bf *= c.scale[2]
|
bf *= c.scale[2]
|
||||||
@ -206,7 +218,8 @@ func (c *colorMImplScale) Apply(rf, gf, bf, af float32) color.Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Apply(rf, gf, bf, af float32) color.Color {
|
func (c *colorMImplBodyTranslate) Apply(clr color.Color) color.Color {
|
||||||
|
rf, gf, bf, af := colorToFloat32s(clr)
|
||||||
eb := &c.body
|
eb := &c.body
|
||||||
et := &c.translate
|
et := &c.translate
|
||||||
rf2 := eb[0]*rf + eb[4]*gf + eb[8]*bf + eb[12]*af + et[0]
|
rf2 := eb[0]*rf + eb[4]*gf + eb[8]*bf + eb[12]*af + et[0]
|
||||||
@ -225,12 +238,9 @@ func (c *colorMImplBodyTranslate) Apply(rf, gf, bf, af float32) color.Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) UnsafeElements() (*[16]float32, *[4]float32) {
|
func (c ColorMIdentity) UnsafeElements() (*[16]float32, *[4]float32) {
|
||||||
if c.isIdentity() {
|
|
||||||
return &colorMIdentityBody, &colorMIdentityTranslate
|
return &colorMIdentityBody, &colorMIdentityTranslate
|
||||||
}
|
}
|
||||||
return c.impl.UnsafeElements()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) UnsafeElements() (*[16]float32, *[4]float32) {
|
func (c *colorMImplScale) UnsafeElements() (*[16]float32, *[4]float32) {
|
||||||
return &[...]float32{
|
return &[...]float32{
|
||||||
@ -276,14 +286,9 @@ func (c *colorMImplBodyTranslate) det() float32 {
|
|||||||
m03*(m10*b124234-m11*b024234+m12*b014234)
|
m03*(m10*b124234-m11*b024234+m12*b014234)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsInvertible returns a boolean value indicating
|
func (c ColorMIdentity) IsInvertible() bool {
|
||||||
// whether the matrix c is invertible or not.
|
|
||||||
func (c *ColorM) IsInvertible() bool {
|
|
||||||
if c.isIdentity() {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return c.impl.IsInvertible()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) IsInvertible() bool {
|
func (c *colorMImplScale) IsInvertible() bool {
|
||||||
return c.scale[0] != 0 && c.scale[1] != 0 && c.scale[2] != 0 && c.scale[3] != 0
|
return c.scale[0] != 0 && c.scale[1] != 0 && c.scale[2] != 0 && c.scale[3] != 0
|
||||||
@ -293,29 +298,22 @@ func (c *colorMImplBodyTranslate) IsInvertible() bool {
|
|||||||
return c.det() != 0
|
return c.det() != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert inverts the matrix.
|
func (c ColorMIdentity) Invert() ColorM {
|
||||||
// If c is not invertible, Invert panics.
|
return c
|
||||||
func (c *ColorM) Invert() *ColorM {
|
|
||||||
if c.isIdentity() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return c.impl.Invert()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Invert() *ColorM {
|
func (c *colorMImplScale) Invert() ColorM {
|
||||||
return &ColorM{
|
return &colorMImplScale{
|
||||||
impl: &colorMImplScale{
|
|
||||||
scale: [4]float32{
|
scale: [4]float32{
|
||||||
1 / c.scale[0],
|
1 / c.scale[0],
|
||||||
1 / c.scale[1],
|
1 / c.scale[1],
|
||||||
1 / c.scale[2],
|
1 / c.scale[2],
|
||||||
1 / c.scale[3],
|
1 / c.scale[3],
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Invert() *ColorM {
|
func (c *colorMImplBodyTranslate) Invert() ColorM {
|
||||||
det := c.det()
|
det := c.det()
|
||||||
if det == 0 {
|
if det == 0 {
|
||||||
panic("affine: c is not invertible")
|
panic("affine: c is not invertible")
|
||||||
@ -417,13 +415,11 @@ func (c *colorMImplBodyTranslate) Invert() *ColorM {
|
|||||||
m.translate[2] = idet * (m00*b123134 - m01*b023134 + m02*b013134 - m03*b012134)
|
m.translate[2] = idet * (m00*b123134 - m01*b023134 + m02*b013134 - m03*b012134)
|
||||||
m.translate[3] = idet * -(m00*b123124 - m01*b023124 + m02*b013124 - m03*b012124)
|
m.translate[3] = idet * -(m00*b123124 - m01*b023124 + m02*b013124 - m03*b012124)
|
||||||
|
|
||||||
return &ColorM{
|
return m
|
||||||
impl: m,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Element returns a value of a matrix at (i, j).
|
// ColorMElement returns a value of a matrix at (i, j).
|
||||||
func (c *ColorM) Element(i, j int) float32 {
|
func ColorMElement(c ColorM, i, j int) float32 {
|
||||||
b, t := c.UnsafeElements()
|
b, t := c.UnsafeElements()
|
||||||
if j < ColorMDim-1 {
|
if j < ColorMDim-1 {
|
||||||
return b[i+j*(ColorMDim-1)]
|
return b[i+j*(ColorMDim-1)]
|
||||||
@ -431,13 +427,13 @@ func (c *ColorM) Element(i, j int) float32 {
|
|||||||
return t[i]
|
return t[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetElement sets an element at (i, j).
|
// ColorMSetElement sets an element at (i, j).
|
||||||
func (c *ColorM) SetElement(i, j int, element float32) *ColorM {
|
func ColorMSetElement(c ColorM, i, j int, element float32) ColorM {
|
||||||
newImpl := &colorMImplBodyTranslate{
|
newImpl := &colorMImplBodyTranslate{
|
||||||
body: colorMIdentityBody,
|
body: colorMIdentityBody,
|
||||||
}
|
}
|
||||||
if !c.isIdentity() {
|
if !c.IsIdentity() {
|
||||||
b, t := c.impl.UnsafeElements()
|
b, t := c.UnsafeElements()
|
||||||
newImpl.body = *b
|
newImpl.body = *b
|
||||||
newImpl.translate = *t
|
newImpl.translate = *t
|
||||||
}
|
}
|
||||||
@ -446,26 +442,18 @@ func (c *ColorM) SetElement(i, j int, element float32) *ColorM {
|
|||||||
} else {
|
} else {
|
||||||
newImpl.translate[i] = element
|
newImpl.translate[i] = element
|
||||||
}
|
}
|
||||||
return &ColorM{
|
return newImpl
|
||||||
impl: newImpl,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ColorM) Equals(other *ColorM) bool {
|
func (c ColorMIdentity) Equals(other ColorM) bool {
|
||||||
if c.isIdentity() {
|
return other.IsIdentity()
|
||||||
return other.isIdentity()
|
|
||||||
}
|
|
||||||
if other.isIdentity() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return c.impl.Equals(other)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplScale) Equals(other *ColorM) bool {
|
func (c *colorMImplScale) Equals(other ColorM) bool {
|
||||||
if !other.impl.ScaleOnly() {
|
if !other.ScaleOnly() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i, s := range other.impl.UnsafeScaleElements() {
|
for i, s := range other.UnsafeScaleElements() {
|
||||||
if c.scale[i] != s {
|
if c.scale[i] != s {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -473,35 +461,30 @@ func (c *colorMImplScale) Equals(other *ColorM) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Equals(other *ColorM) bool {
|
func (c *colorMImplBodyTranslate) Equals(other ColorM) bool {
|
||||||
lhsb, lhst := other.impl.UnsafeElements()
|
lhsb, lhst := other.UnsafeElements()
|
||||||
rhsb := &c.body
|
rhsb := &c.body
|
||||||
rhst := &c.translate
|
rhst := &c.translate
|
||||||
return *lhsb == *rhsb && *lhst == *rhst
|
return *lhsb == *rhsb && *lhst == *rhst
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concat multiplies a color matrix with the other color matrix.
|
func (c ColorMIdentity) Concat(other ColorM) ColorM {
|
||||||
// This is same as muptiplying the matrix other and the matrix c in this order.
|
|
||||||
func (c *ColorM) Concat(other *ColorM) *ColorM {
|
|
||||||
if c.isIdentity() {
|
|
||||||
return other
|
return other
|
||||||
}
|
}
|
||||||
if other.isIdentity() {
|
|
||||||
|
func (c *colorMImplScale) Concat(other ColorM) ColorM {
|
||||||
|
if other.IsIdentity() {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
return c.impl.Concat(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) Concat(other *ColorM) *ColorM {
|
|
||||||
if other.ScaleOnly() {
|
if other.ScaleOnly() {
|
||||||
s := other.impl.UnsafeScaleElements()
|
s := other.UnsafeScaleElements()
|
||||||
return c.Scale(s[0], s[1], s[2], s[3])
|
return c.Scale(s[0], s[1], s[2], s[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
lhsb, lhst := other.impl.UnsafeElements()
|
lhsb, lhst := other.UnsafeElements()
|
||||||
s := &c.scale
|
s := &c.scale
|
||||||
return &ColorM{
|
return &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
lhsb[0] * s[0], lhsb[1] * s[0], lhsb[2] * s[0], lhsb[3] * s[0],
|
lhsb[0] * s[0], lhsb[1] * s[0], lhsb[2] * s[0], lhsb[3] * s[0],
|
||||||
lhsb[4] * s[1], lhsb[5] * s[1], lhsb[6] * s[1], lhsb[7] * s[1],
|
lhsb[4] * s[1], lhsb[5] * s[1], lhsb[6] * s[1], lhsb[7] * s[1],
|
||||||
@ -509,17 +492,19 @@ func (c *colorMImplScale) Concat(other *ColorM) *ColorM {
|
|||||||
lhsb[12] * s[3], lhsb[13] * s[3], lhsb[14] * s[3], lhsb[15] * s[3],
|
lhsb[12] * s[3], lhsb[13] * s[3], lhsb[14] * s[3], lhsb[15] * s[3],
|
||||||
},
|
},
|
||||||
translate: *lhst,
|
translate: *lhst,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Concat(other *ColorM) *ColorM {
|
func (c *colorMImplBodyTranslate) Concat(other ColorM) ColorM {
|
||||||
lhsb, lhst := other.impl.UnsafeElements()
|
if other.IsIdentity() {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
lhsb, lhst := other.UnsafeElements()
|
||||||
rhsb := &c.body
|
rhsb := &c.body
|
||||||
rhst := &c.translate
|
rhst := &c.translate
|
||||||
|
|
||||||
return &ColorM{
|
return &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
// TODO: This is a temporary hack to calculate multiply of transposed matrices.
|
// TODO: This is a temporary hack to calculate multiply of transposed matrices.
|
||||||
// Fix mulSquare implmentation and swap the arguments.
|
// Fix mulSquare implmentation and swap the arguments.
|
||||||
body: mulSquare(rhsb, lhsb, ColorMDim-1),
|
body: mulSquare(rhsb, lhsb, ColorMDim-1),
|
||||||
@ -529,36 +514,30 @@ func (c *colorMImplBodyTranslate) Concat(other *ColorM) *ColorM {
|
|||||||
lhsb[2]*rhst[0] + lhsb[6]*rhst[1] + lhsb[10]*rhst[2] + lhsb[14]*rhst[3] + lhst[2],
|
lhsb[2]*rhst[0] + lhsb[6]*rhst[1] + lhsb[10]*rhst[2] + lhsb[14]*rhst[3] + lhst[2],
|
||||||
lhsb[3]*rhst[0] + lhsb[7]*rhst[1] + lhsb[11]*rhst[2] + lhsb[15]*rhst[3] + lhst[3],
|
lhsb[3]*rhst[0] + lhsb[7]*rhst[1] + lhsb[11]*rhst[2] + lhsb[15]*rhst[3] + lhst[3],
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale scales the matrix by (r, g, b, a).
|
func (c ColorMIdentity) Scale(r, g, b, a float32) ColorM {
|
||||||
func (c *ColorM) Scale(r, g, b, a float32) *ColorM {
|
|
||||||
if c.isIdentity() {
|
|
||||||
return getCachedScalingColorM(r, g, b, a)
|
return getCachedScalingColorM(r, g, b, a)
|
||||||
}
|
}
|
||||||
if c.ScaleOnly() {
|
|
||||||
s := c.impl.UnsafeScaleElements()
|
|
||||||
return getCachedScalingColorM(r*s[0], g*s[1], b*s[2], a*s[3])
|
|
||||||
}
|
|
||||||
return c.impl.Scale(r, g, b, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) Scale(r, g, b, a float32) *ColorM {
|
func (c *colorMImplScale) Scale(r, g, b, a float32) ColorM {
|
||||||
return &ColorM{
|
return &colorMImplScale{
|
||||||
impl: &colorMImplScale{
|
|
||||||
scale: [...]float32{
|
scale: [...]float32{
|
||||||
c.scale[0] * r,
|
c.scale[0] * r,
|
||||||
c.scale[1] * g,
|
c.scale[1] * g,
|
||||||
c.scale[2] * b,
|
c.scale[2] * b,
|
||||||
c.scale[3] * a,
|
c.scale[3] * a,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Scale(r, g, b, a float32) *ColorM {
|
func (c *colorMImplBodyTranslate) Scale(r, g, b, a float32) ColorM {
|
||||||
|
if c.ScaleOnly() {
|
||||||
|
s := c.UnsafeScaleElements()
|
||||||
|
return getCachedScalingColorM(r*s[0], g*s[1], b*s[2], a*s[3])
|
||||||
|
}
|
||||||
|
|
||||||
eb := c.body
|
eb := c.body
|
||||||
for i := 0; i < ColorMDim-1; i++ {
|
for i := 0; i < ColorMDim-1; i++ {
|
||||||
eb[i*(ColorMDim-1)] *= r
|
eb[i*(ColorMDim-1)] *= r
|
||||||
@ -574,30 +553,21 @@ func (c *colorMImplBodyTranslate) Scale(r, g, b, a float32) *ColorM {
|
|||||||
c.translate[3] * a,
|
c.translate[3] * a,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ColorM{
|
return &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: eb,
|
body: eb,
|
||||||
translate: et,
|
translate: et,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate translates the matrix by (r, g, b, a).
|
func (c ColorMIdentity) Translate(r, g, b, a float32) ColorM {
|
||||||
func (c *ColorM) Translate(r, g, b, a float32) *ColorM {
|
return &colorMImplBodyTranslate{
|
||||||
if c.isIdentity() {
|
|
||||||
return &ColorM{
|
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: colorMIdentityBody,
|
body: colorMIdentityBody,
|
||||||
translate: [...]float32{r, g, b, a},
|
translate: [...]float32{r, g, b, a},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c.impl.Translate(r, g, b, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *colorMImplScale) Translate(r, g, b, a float32) *ColorM {
|
func (c *colorMImplScale) Translate(r, g, b, a float32) ColorM {
|
||||||
return &ColorM{
|
return &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
c.scale[0], 0, 0, 0,
|
c.scale[0], 0, 0, 0,
|
||||||
0, c.scale[1], 0, 0,
|
0, c.scale[1], 0, 0,
|
||||||
@ -605,21 +575,18 @@ func (c *colorMImplScale) Translate(r, g, b, a float32) *ColorM {
|
|||||||
0, 0, 0, c.scale[3],
|
0, 0, 0, c.scale[3],
|
||||||
},
|
},
|
||||||
translate: [...]float32{r, g, b, a},
|
translate: [...]float32{r, g, b, a},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *colorMImplBodyTranslate) Translate(r, g, b, a float32) *ColorM {
|
func (c *colorMImplBodyTranslate) Translate(r, g, b, a float32) ColorM {
|
||||||
es := c.translate
|
es := c.translate
|
||||||
es[0] += r
|
es[0] += r
|
||||||
es[1] += g
|
es[1] += g
|
||||||
es[2] += b
|
es[2] += b
|
||||||
es[3] += a
|
es[3] += a
|
||||||
return &ColorM{
|
return &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: c.body,
|
body: c.body,
|
||||||
translate: es,
|
translate: es,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -629,25 +596,21 @@ var (
|
|||||||
// Cb: [-0.5 - 0.5]
|
// Cb: [-0.5 - 0.5]
|
||||||
// Cr: [-0.5 - 0.5]
|
// Cr: [-0.5 - 0.5]
|
||||||
|
|
||||||
rgbToYCbCr = &ColorM{
|
rgbToYCbCr = &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
0.2990, -0.1687, 0.5000, 0,
|
0.2990, -0.1687, 0.5000, 0,
|
||||||
0.5870, -0.3313, -0.4187, 0,
|
0.5870, -0.3313, -0.4187, 0,
|
||||||
0.1140, 0.5000, -0.0813, 0,
|
0.1140, 0.5000, -0.0813, 0,
|
||||||
0, 0, 0, 1,
|
0, 0, 0, 1,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
yCbCrToRgb = &ColorM{
|
yCbCrToRgb = &colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
1, 1, 1, 0,
|
1, 1, 1, 0,
|
||||||
0, -0.34414, 1.77200, 0,
|
0, -0.34414, 1.77200, 0,
|
||||||
1.40200, -0.71414, 0, 0,
|
1.40200, -0.71414, 0, 0,
|
||||||
0, 0, 0, 1,
|
0, 0, 0, 1,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -657,19 +620,17 @@ var (
|
|||||||
// valueScale is a value to scale value (a.k.a. brightness).
|
// valueScale is a value to scale value (a.k.a. brightness).
|
||||||
//
|
//
|
||||||
// This conversion uses RGB to/from YCrCb conversion.
|
// This conversion uses RGB to/from YCrCb conversion.
|
||||||
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float32, valueScale float32) *ColorM {
|
func ChangeHSV(c ColorM, hueTheta float64, saturationScale float32, valueScale float32) ColorM {
|
||||||
sin, cos := math.Sincos(hueTheta)
|
sin, cos := math.Sincos(hueTheta)
|
||||||
s32, c32 := float32(sin), float32(cos)
|
s32, c32 := float32(sin), float32(cos)
|
||||||
c = c.Concat(rgbToYCbCr)
|
c = c.Concat(rgbToYCbCr)
|
||||||
c = c.Concat(&ColorM{
|
c = c.Concat(&colorMImplBodyTranslate{
|
||||||
impl: &colorMImplBodyTranslate{
|
|
||||||
body: [...]float32{
|
body: [...]float32{
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, c32, s32, 0,
|
0, c32, s32, 0,
|
||||||
0, -s32, c32, 0,
|
0, -s32, c32, 0,
|
||||||
0, 0, 0, 1,
|
0, 0, 0, 1,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
})
|
})
|
||||||
s := saturationScale
|
s := saturationScale
|
||||||
v := valueScale
|
v := valueScale
|
||||||
@ -683,7 +644,7 @@ type cachedScalingColorMKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cachedScalingColorMValue struct {
|
type cachedScalingColorMValue struct {
|
||||||
c *ColorM
|
c *colorMImplScale
|
||||||
atime uint64
|
atime uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +654,7 @@ var (
|
|||||||
cacheMonotonicClock uint64
|
cacheMonotonicClock uint64
|
||||||
)
|
)
|
||||||
|
|
||||||
func getCachedScalingColorM(r, g, b, a float32) *ColorM {
|
func getCachedScalingColorM(r, g, b, a float32) ColorM {
|
||||||
key := cachedScalingColorMKey{r, g, b, a}
|
key := cachedScalingColorMKey{r, g, b, a}
|
||||||
|
|
||||||
cachedScalingColorMM.Lock()
|
cachedScalingColorMM.Lock()
|
||||||
@ -722,11 +683,9 @@ func getCachedScalingColorM(r, g, b, a float32) *ColorM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v := &cachedScalingColorMValue{
|
v := &cachedScalingColorMValue{
|
||||||
c: &ColorM{
|
c: &colorMImplScale{
|
||||||
impl: &colorMImplScale{
|
|
||||||
scale: [...]float32{r, g, b, a},
|
scale: [...]float32{r, g, b, a},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
atime: now,
|
atime: now,
|
||||||
}
|
}
|
||||||
cachedScalingColorM[key] = v
|
cachedScalingColorM[key] = v
|
||||||
|
@ -24,26 +24,26 @@ import (
|
|||||||
|
|
||||||
func TestColorMScale(t *testing.T) {
|
func TestColorMScale(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In *ColorM
|
In ColorM
|
||||||
Out *ColorM
|
Out ColorM
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
nil,
|
ColorMIdentity{},
|
||||||
(*ColorM)(nil).Scale(0.25, 0.5, 0.75, 1),
|
ColorMIdentity{}.Scale(0.25, 0.5, 0.75, 1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(0.5, 0.5, 0.5, 0.8),
|
ColorMIdentity{}.Scale(0.5, 0.5, 0.5, 0.8),
|
||||||
(*ColorM)(nil).Scale(0.125, 0.25, 0.375, 0.8),
|
ColorMIdentity{}.Scale(0.125, 0.25, 0.375, 0.8),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Translate(0, 0, 0, 0),
|
ColorMIdentity{}.Translate(0, 0, 0, 0),
|
||||||
(*ColorM)(nil).Scale(0.25, 0.5, 0.75, 1),
|
ColorMIdentity{}.Scale(0.25, 0.5, 0.75, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
got := c.In.Scale(0.25, 0.5, 0.75, 1)
|
got := c.In.Scale(0.25, 0.5, 0.75, 1)
|
||||||
want := c.Out
|
want := c.Out
|
||||||
if got != want {
|
if !got.Equals(want) {
|
||||||
t.Errorf("%v.Scale(): got: %v, want: %v", c.In, got, want)
|
t.Errorf("%v.Scale(): got: %v, want: %v", c.In, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,51 +51,51 @@ func TestColorMScale(t *testing.T) {
|
|||||||
|
|
||||||
func TestColorMScaleOnly(t *testing.T) {
|
func TestColorMScaleOnly(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In *ColorM
|
In ColorM
|
||||||
Out bool
|
Out bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
nil,
|
ColorMIdentity{},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Translate(0, 0, 0, 0),
|
ColorMIdentity{}.Translate(0, 0, 0, 0),
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Translate(1, 0, 0, 0),
|
ColorMIdentity{}.Translate(1, 0, 0, 0),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Translate(0, 0, 0, -1),
|
ColorMIdentity{}.Translate(0, 0, 0, -1),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(1, 1, 1, 1),
|
ColorMIdentity{}.Scale(1, 1, 1, 1),
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(0, 0, 0, 0),
|
ColorMIdentity{}.Scale(0, 0, 0, 0),
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(0.1, 0.2, 0.3, 0.4),
|
ColorMIdentity{}.Scale(0.1, 0.2, 0.3, 0.4),
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(0.1, 0.2, 0.3, 0.4).Translate(1, 0, 0, 0),
|
ColorMIdentity{}.Scale(0.1, 0.2, 0.3, 0.4).Translate(1, 0, 0, 0),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).ChangeHSV(math.Pi/2, 0.5, 0.5),
|
ChangeHSV(ColorMIdentity{}, math.Pi/2, 0.5, 0.5),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).SetElement(0, 0, 2),
|
ColorMSetElement(ColorMIdentity{}, 0, 0, 2),
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).SetElement(0, 1, 2),
|
ColorMSetElement(ColorMIdentity{}, 0, 1, 2),
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -109,28 +109,24 @@ func TestColorMScaleOnly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestColorMIsInvertible(t *testing.T) {
|
func TestColorMIsInvertible(t *testing.T) {
|
||||||
m := &ColorM{}
|
var m ColorM = ColorMIdentity{}
|
||||||
m = m.SetElement(1, 0, .5)
|
m = ColorMSetElement(m, 1, 0, .5)
|
||||||
m = m.SetElement(1, 1, .5)
|
m = ColorMSetElement(m, 1, 1, .5)
|
||||||
m = m.SetElement(1, 2, .5)
|
m = ColorMSetElement(m, 1, 2, .5)
|
||||||
m = m.SetElement(1, 3, .5)
|
m = ColorMSetElement(m, 1, 3, .5)
|
||||||
m = m.SetElement(1, 4, .5)
|
m = ColorMSetElement(m, 1, 4, .5)
|
||||||
|
|
||||||
cidentity := &ColorM{}
|
var cidentity ColorM = ColorMIdentity{}
|
||||||
cinvalid := &ColorM{}
|
var cinvalid ColorM = ColorMIdentity{}
|
||||||
cinvalid = cinvalid.SetElement(0, 0, 0)
|
cinvalid = ColorMSetElement(cinvalid, 0, 0, 0)
|
||||||
cinvalid = cinvalid.SetElement(1, 1, 0)
|
cinvalid = ColorMSetElement(cinvalid, 1, 1, 0)
|
||||||
cinvalid = cinvalid.SetElement(2, 2, 0)
|
cinvalid = ColorMSetElement(cinvalid, 2, 2, 0)
|
||||||
cinvalid = cinvalid.SetElement(3, 3, 0)
|
cinvalid = ColorMSetElement(cinvalid, 3, 3, 0)
|
||||||
|
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In *ColorM
|
In ColorM
|
||||||
Out bool
|
Out bool
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
nil,
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
cidentity,
|
cidentity,
|
||||||
true,
|
true,
|
||||||
@ -153,11 +149,11 @@ func TestColorMIsInvertible(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func arrayToColorM(es [4][5]float32) *ColorM {
|
func arrayToColorM(es [4][5]float32) ColorM {
|
||||||
var a = &ColorM{}
|
var a ColorM = ColorMIdentity{}
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
a = a.SetElement(i, j, es[i][j])
|
a = ColorMSetElement(a, i, j, es[i][j])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
@ -170,11 +166,11 @@ func abs(x float32) float32 {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func equalWithDelta(a, b *ColorM, delta float32) bool {
|
func equalWithDelta(a, b ColorM, delta float32) bool {
|
||||||
for j := 0; j < 5; j++ {
|
for j := 0; j < 5; j++ {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
ea := a.Element(i, j)
|
ea := ColorMElement(a, i, j)
|
||||||
eb := b.Element(i, j)
|
eb := ColorMElement(b, i, j)
|
||||||
if abs(ea-eb) > delta {
|
if abs(ea-eb) > delta {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -185,12 +181,12 @@ func equalWithDelta(a, b *ColorM, delta float32) bool {
|
|||||||
|
|
||||||
func TestColorMInvert(t *testing.T) {
|
func TestColorMInvert(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In *ColorM
|
In ColorM
|
||||||
Out *ColorM
|
Out ColorM
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
In: nil,
|
In: ColorMIdentity{},
|
||||||
Out: nil,
|
Out: ColorMIdentity{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
In: arrayToColorM([4][5]float32{
|
In: arrayToColorM([4][5]float32{
|
||||||
@ -207,7 +203,7 @@ func TestColorMInvert(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
In: (*ColorM)(nil).Scale(1, 2, 4, 8),
|
In: ColorMIdentity{}.Scale(1, 2, 4, 8),
|
||||||
Out: arrayToColorM([4][5]float32{
|
Out: arrayToColorM([4][5]float32{
|
||||||
{1, 0, 0, 0, 0},
|
{1, 0, 0, 0, 0},
|
||||||
{0, 0.5, 0, 0, 0},
|
{0, 0.5, 0, 0, 0},
|
||||||
@ -256,8 +252,8 @@ func BenchmarkColorMInvert(b *testing.B) {
|
|||||||
r := rand.Float32
|
r := rand.Float32
|
||||||
|
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
var m *ColorM
|
var m ColorM = ColorMIdentity{}
|
||||||
for m == nil || !m.IsInvertible() {
|
for m.IsIdentity() || !m.IsInvertible() {
|
||||||
m = arrayToColorM([4][5]float32{
|
m = arrayToColorM([4][5]float32{
|
||||||
{r(), r(), r(), r(), r() * 10},
|
{r(), r(), r(), r(), r() * 10},
|
||||||
{r(), r(), r(), r(), r() * 10},
|
{r(), r(), r(), r(), r() * 10},
|
||||||
@ -274,24 +270,24 @@ func BenchmarkColorMInvert(b *testing.B) {
|
|||||||
|
|
||||||
func TestColorMConcat(t *testing.T) {
|
func TestColorMConcat(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In0 *ColorM
|
In0 ColorM
|
||||||
In1 *ColorM
|
In1 ColorM
|
||||||
Out *ColorM
|
Out ColorM
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
nil,
|
ColorMIdentity{},
|
||||||
nil,
|
ColorMIdentity{},
|
||||||
nil,
|
ColorMIdentity{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(1, 2, 3, 4),
|
ColorMIdentity{}.Scale(1, 2, 3, 4),
|
||||||
(*ColorM)(nil).Scale(5, 6, 7, 8),
|
ColorMIdentity{}.Scale(5, 6, 7, 8),
|
||||||
(*ColorM)(nil).Scale(5, 12, 21, 32),
|
ColorMIdentity{}.Scale(5, 12, 21, 32),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(5, 6, 7, 8),
|
ColorMIdentity{}.Scale(5, 6, 7, 8),
|
||||||
(*ColorM)(nil).Scale(1, 2, 3, 4),
|
ColorMIdentity{}.Scale(1, 2, 3, 4),
|
||||||
(*ColorM)(nil).Scale(5, 12, 21, 32),
|
ColorMIdentity{}.Scale(5, 12, 21, 32),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arrayToColorM([4][5]float32{
|
arrayToColorM([4][5]float32{
|
||||||
@ -300,7 +296,7 @@ func TestColorMConcat(t *testing.T) {
|
|||||||
{4, 5, 1, 2, 3},
|
{4, 5, 1, 2, 3},
|
||||||
{3, 4, 5, 1, 2},
|
{3, 4, 5, 1, 2},
|
||||||
}),
|
}),
|
||||||
(*ColorM)(nil).Scale(1, 2, 3, 4),
|
ColorMIdentity{}.Scale(1, 2, 3, 4),
|
||||||
arrayToColorM([4][5]float32{
|
arrayToColorM([4][5]float32{
|
||||||
{1, 2, 3, 4, 5},
|
{1, 2, 3, 4, 5},
|
||||||
{10, 2, 4, 6, 8},
|
{10, 2, 4, 6, 8},
|
||||||
@ -309,7 +305,7 @@ func TestColorMConcat(t *testing.T) {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
(*ColorM)(nil).Scale(1, 2, 3, 4),
|
ColorMIdentity{}.Scale(1, 2, 3, 4),
|
||||||
arrayToColorM([4][5]float32{
|
arrayToColorM([4][5]float32{
|
||||||
{1, 2, 3, 4, 5},
|
{1, 2, 3, 4, 5},
|
||||||
{5, 1, 2, 3, 4},
|
{5, 1, 2, 3, 4},
|
||||||
|
@ -298,7 +298,7 @@ func (i *Image) ensureIsolated() {
|
|||||||
Width: float32(w - 2*paddingSize),
|
Width: float32(w - 2*paddingSize),
|
||||||
Height: float32(h - 2*paddingSize),
|
Height: float32(h - 2*paddingSize),
|
||||||
}
|
}
|
||||||
newImg.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil, false)
|
newImg.DrawTriangles(srcs, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil, false)
|
||||||
|
|
||||||
i.dispose(false)
|
i.dispose(false)
|
||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
@ -354,7 +354,7 @@ func (i *Image) putOnAtlas() error {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
newI.drawTriangles([graphics.ShaderImageNum]*Image{i}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, true)
|
newI.drawTriangles([graphics.ShaderImageNum]*Image{i}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
newI.moveTo(i)
|
newI.moveTo(i)
|
||||||
@ -402,13 +402,13 @@ func (i *Image) processSrc(src *Image) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
i.drawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false)
|
i.drawTriangles(srcs, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, shader, uniforms, evenOdd, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, keepOnAtlas bool) {
|
func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, keepOnAtlas bool) {
|
||||||
if i.disposed {
|
if i.disposed {
|
||||||
panic("atlas: the drawing target image must not be disposed (DrawTriangles)")
|
panic("atlas: the drawing target image must not be disposed (DrawTriangles)")
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
. "github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
. "github.com/hajimehoshi/ebiten/v2/internal/atlas"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
@ -102,7 +103,7 @@ func TestEnsureIsolated(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
want := false
|
want := false
|
||||||
if got := img4.IsOnAtlasForTesting(); got != want {
|
if got := img4.IsOnAtlasForTesting(); got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
@ -132,7 +133,7 @@ func TestEnsureIsolated(t *testing.T) {
|
|||||||
|
|
||||||
// Check further drawing doesn't cause panic.
|
// Check further drawing doesn't cause panic.
|
||||||
// This bug was fixed by 03dcd948.
|
// This bug was fixed by 03dcd948.
|
||||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReputOnAtlas(t *testing.T) {
|
func TestReputOnAtlas(t *testing.T) {
|
||||||
@ -179,7 +180,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -191,7 +192,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
if err := PutImagesOnAtlasForTesting(); err != nil {
|
if err := PutImagesOnAtlasForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -219,7 +220,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// img1 is on an atlas again.
|
// img1 is on an atlas again.
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), true; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), true; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -243,7 +244,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img1 as a render target again.
|
// Use img1 as a render target again.
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -255,7 +256,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
img1.ReplacePixels(make([]byte, 4*size*size))
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -265,7 +266,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// img1 is not on an atlas due to ReplacePixels.
|
// img1 is not on an atlas due to ReplacePixels.
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img1.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -275,7 +276,7 @@ func TestReputOnAtlas(t *testing.T) {
|
|||||||
if err := PutImagesOnAtlasForTesting(); err != nil {
|
if err := PutImagesOnAtlasForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -375,7 +376,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
dst.ReplacePixels(pix)
|
dst.ReplacePixels(pix)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
@ -423,7 +424,7 @@ func TestSmallImages(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, w, h)
|
pix, err := dst.Pixels(0, 0, w, h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -471,7 +472,7 @@ func TestLongImages(t *testing.T) {
|
|||||||
Width: dstW,
|
Width: dstW,
|
||||||
Height: dstH,
|
Height: dstH,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
|
|
||||||
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -559,7 +560,7 @@ func TestDisposedAndReputOnAtlas(t *testing.T) {
|
|||||||
Width: size,
|
Width: size,
|
||||||
Height: size,
|
Height: size,
|
||||||
}
|
}
|
||||||
src.DrawTriangles([graphics.ShaderImageNum]*Image{src2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
src.DrawTriangles([graphics.ShaderImageNum]*Image{src2}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -569,7 +570,7 @@ func TestDisposedAndReputOnAtlas(t *testing.T) {
|
|||||||
if err := PutImagesOnAtlasForTesting(); err != nil {
|
if err := PutImagesOnAtlasForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -609,7 +610,7 @@ func TestImageIsNotReputOnAtlasWithoutUsingAsSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use src2 as a rendering target, and make src2 an independent image.
|
// Use src2 as a rendering target, and make src2 an independent image.
|
||||||
src2.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
src2.DrawTriangles([graphics.ShaderImageNum]*Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
@ -630,7 +631,7 @@ func TestImageIsNotReputOnAtlasWithoutUsingAsSource(t *testing.T) {
|
|||||||
if err := PutImagesOnAtlasForTesting(); err != nil {
|
if err := PutImagesOnAtlasForTesting(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src2}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src2}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
if got, want := src2.IsOnAtlasForTesting(), false; got != want {
|
||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) {
|
|||||||
// DrawTriangles draws the src image with the given vertices.
|
// DrawTriangles draws the src image with the given vertices.
|
||||||
//
|
//
|
||||||
// Copying vertices and indices is the caller's responsibility.
|
// Copying vertices and indices is the caller's responsibility.
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if i == src {
|
if i == src {
|
||||||
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
panic("buffered: Image.DrawTriangles: source images must be different from the receiver")
|
||||||
|
@ -58,7 +58,7 @@ type Graphics interface {
|
|||||||
//
|
//
|
||||||
// * float32
|
// * float32
|
||||||
// * []float32
|
// * []float32
|
||||||
DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM *affine.ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms []interface{}, evenOdd bool) error
|
DrawTriangles(dst ImageID, srcs [graphics.ShaderImageNum]ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, colorM affine.ColorM, filter Filter, address Address, dstRegion, srcRegion Region, uniforms []interface{}, evenOdd bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||||
|
@ -128,7 +128,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, color affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
if len(indices) > graphics.IndicesNum {
|
if len(indices) > graphics.IndicesNum {
|
||||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
||||||
}
|
}
|
||||||
@ -317,7 +317,7 @@ type drawTrianglesCommand struct {
|
|||||||
offsets [graphics.ShaderImageNum - 1][2]float32
|
offsets [graphics.ShaderImageNum - 1][2]float32
|
||||||
vertices []float32
|
vertices []float32
|
||||||
nindices int
|
nindices int
|
||||||
color *affine.ColorM
|
color affine.ColorM
|
||||||
mode driver.CompositeMode
|
mode driver.CompositeMode
|
||||||
filter driver.Filter
|
filter driver.Filter
|
||||||
address driver.Address
|
address driver.Address
|
||||||
@ -456,7 +456,7 @@ func (c *drawTrianglesCommand) addNumIndices(n int) {
|
|||||||
|
|
||||||
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
// CanMergeWithDrawTrianglesCommand returns a boolean value indicating whether the other drawTrianglesCommand can be merged
|
||||||
// with the drawTrianglesCommand c.
|
// with the drawTrianglesCommand c.
|
||||||
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, vertices []float32, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, evenOdd bool) bool {
|
func (c *drawTrianglesCommand) CanMergeWithDrawTrianglesCommand(dst *Image, srcs [graphics.ShaderImageNum]*Image, vertices []float32, color affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, evenOdd bool) bool {
|
||||||
// If a shader is used, commands are not merged.
|
// If a shader is used, commands are not merged.
|
||||||
//
|
//
|
||||||
// TODO: Merge shader commands considering uniform variables.
|
// TODO: Merge shader commands considering uniform variables.
|
||||||
|
@ -139,7 +139,7 @@ func (i *Image) InternalSize() (int, int) {
|
|||||||
//
|
//
|
||||||
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
||||||
// elements for the source image are not used.
|
// elements for the source image are not used.
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
if shader == nil {
|
if shader == nil {
|
||||||
// Fast path for rendering without a shader (#1355).
|
// Fast path for rendering without a shader (#1355).
|
||||||
img := srcs[0]
|
img := srcs[0]
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
. "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
. "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
||||||
@ -50,7 +51,7 @@ func TestClear(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
|
|
||||||
pix, err := dst.Pixels()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -81,8 +82,8 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
|
|
||||||
// TODO: Check the result.
|
// TODO: Check the result.
|
||||||
@ -100,11 +101,11 @@ func TestShader(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
|
|
||||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
s := NewShader(&ir)
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, s, nil, false)
|
||||||
|
|
||||||
pix, err := dst.Pixels()
|
pix, err := dst.Pixels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -868,7 +868,7 @@ func (g *Graphics) draw(rps mtl.RenderPipelineState, dst *Image, dstRegion drive
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error {
|
func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error {
|
||||||
dst := g.images[dstID]
|
dst := g.images[dstID]
|
||||||
|
|
||||||
if dst.screen {
|
if dst.screen {
|
||||||
@ -893,7 +893,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
} {
|
} {
|
||||||
rpss[stencil] = g.rpss[rpsKey{
|
rpss[stencil] = g.rpss[rpsKey{
|
||||||
screen: dst.screen,
|
screen: dst.screen,
|
||||||
useColorM: colorM != nil,
|
useColorM: !colorM.IsIdentity(),
|
||||||
filter: filter,
|
filter: filter,
|
||||||
address: address,
|
address: address,
|
||||||
compositeMode: mode,
|
compositeMode: mode,
|
||||||
|
@ -146,7 +146,7 @@ func (g *Graphics) SetVertices(vertices []float32, indices []uint16) {
|
|||||||
g.context.elementArrayBufferSubData(indices)
|
g.context.elementArrayBufferSubData(indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error {
|
func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderImageNum]driver.ImageID, offsets [graphics.ShaderImageNum - 1][2]float32, shaderID driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, colorM affine.ColorM, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, uniforms []interface{}, evenOdd bool) error {
|
||||||
destination := g.images[dstID]
|
destination := g.images[dstID]
|
||||||
|
|
||||||
g.drawCalled = true
|
g.drawCalled = true
|
||||||
@ -166,7 +166,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
var uniformVars []uniformVariable
|
var uniformVars []uniformVariable
|
||||||
if shaderID == driver.InvalidShaderID {
|
if shaderID == driver.InvalidShaderID {
|
||||||
program = g.state.programs[programKey{
|
program = g.state.programs[programKey{
|
||||||
useColorM: colorM != nil,
|
useColorM: !colorM.IsIdentity(),
|
||||||
filter: filter,
|
filter: filter,
|
||||||
address: address,
|
address: address,
|
||||||
}]
|
}]
|
||||||
@ -187,7 +187,7 @@ func (g *Graphics) DrawTriangles(dstID driver.ImageID, srcIDs [graphics.ShaderIm
|
|||||||
typ: shaderir.Type{Main: shaderir.Vec4},
|
typ: shaderir.Type{Main: shaderir.Vec4},
|
||||||
})
|
})
|
||||||
|
|
||||||
if colorM != nil {
|
if !colorM.IsIdentity() {
|
||||||
// ColorM's elements are immutable. It's OK to hold the reference without copying.
|
// ColorM's elements are immutable. It's OK to hold the reference without copying.
|
||||||
esBody, esTranslate := colorM.UnsafeElements()
|
esBody, esTranslate := colorM.UnsafeElements()
|
||||||
uniformVars = append(uniformVars, uniformVariable{
|
uniformVars = append(uniformVars, uniformVariable{
|
||||||
|
@ -85,7 +85,7 @@ func (m *Mipmap) Pixels(x, y, width, height int) ([]byte, error) {
|
|||||||
return m.orig.Pixels(x, y, width, height)
|
return m.orig.Pixels(x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, canSkipMipmap bool) {
|
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, subimageOffsets [graphics.ShaderImageNum - 1][2]float32, shader *Shader, uniforms []interface{}, evenOdd bool, canSkipMipmap bool) {
|
||||||
if len(indices) == 0 {
|
if len(indices) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -123,13 +123,13 @@ func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageNum]*Mipmap, vertices [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if colorm != nil && colorm.ScaleOnly() {
|
if colorm.ScaleOnly() {
|
||||||
body, _ := colorm.UnsafeElements()
|
body, _ := colorm.UnsafeElements()
|
||||||
cr := body[0]
|
cr := body[0]
|
||||||
cg := body[5]
|
cg := body[5]
|
||||||
cb := body[10]
|
cb := body[10]
|
||||||
ca := body[15]
|
ca := body[15]
|
||||||
colorm = nil
|
colorm = affine.ColorMIdentity{}
|
||||||
const n = graphics.VertexFloatNum
|
const n = graphics.VertexFloatNum
|
||||||
for i := 0; i < len(vertices)/n; i++ {
|
for i := 0; i < len(vertices)/n; i++ {
|
||||||
vertices[i*n+4] *= cr
|
vertices[i*n+4] *= cr
|
||||||
@ -226,7 +226,7 @@ func (m *Mipmap) level(level int) *buffered.Image {
|
|||||||
Width: float32(w2),
|
Width: float32(w2),
|
||||||
Height: float32(h2),
|
Height: float32(h2),
|
||||||
}
|
}
|
||||||
s.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{src}, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
s.DrawTriangles([graphics.ShaderImageNum]*buffered.Image{src}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, filter, driver.AddressUnsafe, dstRegion, driver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
|
||||||
m.imgs[level] = s
|
m.imgs[level] = s
|
||||||
|
|
||||||
return m.imgs[level]
|
return m.imgs[level]
|
||||||
|
@ -68,7 +68,7 @@ type drawTrianglesHistoryItem struct {
|
|||||||
offsets [graphics.ShaderImageNum - 1][2]float32
|
offsets [graphics.ShaderImageNum - 1][2]float32
|
||||||
vertices []float32
|
vertices []float32
|
||||||
indices []uint16
|
indices []uint16
|
||||||
colorm *affine.ColorM
|
colorm affine.ColorM
|
||||||
mode driver.CompositeMode
|
mode driver.CompositeMode
|
||||||
filter driver.Filter
|
filter driver.Filter
|
||||||
address driver.Address
|
address driver.Address
|
||||||
@ -187,7 +187,7 @@ func (i *Image) Extend(width, height int) *Image {
|
|||||||
Width: float32(sw),
|
Width: float32(sw),
|
||||||
Height: float32(sh),
|
Height: float32(sh),
|
||||||
}
|
}
|
||||||
newImg.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
newImg.DrawTriangles(srcs, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
|
|
||||||
// Overwrite the history as if the image newImg is created only by ReplacePixels. Now drawTrianglesHistory
|
// Overwrite the history as if the image newImg is created only by ReplacePixels. Now drawTrianglesHistory
|
||||||
// and basePixels cannot be mixed.
|
// and basePixels cannot be mixed.
|
||||||
@ -248,7 +248,7 @@ func clearImage(i *graphicscommand.Image) {
|
|||||||
Width: float32(dw),
|
Width: float32(dw),
|
||||||
Height: float32(dh),
|
Height: float32(dh),
|
||||||
}
|
}
|
||||||
i.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil, false)
|
i.DrawTriangles(srcs, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dstRegion, driver.Region{}, nil, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasePixelsForTesting returns the image's basePixels for testing.
|
// BasePixelsForTesting returns the image's basePixels for testing.
|
||||||
@ -351,7 +351,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
// 5: Color G
|
// 5: Color G
|
||||||
// 6: Color B
|
// 6: Color B
|
||||||
// 7: Color Y
|
// 7: Color Y
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
if i.priority {
|
if i.priority {
|
||||||
panic("restorable: DrawTriangles cannot be called on a priority image")
|
panic("restorable: DrawTriangles cannot be called on a priority image")
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
|||||||
}
|
}
|
||||||
|
|
||||||
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
||||||
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
func (i *Image) appendDrawTrianglesHistory(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, colorm affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, dstRegion, srcRegion driver.Region, shader *Shader, uniforms []interface{}, evenOdd bool) {
|
||||||
if i.stale || i.volatile || i.screen {
|
if i.stale || i.volatile || i.screen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
. "github.com/hajimehoshi/ebiten/v2/internal/restorable"
|
. "github.com/hajimehoshi/ebiten/v2/internal/restorable"
|
||||||
@ -137,7 +138,7 @@ func TestRestoreChain(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
}
|
}
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -185,10 +186,10 @@ func TestRestoreChain2(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
imgs[8].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
imgs[8].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
imgs[9].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
imgs[9].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
for i := 0; i < 7; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -234,10 +235,10 @@ func TestRestoreOverrideSource(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
img2.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img2.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -323,23 +324,23 @@ func TestRestoreComplexGraph(t *testing.T) {
|
|||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
var offsets [graphics.ShaderImageNum - 1][2]float32
|
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img3.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 2, 0)
|
vs = quadVertices(w, h, 2, 0)
|
||||||
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img4.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img5.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img5.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 1, 0)
|
vs = quadVertices(w, h, 1, 0)
|
||||||
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img4}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img6.DrawTriangles([graphics.ShaderImageNum]*Image{img4}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 0, 0)
|
vs = quadVertices(w, h, 0, 0)
|
||||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
vs = quadVertices(w, h, 2, 0)
|
vs = quadVertices(w, h, 2, 0)
|
||||||
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img7.DrawTriangles([graphics.ShaderImageNum]*Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -437,8 +438,8 @@ func TestRestoreRecursive(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -538,7 +539,7 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
|||||||
Width: 2,
|
Width: 2,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -581,8 +582,8 @@ func TestDispose(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img0.DrawTriangles([graphics.ShaderImageNum]*Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img1.Dispose()
|
img1.Dispose()
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
@ -696,7 +697,7 @@ func TestReplacePixelsOnly(t *testing.T) {
|
|||||||
Width: 1,
|
Width: 1,
|
||||||
Height: 1,
|
Height: 1,
|
||||||
}
|
}
|
||||||
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img1.DrawTriangles([graphics.ShaderImageNum]*Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||||
|
|
||||||
// BasePixelsForTesting is available without GPU accessing.
|
// BasePixelsForTesting is available without GPU accessing.
|
||||||
@ -756,7 +757,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
|
|
||||||
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
||||||
// stale.
|
// stale.
|
||||||
@ -783,7 +784,7 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||||
// ReplacePixels for a whole image doesn't panic.
|
// ReplacePixels for a whole image doesn't panic.
|
||||||
}
|
}
|
||||||
@ -807,7 +808,7 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,7 +885,7 @@ func TestMutateSlices(t *testing.T) {
|
|||||||
Width: w,
|
Width: w,
|
||||||
Height: h,
|
Height: h,
|
||||||
}
|
}
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
for i := range vs {
|
for i := range vs {
|
||||||
vs[i] = 0
|
vs[i] = 0
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/internal/affine"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
"github.com/hajimehoshi/ebiten/v2/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||||
. "github.com/hajimehoshi/ebiten/v2/internal/restorable"
|
. "github.com/hajimehoshi/ebiten/v2/internal/restorable"
|
||||||
@ -48,7 +49,7 @@ func clearImage(img *Image, w, h int) {
|
|||||||
Width: float32(w),
|
Width: float32(w),
|
||||||
Height: float32(h),
|
Height: float32(h),
|
||||||
}
|
}
|
||||||
img.DrawTriangles([graphics.ShaderImageNum]*Image{emptyImage}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
img.DrawTriangles([graphics.ShaderImageNum]*Image{emptyImage}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, dr, driver.Region{}, nil, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShader(t *testing.T) {
|
func TestShader(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user