add indices to vertex array

This commit is contained in:
faiface 2016-12-08 15:25:00 +01:00
parent 6268c52e77
commit c87527aa5d
3 changed files with 81 additions and 81 deletions

View File

@ -114,9 +114,9 @@ func NewSprite(parent pixelgl.Doer, picture Picture) *Sprite {
s.va, err = pixelgl.NewVertexArray( s.va, err = pixelgl.NewVertexArray(
picture.Texture(), picture.Texture(),
ctx.Shader().VertexFormat(), ctx.Shader().VertexFormat(),
pixelgl.TriangleFanDrawMode,
pixelgl.DynamicUsage, pixelgl.DynamicUsage,
4, 4,
[]int{0, 1, 2, 0, 2, 3},
) )
if err != nil { if err != nil {
panic(errors.Wrap(err, "failed to create sprite")) panic(errors.Wrap(err, "failed to create sprite"))
@ -231,9 +231,9 @@ func NewLineColor(parent pixelgl.Doer, c color.Color, a, b Vec, width float64) *
lc.va, err = pixelgl.NewVertexArray( lc.va, err = pixelgl.NewVertexArray(
parent, parent,
ctx.Shader().VertexFormat(), ctx.Shader().VertexFormat(),
pixelgl.TriangleStripDrawMode,
pixelgl.DynamicUsage, pixelgl.DynamicUsage,
4, 4,
[]int{0, 1, 2, 1, 2, 3},
) )
if err != nil { if err != nil {
panic(errors.Wrap(err, "failed to create line")) panic(errors.Wrap(err, "failed to create line"))
@ -340,14 +340,19 @@ func NewPolygonColor(parent pixelgl.Doer, c color.Color, points ...Vec) *Polygon
points: points, points: points,
} }
var indices []int
for i := 2; i < len(points); i++ {
indices = append(indices, 0, i-1, i)
}
parent.Do(func(ctx pixelgl.Context) { parent.Do(func(ctx pixelgl.Context) {
var err error var err error
pc.va, err = pixelgl.NewVertexArray( pc.va, err = pixelgl.NewVertexArray(
parent, parent,
ctx.Shader().VertexFormat(), ctx.Shader().VertexFormat(),
pixelgl.TriangleFanDrawMode,
pixelgl.DynamicUsage, pixelgl.DynamicUsage,
len(points), len(points),
indices,
) )
if err != nil { if err != nil {
panic(errors.Wrap(err, "failed to create polygon")) panic(errors.Wrap(err, "failed to create polygon"))
@ -448,17 +453,22 @@ func NewEllipseColor(parent pixelgl.Doer, c color.Color, radius Vec, fill float6
fill: fill, fill: fill,
} }
var indices []int
for i := 2; i < (n+1)*2; i++ {
indices = append(indices, i-2, i-1, i)
}
parent.Do(func(ctx pixelgl.Context) { parent.Do(func(ctx pixelgl.Context) {
var err error var err error
ec.va, err = pixelgl.NewVertexArray( ec.va, err = pixelgl.NewVertexArray(
parent, parent,
ctx.Shader().VertexFormat(), ctx.Shader().VertexFormat(),
pixelgl.TriangleStripDrawMode,
pixelgl.DynamicUsage, pixelgl.DynamicUsage,
(n+1)*2, (n+1)*2,
indices,
) )
if err != nil { if err != nil {
panic(errors.Wrap(err, "failed to create circle")) panic(errors.Wrap(err, "failed to create ellipse"))
} }
}) })

View File

@ -40,55 +40,31 @@ const (
StreamUsage VertexUsage = gl.STREAM_DRAW StreamUsage VertexUsage = gl.STREAM_DRAW
) )
// VertexDrawMode specifies how should the vertices be drawn.
type VertexDrawMode int
const (
// PointsDrawMode just draws individual points
PointsDrawMode VertexDrawMode = gl.POINTS
// LinesDrawMode takes pairs of vertices and draws a line from each pair
LinesDrawMode VertexDrawMode = gl.LINES
// LineStripDrawMode takes each two subsequent vertices and draws a line from each two
LineStripDrawMode VertexDrawMode = gl.LINE_STRIP
// LineLoopDrawMode is same as line strip, but also draws a line between the first and the last vertex
LineLoopDrawMode VertexDrawMode = gl.LINE_LOOP
// TrianglesDrawMode takes triples of vertices and draws a triangle from each triple
TrianglesDrawMode VertexDrawMode = gl.TRIANGLES
// TriangleStripDrawMode takes each three subsequent vertices and draws a triangle from each three
TriangleStripDrawMode VertexDrawMode = gl.TRIANGLE_STRIP
// TriangleFanDrawMode draws triangles from the first vertex and each two subsequent: {0, 1, 2, 3} -> {0, 1, 2}, {0, 2, 3}.
TriangleFanDrawMode VertexDrawMode = gl.TRIANGLE_FAN
)
// VertexArray is an OpenGL vertex array object that also holds it's own vertex buffer object. // VertexArray is an OpenGL vertex array object that also holds it's own vertex buffer object.
// From the user's points of view, VertexArray is an array of vertices that can be drawn. // From the user's points of view, VertexArray is an array of vertices that can be drawn.
type VertexArray struct { type VertexArray struct {
enabled bool enabled bool
parent Doer parent Doer
vao uint32 vao, vbo, ebo uint32
vbo uint32 vertexNum, indexNum int
format VertexFormat format VertexFormat
stride int usage VertexUsage
count int stride int
attrs map[Attr]int attrs map[Attr]int
mode VertexDrawMode
} }
// NewVertexArray creates a new empty vertex array and wraps another Doer around it. // NewVertexArray creates a new empty vertex array and wraps another Doer around it.
func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage VertexUsage, count int) (*VertexArray, error) { //
// You cannot specify vertex attributes in this constructor, only their count. Use SetVertexAttribute* methods to
// set the vertex attributes. Use indices to specify how you want to combine vertices into triangles.
func NewVertexArray(parent Doer, format VertexFormat, usage VertexUsage, vertexNum int, indices []int) (*VertexArray, error) {
va := &VertexArray{ va := &VertexArray{
parent: parent, parent: parent,
format: format, format: format,
count: count, usage: usage,
stride: format.Size(), vertexNum: vertexNum,
attrs: make(map[Attr]int), stride: format.Size(),
mode: mode, attrs: make(map[Attr]int),
} }
offset := 0 offset := 0
@ -105,18 +81,19 @@ func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage
offset += attr.Type.Size() offset += attr.Type.Size()
} }
var err error
parent.Do(func(ctx Context) { parent.Do(func(ctx Context) {
err = DoErr(func() error { Do(func() {
gl.GenVertexArrays(1, &va.vao) gl.GenVertexArrays(1, &va.vao)
gl.BindVertexArray(va.vao) gl.BindVertexArray(va.vao)
gl.GenBuffers(1, &va.vbo) gl.GenBuffers(1, &va.vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo) gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
emptyData := make([]byte, count*va.stride) emptyData := make([]byte, vertexNum*va.stride)
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), uint32(usage)) gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), uint32(usage))
gl.GenBuffers(1, &va.ebo)
offset := 0 offset := 0
for i, attr := range format { for i, attr := range format {
var size int32 var size int32
@ -143,15 +120,16 @@ func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage
offset += attr.Type.Size() offset += attr.Type.Size()
} }
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, va.ebo) // need to bind EBO, so that VAO registers it
gl.BindBuffer(gl.ARRAY_BUFFER, 0) gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindVertexArray(0) gl.BindVertexArray(0)
return nil gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
}) })
}) })
if err != nil {
return nil, errors.Wrap(err, "failed to create vertex array") va.SetIndices(indices)
}
return va, nil return va, nil
} }
@ -173,7 +151,7 @@ func (va *VertexArray) ID() uint32 {
// Count returns the number of vertices in a vertex array. // Count returns the number of vertices in a vertex array.
func (va *VertexArray) Count() int { func (va *VertexArray) Count() int {
return va.count return va.vertexNum
} }
// VertexFormat returns the format of the vertices inside a vertex array. // VertexFormat returns the format of the vertices inside a vertex array.
@ -183,19 +161,9 @@ func (va *VertexArray) VertexFormat() VertexFormat {
return va.format return va.format
} }
// SetDrawMode sets the draw mode of a vertex array. Subsequent calls to Draw will use this draw mode. // VertexUsage returns the usage of the verteices inside a vertex array.
func (va *VertexArray) SetDrawMode(mode VertexDrawMode) { func (va *VertexArray) VertexUsage() VertexUsage {
DoNoBlock(func() { return va.usage
va.mode = mode
})
}
// DrawMode returns the most recently set draw mode of a vertex array.
func (va *VertexArray) DrawMode() VertexDrawMode {
mode := DoVal(func() interface{} {
return va.mode
})
return mode.(VertexDrawMode)
} }
// Draw draws a vertex array. // Draw draws a vertex array.
@ -203,10 +171,29 @@ func (va *VertexArray) Draw() {
va.Do(func(Context) {}) va.Do(func(Context) {})
} }
// SetIndices sets the indices of triangles to be drawn. Triangles will be formed from the vertices of the array
// as defined by these indices. The first drawn triangle is specified by the first three indices, the second by
// the fourth through sixth and so on.
func (va *VertexArray) SetIndices(indices []int) {
if len(indices)%3 != 0 {
panic("vertex array set indices: number of indices not divisible by 3")
}
indices32 := make([]uint32, len(indices))
for i := range indices32 {
indices32[i] = uint32(indices[i])
}
va.indexNum = len(indices32)
DoNoBlock(func() {
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, va.ebo)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, 4*len(indices32), gl.Ptr(indices32), uint32(va.usage))
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
})
}
// SetVertex sets the value of all attributes of a vertex. // SetVertex sets the value of all attributes of a vertex.
// Argument data must be a slice/array containing the new vertex data. // Argument data must be a slice/array containing the new vertex data.
func (va *VertexArray) SetVertex(vertex int, data interface{}) { func (va *VertexArray) SetVertex(vertex int, data interface{}) {
if vertex < 0 || vertex >= va.count { if vertex < 0 || vertex >= va.vertexNum {
panic("set vertex error: invalid vertex index") panic("set vertex error: invalid vertex index")
} }
DoNoBlock(func() { DoNoBlock(func() {
@ -220,7 +207,7 @@ func (va *VertexArray) SetVertex(vertex int, data interface{}) {
} }
func (va *VertexArray) checkVertex(vertex int) { func (va *VertexArray) checkVertex(vertex int) {
if vertex < 0 || vertex >= va.count { if vertex < 0 || vertex >= va.vertexNum {
panic("invalid vertex index") panic("invalid vertex index")
} }
} }
@ -322,14 +309,12 @@ func (va *VertexArray) Do(sub func(Context)) {
} }
DoNoBlock(func() { DoNoBlock(func() {
gl.BindVertexArray(va.vao) gl.BindVertexArray(va.vao)
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
}) })
va.enabled = true va.enabled = true
sub(ctx) sub(ctx)
va.enabled = false va.enabled = false
DoNoBlock(func() { DoNoBlock(func() {
gl.DrawArrays(uint32(va.mode), 0, int32(va.count)) gl.DrawElements(gl.TRIANGLES, int32(va.indexNum), gl.UNSIGNED_INT, gl.PtrOffset(0))
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindVertexArray(0) gl.BindVertexArray(0)
}) })
}) })

