go-opengl-pixel/pixelgl/vertex.go

187 lines
5.5 KiB
Go
Raw Normal View History

2016-11-23 07:03:23 -06:00
package pixelgl
2016-11-23 08:59:21 -06:00
import "github.com/go-gl/gl/v3.3-core/gl"
2016-11-23 07:03:23 -06:00
// VertexFormat defines a data format in a vertex buffer.
//
// Example:
//
// vf := VertexFormat{{Position, 2}, {Color, 4}, {TexCoord, 2}}
type VertexFormat []VertexAttribute
2016-11-23 08:59:21 -06:00
// Size returns the total size of all vertex attributes in a vertex format.
func (vf VertexFormat) Size() int {
size := 0
for _, va := range vf {
size += va.Size
}
return size
}
2016-11-23 07:03:23 -06:00
// VertexAttribute specifies a single attribute in a vertex buffer.
// All vertex attributes are composed of float64s.
//
// A vertex attribute has a Purpose (such as Position, Color, etc.) and Size. Size specifies
// the number of float64s the vertex attribute is composed of.
type VertexAttribute struct {
Purpose VertexAttributePurpose
Size int
}
// VertexAttributePurpose clarifies the purpose of a vertex attribute. This can be a color, position, texture
// coordinates or anything else.
//
// VertexAttributePurpose may be used to correctly assign data to a vertex buffer.
type VertexAttributePurpose int
// Position, Color and TexCoord are the standard vertex attributes.
//
// Feel free to define more vertex attribute purposes (e.g. in an effects library).
const (
Position VertexAttributePurpose = iota
Color
TexCoord
NumStandardVertexAttrib
)
2016-11-23 08:59:21 -06:00
// VertexUsage specifies how often the vertex array data will be updated.
type VertexUsage int
// Possible VertexUsage values are:
// 1. StaticUsage - never or rarely updated
// 2. DynamicUsage - often updated
// 3. StreamUsage - updated every frame
const (
StaticUsage VertexUsage = gl.STATIC_DRAW
DynamicUsage = gl.DYNAMIC_DRAW
StreamUsage = gl.STREAM_DRAW
)
// VertexDrawMode specifies how should the vertices be drawn.
type VertexDrawMode int
// Possible VertexDrawMode values are:
// 1. PointsDrawMode - just draw individual PointsDrawMode
// 2. LinesDrawMode - take pairs of vertices and draw a line from each pair
// 3. LineStripDrawMode - take each two subsequent vertices and draw a line from each two
// 4. LineLoopDrawMode - same as line strip, but also draw a line between the first and the last vertex
// 5. TrianglesDrawMode - take triples of vertices and draw a triangle from each triple
// 6. TriangleStripDrawMode - take each three subsequent vertices and draw a triangle from each three
// 7. TriangleFanDrawMode - take each two subsequent vertices excluding the first vertex and draw a triangle from the first vertex and the two
const (
PointsDrawMode VertexDrawMode = gl.POINTS
LinesDrawMode = gl.LINES
LineStripDrawMode = gl.LINE_STRIP
LineLoopDrawMode = gl.LINE_LOOP
TrianglesDrawMode = gl.TRIANGLES
TriangleStripDrawMode = gl.TRIANGLE_STRIP
TriangleFanDrawMode = gl.TRIANGLE_FAN
)
// 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.
type VertexArray struct {
parent BeginEnder
format VertexFormat
vao uint32
vbo uint32
mode VertexDrawMode
count int
}
// NewVertexArray creates a new vertex array and wrap another BeginEnder around it.
func NewVertexArray(parent BeginEnder, format VertexFormat, mode VertexDrawMode, usage VertexUsage, data []float64) *VertexArray {
va := &VertexArray{
parent: parent,
format: format,
mode: mode,
}
Do(func() {
gl.GenVertexArrays(1, &va.vao)
gl.BindVertexArray(va.vao)
gl.GenBuffers(1, &va.vbo)
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
gl.BufferData(gl.ARRAY_BUFFER, 8*len(data), gl.Ptr(data), uint32(usage))
stride := format.Size()
va.count = len(data) / stride
offset := 0
for i, attr := range format {
gl.VertexAttribPointer(
uint32(i),
int32(attr.Size),
gl.DOUBLE,
false,
int32(stride),
gl.PtrOffset(8*offset),
)
gl.EnableVertexAttribArray(uint32(i))
offset += attr.Size
}
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindVertexArray(0)
})
return va
}
// VertexFormat returns the format of the vertices inside a vertex array.
//
// Do not change this format!
func (va *VertexArray) VertexFormat() VertexFormat {
return va.format
}
// SetDrawMode sets the draw mode of a vertex array. Subsequent calls to Draw will use this draw mode.
func (va *VertexArray) SetDrawMode(mode VertexDrawMode) {
Do(func() {
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.
func (va *VertexArray) Draw() {
va.Begin()
va.End()
}
// UpdateData overwrites the current vertex array data starting at the index offset.
//
// Offset is not a number of bytes, instead, it's an index in the array.
func (va *VertexArray) UpdateData(offset int, data []float64) {
Do(func() {
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
gl.BufferSubData(gl.ARRAY_BUFFER, 8*offset, 8*len(data), gl.Ptr(data))
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
})
}
// Begin binds a vertex array and it's associated vertex buffer.
func (va *VertexArray) Begin() {
va.parent.Begin()
Do(func() {
gl.BindVertexArray(va.vao)
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
})
}
// End draws a vertex array and unbinds it alongside with it's associated vertex buffer.
func (va *VertexArray) End() {
Do(func() {
gl.DrawArrays(uint32(va.mode), 0, int32(va.count))
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindVertexArray(0)
})
va.parent.End()
}