affine: Use float32 inside of ColorM

This commit is contained in:
Hajime Hoshi 2018-02-20 00:33:56 +09:00
parent f500acde4c
commit 9b361086d7
5 changed files with 47 additions and 51 deletions

View File

@ -61,12 +61,12 @@ func (c *ColorM) Add(other ColorM) {
// 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.Scale(r, g, b, a) c.impl.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.Translate(r, g, b, a) c.impl.Translate(float32(r), float32(g), float32(b), float32(a))
} }
// RotateHue rotates the hue. // RotateHue rotates the hue.
@ -82,21 +82,21 @@ 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.ChangeHSV(hueTheta, saturationScale, valueScale) c.impl.ChangeHSV(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 {
b, t := c.impl.UnsafeElements() b, t := c.impl.UnsafeElements()
if j < ColorMDim-1 { if j < ColorMDim-1 {
return b[i*(ColorMDim-1)+j] return float64(b[i*(ColorMDim-1)+j])
} }
return t[i] return float64(t[i])
} }
// 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.SetElement(i, j, element) c.impl.SetElement(i, j, float32(element))
} }
// Monochrome is deprecated as of 1.6.0-alpha. Use ChangeHSV(0, 0, 1) instead. // Monochrome is deprecated as of 1.6.0-alpha. Use ChangeHSV(0, 0, 1) instead.

View File

