mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
Do GeoM projection on CPU (#477)
Handling GeoM projection on CPU may seem like a weird choice, given how fast GPU is, but it pays off: * You only have to do a very small subset of the actual matrix multiply. * You don't have to construct a matrix in the vertex shader. * Six fewer float32 values per vertex. * You do still have to do the matrix computation for each vertex, though. Signed-off-by: Seebs <seebs@seebs.net>
This commit is contained in:
parent
38c72faf95
commit
0b7ba8e573
@ -45,6 +45,13 @@ func (g *GeoM) Apply(x, y float64) (x2, y2 float64) {
|
||||
return g.a*x + g.b*y + g.tx, g.c*x + g.d*y + g.ty
|
||||
}
|
||||
|
||||
func (g *GeoM) Apply32(x, y float64) (x2, y2 float32) {
|
||||
if !g.inited {
|
||||
return float32(x), float32(y)
|
||||
}
|
||||
return float32(g.a*x + g.b*y + g.tx), float32(g.c*x + g.d*y + g.ty)
|
||||
}
|
||||
|
||||
func (g *GeoM) Elements() (a, b, c, d, tx, ty float64) {
|
||||
if !g.inited {
|
||||
return 1, 0, 0, 1, 0, 0
|
||||
|
@ -92,16 +92,6 @@ var (
|
||||
dataType: opengl.Float,
|
||||
num: 4,
|
||||
},
|
||||
{
|
||||
name: "geo_matrix_body",
|
||||
dataType: opengl.Float,
|
||||
num: 4,
|
||||
},
|
||||
{
|
||||
name: "geo_matrix_translation",
|
||||
dataType: opengl.Float,
|
||||
num: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
@ -47,8 +47,6 @@ const (
|
||||
uniform mat4 projection_matrix;
|
||||
attribute vec2 vertex;
|
||||
attribute vec4 tex_coord;
|
||||
attribute vec4 geo_matrix_body;
|
||||
attribute vec2 geo_matrix_translation;
|
||||
varying vec2 varying_tex_coord;
|
||||
varying vec2 varying_tex_coord_min;
|
||||
varying vec2 varying_tex_coord_max;
|
||||
@ -59,13 +57,7 @@ void main(void) {
|
||||
vec2(min(tex_coord[0], tex_coord[2]), min(tex_coord[1], tex_coord[3]));
|
||||
varying_tex_coord_max =
|
||||
vec2(max(tex_coord[0], tex_coord[2]), max(tex_coord[1], tex_coord[3]));
|
||||
mat4 geo_matrix = mat4(
|
||||
vec4(geo_matrix_body[0], geo_matrix_body[2], 0, 0),
|
||||
vec4(geo_matrix_body[1], geo_matrix_body[3], 0, 0),
|
||||
vec4(0, 0, 1, 0),
|
||||
vec4(geo_matrix_translation, 0, 1)
|
||||
);
|
||||
gl_Position = projection_matrix * geo_matrix * vec4(vertex, 0, 1);
|
||||
gl_Position = projection_matrix * vec4(vertex, 0, 1);
|
||||
}
|
||||
`
|
||||
shaderStrFragment = `
|
||||
|
@ -79,10 +79,10 @@ func vertices(sw, sh int, x, y int) []float32 {
|
||||
|
||||
// For the rule of values, see vertices.go.
|
||||
return []float32{
|
||||
0, 0, 0, 0, 1, 1, a, b, c, d, tx, ty,
|
||||
0, shf, 0, 1, 1, 0, a, b, c, d, tx, ty,
|
||||
swf, 0, 1, 0, 0, 1, a, b, c, d, tx, ty,
|
||||
swf, shf, 1, 1, 0, 0, a, b, c, d, tx, ty,
|
||||
0 + tx, 0 + ty, 0, 0, 1, 1,
|
||||
0 + tx, shf + ty, 0, 1, 1, 0,
|
||||
swf + tx, 0 + ty, 1, 0, 0, 1,
|
||||
swf + tx, shf + ty, 1, 1, 0, 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
87
vertices.go
87
vertices.go
@ -70,30 +70,27 @@ func vertices(sx0, sy0, sx1, sy1 int, width, height int, geo *affine.GeoM) []flo
|
||||
g.Concat(geo)
|
||||
geo = &g
|
||||
}
|
||||
x0, y0 := float64(0), float64(0)
|
||||
x1, y1 := float64(sx1 - sx0), float64(sy1 - sy0)
|
||||
|
||||
a, b, c, d, tx, ty := geo.Elements()
|
||||
g0 := float32(a)
|
||||
g1 := float32(b)
|
||||
g2 := float32(c)
|
||||
g3 := float32(d)
|
||||
g4 := float32(tx)
|
||||
g5 := float32(ty)
|
||||
// it really feels like we should be able to cache this computation
|
||||
// but it may not matter.
|
||||
w := 1
|
||||
h := 1
|
||||
for w < width {
|
||||
w *= 2
|
||||
w *= 2
|
||||
}
|
||||
for h < height {
|
||||
h *= 2
|
||||
h *= 2
|
||||
}
|
||||
wf := float32(w)
|
||||
hf := float32(h)
|
||||
x0, y0, x1, y1 := float32(0), float32(0), float32(sx1-sx0), float32(sy1-sy0)
|
||||
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
||||
|
||||
x, y := geo.Apply32(x0, y0)
|
||||
// Vertex coordinates
|
||||
vs[0] = x0
|
||||
vs[1] = y0
|
||||
vs[0] = x
|
||||
vs[1] = y
|
||||
|
||||
// Texture coordinates: first 2 values indicates the actual coodinate, and
|
||||
// the second indicates diagonally opposite coodinates.
|
||||
@ -103,52 +100,30 @@ func vertices(sx0, sy0, sx1, sy1 int, width, height int, geo *affine.GeoM) []flo
|
||||
vs[4] = u1
|
||||
vs[5] = v1
|
||||
|
||||
// Geometry matrix
|
||||
vs[6] = g0
|
||||
vs[7] = g1
|
||||
vs[8] = g2
|
||||
vs[9] = g3
|
||||
vs[10] = g4
|
||||
vs[11] = g5
|
||||
// and the same for the other three coordinates
|
||||
x, y = geo.Apply32(x1, y0)
|
||||
vs[6] = x
|
||||
vs[7] = y
|
||||
vs[8] = u1
|
||||
vs[9] = v0
|
||||
vs[10] = u0
|
||||
vs[11] = v1
|
||||
|
||||
vs[12] = x1
|
||||
vs[13] = y0
|
||||
vs[14] = u1
|
||||
vs[15] = v0
|
||||
vs[16] = u0
|
||||
vs[17] = v1
|
||||
vs[18] = g0
|
||||
vs[19] = g1
|
||||
vs[20] = g2
|
||||
vs[21] = g3
|
||||
vs[22] = g4
|
||||
vs[23] = g5
|
||||
x, y = geo.Apply32(x0, y1)
|
||||
vs[12] = x
|
||||
vs[13] = y
|
||||
vs[14] = u0
|
||||
vs[15] = v1
|
||||
vs[16] = u1
|
||||
vs[17] = v0
|
||||
|
||||
vs[24] = x0
|
||||
vs[25] = y1
|
||||
vs[26] = u0
|
||||
vs[27] = v1
|
||||
vs[28] = u1
|
||||
vs[29] = v0
|
||||
vs[30] = g0
|
||||
vs[31] = g1
|
||||
vs[32] = g2
|
||||
vs[33] = g3
|
||||
vs[34] = g4
|
||||
vs[35] = g5
|
||||
|
||||
vs[36] = x1
|
||||
vs[37] = y1
|
||||
vs[38] = u1
|
||||
vs[39] = v1
|
||||
vs[40] = u0
|
||||
vs[41] = v0
|
||||
vs[42] = g0
|
||||
vs[43] = g1
|
||||
vs[44] = g2
|
||||
vs[45] = g3
|
||||
vs[46] = g4
|
||||
vs[47] = g5
|
||||
x, y = geo.Apply32(x1, y1)
|
||||
vs[18] = x
|
||||
vs[19] = y
|
||||
vs[20] = u1
|
||||
vs[21] = v1
|
||||
vs[22] = u0
|
||||
vs[23] = v0
|
||||
|
||||
return vs
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user