go-opengl-pixel/pixelgl/gltriangles.go

171 lines
4.1 KiB
Go
Raw Normal View History

package pixelgl
2017-01-20 11:40:48 -06:00
import (
2017-01-28 13:01:59 -06:00
"fmt"
2017-02-11 07:09:47 -06:00
"github.com/faiface/glhf"
2017-01-20 11:40:48 -06:00
"github.com/faiface/mainthread"
"github.com/faiface/pixel"
2017-01-20 11:40:48 -06:00
)
2017-02-11 07:09:47 -06:00
// NewGLTriangles returns OpenGL triangles implemented using glhf.VertexSlice. A few notes.
2017-01-20 11:40:48 -06:00
//
// Triangles returned from this function support TrianglesPosition, TrianglesColor and
2017-02-02 19:09:06 -06:00
// TrianglesTexture. If you need to support more, you can "override" SetLen and Update method.
2017-01-20 11:40:48 -06:00
//
2017-02-11 07:09:47 -06:00
// Draw method simply draws the underlying glhf.VertexSlice. It needs to be called in the main
2017-01-20 11:40:48 -06:00
// thread manually. Also, you need to take care of additional Target initialization or setting of
// uniform attributes.
func NewGLTriangles(shader *glhf.Shader, t pixel.Triangles) pixel.TargetTriangles {
2017-01-20 11:40:48 -06:00
var gt *glTriangles
mainthread.Call(func() {
gt = &glTriangles{
2017-02-11 07:09:47 -06:00
vs: glhf.MakeVertexSlice(shader, 0, t.Len()),
2017-01-20 11:40:48 -06:00
shader: shader,
}
})
2017-01-28 13:01:59 -06:00
gt.SetLen(t.Len())
2017-01-20 11:40:48 -06:00
gt.Update(t)
return gt
}
type glTriangles struct {
2017-02-11 07:09:47 -06:00
vs *glhf.VertexSlice
2017-01-20 11:40:48 -06:00
data []float32
2017-02-11 07:09:47 -06:00
shader *glhf.Shader
2017-01-20 11:40:48 -06:00
}
func (gt *glTriangles) Len() int {
return len(gt.data) / gt.vs.Stride()
}
2017-01-28 13:01:59 -06:00
func (gt *glTriangles) SetLen(len int) {
2017-01-20 11:40:48 -06:00
if len > gt.Len() {
needAppend := len - gt.Len()
for i := 0; i < needAppend; i++ {
gt.data = append(gt.data,
0, 0,
1, 1, 1, 1,
-1, -1,
)
}
}
if len < gt.Len() {
gt.data = gt.data[:len]
}
}
func (gt *glTriangles) Slice(i, j int) pixel.Triangles {
2017-01-28 13:01:59 -06:00
return &glTriangles{
vs: gt.vs.Slice(i, j),
data: gt.data[i*gt.vs.Stride() : j*gt.vs.Stride()],
shader: gt.shader,
}
}
func (gt *glTriangles) updateData(t pixel.Triangles) {
2017-01-28 13:01:59 -06:00
// glTriangles short path
if t, ok := t.(*glTriangles); ok {
copy(gt.data, t.data)
return
}
2017-01-25 16:51:27 -06:00
// TrianglesData short path
if t, ok := t.(*pixel.TrianglesData); ok {
2017-01-28 13:01:59 -06:00
for i := 0; i < gt.Len(); i++ {
2017-01-25 16:51:27 -06:00
var (
px, py = (*t)[i].Position.XY()
col = (*t)[i].Color
2017-02-23 06:07:40 -06:00
tx, ty = (*t)[i].Picture.XY()
2017-01-25 16:51:27 -06:00
)
gt.data[i*gt.vs.Stride()+0] = float32(px)
gt.data[i*gt.vs.Stride()+1] = float32(py)
gt.data[i*gt.vs.Stride()+2] = float32(col.R)
gt.data[i*gt.vs.Stride()+3] = float32(col.G)
gt.data[i*gt.vs.Stride()+4] = float32(col.B)
gt.data[i*gt.vs.Stride()+5] = float32(col.A)
gt.data[i*gt.vs.Stride()+6] = float32(tx)
gt.data[i*gt.vs.Stride()+7] = float32(ty)
}
return
}
if t, ok := t.(pixel.TrianglesPosition); ok {
2017-01-28 13:01:59 -06:00
for i := 0; i < gt.Len(); i++ {
2017-01-20 11:40:48 -06:00
px, py := t.Position(i).XY()
gt.data[i*gt.vs.Stride()+0] = float32(px)
gt.data[i*gt.vs.Stride()+1] = float32(py)
}
}
if t, ok := t.(pixel.TrianglesColor); ok {
2017-01-28 13:01:59 -06:00
for i := 0; i < gt.Len(); i++ {
2017-01-20 11:40:48 -06:00
col := t.Color(i)
gt.data[i*gt.vs.Stride()+2] = float32(col.R)
gt.data[i*gt.vs.Stride()+3] = float32(col.G)
gt.data[i*gt.vs.Stride()+4] = float32(col.B)
gt.data[i*gt.vs.Stride()+5] = float32(col.A)
}
}
2017-02-23 06:07:40 -06:00
if t, ok := t.(pixel.TrianglesPicture); ok {
2017-01-28 13:01:59 -06:00
for i := 0; i < gt.Len(); i++ {
2017-02-23 06:07:40 -06:00
tx, ty := t.Picture(i).XY()
2017-01-20 11:40:48 -06:00
gt.data[i*gt.vs.Stride()+6] = float32(tx)
gt.data[i*gt.vs.Stride()+7] = float32(ty)
}
}
}
func (gt *glTriangles) submitData() {
data := gt.data // avoid race condition
mainthread.CallNonBlock(func() {
gt.vs.Begin()
dataLen := len(data) / gt.vs.Stride()
gt.vs.SetLen(dataLen)
2017-01-20 11:40:48 -06:00
gt.vs.SetVertexData(gt.data)
gt.vs.End()
})
}
func (gt *glTriangles) Update(t pixel.Triangles) {
2017-01-28 13:01:59 -06:00
if gt.Len() != t.Len() {
panic(fmt.Errorf("%T.Update: invalid triangles len", gt))
}
gt.updateData(t)
2017-01-20 11:40:48 -06:00
gt.submitData()
}
func (gt *glTriangles) Copy() pixel.Triangles {
2017-01-20 11:40:48 -06:00
return NewGLTriangles(gt.shader, gt)
}
2017-01-28 13:01:59 -06:00
func (gt *glTriangles) Draw() {
gt.vs.Begin()
gt.vs.Draw()
gt.vs.End()
}
func (gt *glTriangles) Position(i int) pixel.Vec {
2017-01-20 11:40:48 -06:00
px := gt.data[i*gt.vs.Stride()+0]
py := gt.data[i*gt.vs.Stride()+1]
return pixel.V(float64(px), float64(py))
2017-01-20 11:40:48 -06:00
}
func (gt *glTriangles) Color(i int) pixel.NRGBA {
2017-01-20 11:40:48 -06:00
r := gt.data[i*gt.vs.Stride()+2]
g := gt.data[i*gt.vs.Stride()+3]
b := gt.data[i*gt.vs.Stride()+4]
a := gt.data[i*gt.vs.Stride()+5]
return pixel.NRGBA{
2017-01-20 11:40:48 -06:00
R: float64(r),
G: float64(g),
B: float64(b),
A: float64(a),
}
}
func (gt *glTriangles) Texture(i int) pixel.Vec {
2017-01-20 11:40:48 -06:00
tx := gt.data[i*gt.vs.Stride()+6]
ty := gt.data[i*gt.vs.Stride()+7]
return pixel.V(float64(tx), float64(ty))
2017-01-20 11:40:48 -06:00
}