@ -16,6 +16,7 @@ package ebiten_test
import ( import (
"image/color" "image/color"
"math"
"testing" "testing"
. "github.com/hajimehoshi/ebiten" . "github.com/hajimehoshi/ebiten"
@ -137,7 +138,7 @@ func TestColorMMonochrome(t *testing.T) {
for j := 0; j < 5; j++ { for j := 0; j < 5; j++ {
got := m.Element(i, j) got := m.Element(i, j)
want := expected[i][j] want := expected[i][j]
if want != got { if math.Abs(want-got) > 0.0001 {
t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want) t.Errorf("m.Element(%d, %d) = %f, want %f", i, j, got, want)
} }
} }

View File

@ -25,11 +25,11 @@ func add(lhs, rhs []float64, dim int) []float64 {
return result return result
} }
func mulSquare(lhs, rhs []float64, dim int) []float64 { func mulSquare(lhs, rhs []float32, dim int) []float32 {
result := make([]float64, len(lhs)) result := make([]float32, len(lhs))
for i := 0; i < dim; i++ { for i := 0; i < dim; i++ {
for j := 0; j < dim; j++ { for j := 0; j < dim; j++ {
e := 0.0 e := float32(0.0)
for k := 0; k < dim; k++ { for k := 0; k < dim; k++ {
e += lhs[i*dim+k] * rhs[k*dim+j] e += lhs[i*dim+k] * rhs[k*dim+j]
} }

View File

@ -23,13 +23,13 @@ import (
const ColorMDim = 5 const ColorMDim = 5
var ( var (
colorMIdentityBody = []float64{ colorMIdentityBody = []float32{
1, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1, 0, 0, 0, 1,
} }
colorMIdentityTranslate = []float64{ colorMIdentityTranslate = []float32{
0, 0, 0, 0, 0, 0, 0, 0,
} }
) )
@ -45,8 +45,8 @@ var (
type ColorM struct { type ColorM struct {
// When elements is nil, this matrix is identity. // When elements is nil, this matrix is identity.
// elements is immutable and a new array must be created when updating. // elements is immutable and a new array must be created when updating.
body []float64 // TODO: Transpose this to pass this OpenGL easily body []float32 // TODO: Transpose this to pass this OpenGL easily
translate []float64 translate []float32
} }
func (c *ColorM) Reset() { func (c *ColorM) Reset() {
@ -54,7 +54,7 @@ func (c *ColorM) Reset() {
c.translate = nil c.translate = nil
} }
func clamp(x float64) float64 { func clamp(x float32) float32 {
if x > 1 { if x > 1 {
return 1 return 1
} }
@ -73,10 +73,10 @@ func (c *ColorM) Apply(clr color.Color) color.Color {
return color.Transparent return color.Transparent
} }
// Unmultiply alpha // Unmultiply alpha
rf := float64(r) / float64(a) rf := float32(r) / float32(a)
gf := float64(g) / float64(a) gf := float32(g) / float32(a)
bf := float64(b) / float64(a) bf := float32(b) / float32(a)
af := float64(a) / 0xffff af := float32(a) / 0xffff
eb := c.body eb := c.body
et := c.translate et := c.translate
rf2 := eb[0]*rf + eb[1]*gf + eb[2]*bf + eb[3]*af + et[0] rf2 := eb[0]*rf + eb[1]*gf + eb[2]*bf + eb[3]*af + et[0]
@ -95,7 +95,7 @@ func (c *ColorM) Apply(clr color.Color) color.Color {
} }
} }
func (c *ColorM) UnsafeElements() ([]float64, []float64) { func (c *ColorM) UnsafeElements() ([]float32, []float32) {
if c.body == nil { if c.body == nil {
c.body = colorMIdentityBody c.body = colorMIdentityBody
c.translate = colorMIdentityTranslate c.translate = colorMIdentityTranslate
@ -104,18 +104,18 @@ func (c *ColorM) UnsafeElements() ([]float64, []float64) {
} }
// 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 float32) {
if c.body == nil { if c.body == nil {
c.body = colorMIdentityBody c.body = colorMIdentityBody
c.translate = colorMIdentityTranslate c.translate = colorMIdentityTranslate
} }
if j < (ColorMDim - 1) { if j < (ColorMDim - 1) {
es := make([]float64, len(c.body)) es := make([]float32, len(c.body))
copy(es, c.body) copy(es, c.body)
es[i*(ColorMDim-1)+j] = element es[i*(ColorMDim-1)+j] = element
c.body = es c.body = es
} else { } else {
es := make([]float64, len(c.translate)) es := make([]float32, len(c.translate))
copy(es, c.translate) copy(es, c.translate)
es[i] = element es[i] = element
c.translate = es c.translate = es
@ -163,7 +163,7 @@ func (c *ColorM) Concat(other *ColorM) {
lhsb := other.body lhsb := other.body
lhst := other.translate lhst := other.translate
rhst := c.translate rhst := c.translate
c.translate = []float64{ c.translate = []float32{
lhsb[0]*rhst[0] + lhsb[1]*rhst[1] + lhsb[2]*rhst[2] + lhsb[3]*rhst[3] + lhst[0], lhsb[0]*rhst[0] + lhsb[1]*rhst[1] + lhsb[2]*rhst[2] + lhsb[3]*rhst[3] + lhst[0],
lhsb[4]*rhst[0] + lhsb[5]*rhst[1] + lhsb[6]*rhst[2] + lhsb[7]*rhst[3] + lhst[1], lhsb[4]*rhst[0] + lhsb[5]*rhst[1] + lhsb[6]*rhst[2] + lhsb[7]*rhst[3] + lhst[1],
lhsb[8]*rhst[0] + lhsb[9]*rhst[1] + lhsb[10]*rhst[2] + lhsb[11]*rhst[3] + lhst[2], lhsb[8]*rhst[0] + lhsb[9]*rhst[1] + lhsb[10]*rhst[2] + lhsb[11]*rhst[3] + lhst[2],
@ -183,12 +183,12 @@ func (c *ColorM) Add(other ColorM) {
other.translate = colorMIdentityTranslate other.translate = colorMIdentityTranslate
} }
body := make([]float64, len(c.body)) body := make([]float32, len(c.body))
for i := range c.body { for i := range c.body {
body[i] = c.body[i] + other.body[i] body[i] = c.body[i] + other.body[i]
} }
translate := make([]float64, len(c.translate)) translate := make([]float32, len(c.translate))
for i := range c.translate { for i := range c.translate {
translate[i] = c.translate[i] + other.translate[i] translate[i] = c.translate[i] + other.translate[i]
} }
@ -198,9 +198,9 @@ func (c *ColorM) Add(other ColorM) {
} }
// 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 float32) {
if c.body == nil { if c.body == nil {
c.body = []float64{ c.body = []float32{
r, 0, 0, 0, r, 0, 0, 0,
0, g, 0, 0, 0, g, 0, 0,
0, 0, b, 0, 0, 0, b, 0,
@ -209,7 +209,7 @@ func (c *ColorM) Scale(r, g, b, a float64) {
c.translate = colorMIdentityTranslate c.translate = colorMIdentityTranslate
return return
} }
es := make([]float64, len(c.body)) es := make([]float32, len(c.body))
copy(es, c.body) copy(es, c.body)
for i := 0; i < ColorMDim-1; i++ { for i := 0; i < ColorMDim-1; i++ {
es[i] *= r es[i] *= r
@ -219,7 +219,7 @@ func (c *ColorM) Scale(r, g, b, a float64) {
} }
c.body = es c.body = es
c.translate = []float64{ c.translate = []float32{
c.translate[0] * r, c.translate[0] * r,
c.translate[1] * g, c.translate[1] * g,
c.translate[2] * b, c.translate[2] * b,
@ -228,13 +228,13 @@ func (c *ColorM) Scale(r, g, b, a float64) {
} }
// 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 float32) {
if c.body == nil { if c.body == nil {
c.body = colorMIdentityBody c.body = colorMIdentityBody
c.translate = []float64{r, g, b, a} c.translate = []float32{r, g, b, a}
return return
} }
es := make([]float64, len(c.translate)) es := make([]float32, len(c.translate))
copy(es, c.translate) copy(es, c.translate)
es[0] += r es[0] += r
es[1] += g es[1] += g
@ -250,22 +250,22 @@ var (
// Cr: [-0.5 - 0.5] // Cr: [-0.5 - 0.5]
rgbToYCbCr = ColorM{ rgbToYCbCr = ColorM{
body: []float64{ body: []float32{
0.2990, 0.5870, 0.1140, 0, 0.2990, 0.5870, 0.1140, 0,
-0.1687, -0.3313, 0.5000, 0, -0.1687, -0.3313, 0.5000, 0,
0.5000, -0.4187, -0.0813, 0, 0.5000, -0.4187, -0.0813, 0,
0, 0, 0, 1, 0, 0, 0, 1,
}, },
translate: []float64{0, 0, 0, 0}, translate: []float32{0, 0, 0, 0},
} }
yCbCrToRgb = ColorM{ yCbCrToRgb = ColorM{
body: []float64{ body: []float32{
1, 0, 1.40200, 0, 1, 0, 1.40200, 0,
1, -0.34414, -0.71414, 0, 1, -0.34414, -0.71414, 0,
1, 1.77200, 0, 0, 1, 1.77200, 0, 0,
0, 0, 0, 1, 0, 0, 0, 1,
}, },
translate: []float64{0, 0, 0, 0}, translate: []float32{0, 0, 0, 0},
} }
) )
@ -275,17 +275,18 @@ 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 float64, valueScale float64) { func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float32, valueScale float32) {
sin, cos := math.Sincos(hueTheta) sin, cos := math.Sincos(hueTheta)
s32, c32 := float32(sin), float32(cos)
c.Concat(&rgbToYCbCr) c.Concat(&rgbToYCbCr)
c.Concat(&ColorM{ c.Concat(&ColorM{
body: []float64{ body: []float32{
1, 0, 0, 0, 1, 0, 0, 0,
0, cos, -sin, 0, 0, c32, -s32, 0,
0, sin, cos, 0, 0, s32, c32, 0,
0, 0, 0, 1, 0, 0, 0, 1,
}, },
translate: []float64{0, 0, 0, 0}, translate: []float32{0, 0, 0, 0},
}) })
s := saturationScale s := saturationScale
v := valueScale v := valueScale

View File

@ -280,18 +280,12 @@ func (s *openGLState) useProgram(proj []float32, texture opengl.Texture, sourceW
} }
copy(s.lastColorMatrix, colorMatrix) copy(s.lastColorMatrix, colorMatrix)
} }
colorMatrixTranslation := []float32{ if !areSameFloat32Array(s.lastColorMatrixTranslation, esTranslate) {
float32(esTranslate[0]), c.UniformFloats(program, "color_matrix_translation", esTranslate)
float32(esTranslate[1]),
float32(esTranslate[2]),
float32(esTranslate[3]),
}
if !areSameFloat32Array(s.lastColorMatrixTranslation, colorMatrixTranslation) {
c.UniformFloats(program, "color_matrix_translation", colorMatrixTranslation)
if s.lastColorMatrixTranslation == nil { if s.lastColorMatrixTranslation == nil {
s.lastColorMatrixTranslation = make([]float32, 4) s.lastColorMatrixTranslation = make([]float32, 4)
} }
copy(s.lastColorMatrixTranslation, colorMatrixTranslation) copy(s.lastColorMatrixTranslation, esTranslate)
} }
if program == s.programLinear { if program == s.programLinear {