graphics: Add geometry matrix info to vertices

This commit is contained in:
Hajime Hoshi 2016-10-25 01:56:59 +09:00
parent 8d550a4007
commit ebf7f0df00
6 changed files with 123 additions and 12 deletions

View File

@ -128,7 +128,7 @@ func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error {
}
}
w, h := image.impl.restorable.Size()
vs := vertices(parts, w, h)
vs := vertices(parts, w, h, &options.GeoM)
if len(vs) == 0 {
return nil
}

View File

@ -77,7 +77,8 @@ func v(y, height2p int) int16 {
return int16(math.MaxInt16 * y / height2p)
}
func vertices(parts ImageParts, width, height int) []uint8 {
func vertices(parts ImageParts, width, height int, geo *GeoM) []uint8 {
// TODO: This function should be in graphics package?
totalSize := graphics.QuadVertexSizeInBytes()
oneSize := totalSize / 4
l := parts.Len()
@ -86,6 +87,12 @@ func vertices(parts ImageParts, width, height int) []uint8 {
height2p := graphics.NextPowerOf2Int(height)
n := 0
vs := make([]int16, 16)
geoBytes := floatBytes(geo.Element(0, 0),
geo.Element(0, 1),
geo.Element(1, 0),
geo.Element(1, 1),
geo.Element(0, 2),
geo.Element(1, 2))
for i := 0; i < l; i++ {
dx0, dy0, dx1, dy1 := parts.Dst(i)
if dx0 == dx1 || dy0 == dy1 {
@ -114,15 +121,21 @@ func vertices(parts ImageParts, width, height int) []uint8 {
vs[14] = u1
vs[15] = v1
// Use direct assign here. `append` function might be slow on browsers.
for j := 0; j < 4; j++ {
offset := totalSize*n + oneSize*j
if endian.IsLittle() {
for i, v := range vs {
vertices[totalSize*n+oneSize*(i/4)+2*(i%4)] = uint8(v)
vertices[totalSize*n+oneSize*(i/4)+2*(i%4)+1] = uint8(v >> 8)
for k, v := range vs[4*j : 4*j+4] {
vertices[offset+2*k] = uint8(v)
vertices[offset+2*k+1] = uint8(v >> 8)
}
} else {
for i, v := range vs {
vertices[totalSize*n+oneSize*(i/4)+2*(i%4)] = uint8(v >> 8)
vertices[totalSize*n+oneSize*(i/4)+2*(i%4)+1] = uint8(v)
for k, v := range vs[4*j : 4*j+4] {
vertices[offset+2*k] = uint8(v >> 8)
vertices[offset+2*k+1] = uint8(v)
}
}
for k, g := range geoBytes {
vertices[offset+8+k] = g
}
}
n++

View File

@ -65,6 +65,7 @@ func (a *arrayBufferLayout) disable(c *opengl.Context, program opengl.Program) {
var (
theArrayBufferLayout = arrayBufferLayout{
// Note that GL_MAX_VERTEX_ATTRIBS is at least 16.
parts: []arrayBufferLayoutPart{
{
name: "vertex",
@ -78,6 +79,18 @@ var (
num: 2,
normalize: true,
},
{
name: "geo_matrix",
dataType: opengl.Float,
num: 4,
normalize: false,
},
{
name: "geo_matrix_translation",
dataType: opengl.Float,
num: 2,
normalize: false,
},
},
}
)

View File

@ -39,14 +39,23 @@ func shader(c *opengl.Context, id shaderId) string {
var shaders = map[shaderId]string{
shaderVertexModelview: `
uniform highp mat4 projection_matrix;
uniform highp mat4 modelview_matrix;
uniform highp mat4 modelview_matrix; // TODO: Remove this
attribute highp vec2 vertex;
attribute highp vec2 tex_coord;
attribute highp vec4 geo_matrix;
attribute highp vec2 geo_matrix_translation;
varying highp vec2 vertex_out_tex_coord;
void main(void) {
vertex_out_tex_coord = tex_coord;
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 0, 1);
mat4 x = modelview_matrix; // temporary hack not to omit modelview_matrix
mat4 geom = mat4(
vec4(geo_matrix[0], geo_matrix[2], 0, 0),
vec4(geo_matrix[1], geo_matrix[3], 0, 0),
vec4(0, 0, 1, 0),
vec4(geo_matrix_translation, 0, 1)
);
gl_Position = projection_matrix * geom * vec4(vertex, 0, 1);
}
`,
shaderFragmentTexture: `

45
math.go Normal file
View File

@ -0,0 +1,45 @@
// Copyright 2016 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !js
package ebiten
import (
"unsafe"
"github.com/hajimehoshi/ebiten/internal/endian"
)
func floatBytes(xs ...float64) []uint8 {
bits := make([]uint8, 0, len(xs)*4)
for _, x := range xs {
x32 := float32(x)
n := *(*uint32)(unsafe.Pointer(&x32))
if endian.IsLittle() {
bits = append(bits,
uint8(n),
uint8(n>>8),
uint8(n>>16),
uint8(n>>24))
} else {
bits = append(bits,
uint8(n>>24),
uint8(n>>16),
uint8(n>>8),
uint8(n))
}
}
return bits
}

31
math_js.go Normal file
View File

@ -0,0 +1,31 @@
// Copyright 2016 The Ebiten Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build js
package ebiten
import (
"github.com/gopherjs/gopherjs/js"
)
func floatBytes(xs ...float64) []uint8 {
a := js.Global.Get("ArrayBuffer").New(4 * len(xs))
af32 := js.Global.Get("Float32Array").New(a)
a8 := js.Global.Get("Uint8Array").New(a)
for i, x := range xs {
af32.SetIndex(i, x)
}
return a8.Interface().([]uint8)
}