View File

@ -53,6 +53,7 @@ type WindowConfig struct {
// Window is a window handler. Use this type to manipulate a window (input, drawing, ...). // Window is a window handler. Use this type to manipulate a window (input, drawing, ...).
type Window struct { type Window struct {
enabled bool
window *glfw.Window window *glfw.Window
config WindowConfig config WindowConfig
contextHolder pixelgl.ContextHolder contextHolder pixelgl.ContextHolder
@ -314,22 +315,26 @@ var currentWindow struct {
// Do makes the context of this window current, if it's not already, and executes sub. // Do makes the context of this window current, if it's not already, and executes sub.
func (w *Window) Do(sub func(pixelgl.Context)) { func (w *Window) Do(sub func(pixelgl.Context)) {
currentWindow.Lock() if !w.enabled {
defer currentWindow.Unlock() currentWindow.Lock()
defer currentWindow.Unlock()
if currentWindow.handler != w { if currentWindow.handler != w {
pixelgl.Do(func() { pixelgl.Do(func() {
w.window.MakeContextCurrent() w.window.MakeContextCurrent()
pixelgl.Init() pixelgl.Init()
}) })
currentWindow.handler = w currentWindow.handler = w
}
} }
w.enabled = true
if w.defaultShader != nil { if w.defaultShader != nil {
w.defaultShader.Do(sub) w.defaultShader.Do(sub)
} else { } else {
w.contextHolder.Do(sub) w.contextHolder.Do(sub)
} }
w.enabled = false
} }
var defaultVertexFormat = pixelgl.VertexFormat{ var defaultVertexFormat = pixelgl.VertexFormat{