|
@@ -9,23 +9,23 @@ import (
|
|
|
"unsafe"
|
|
"unsafe"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-// VBO abstracts an OpenGL Vertex Buffer Object
|
|
|
|
|
|
|
+// VBO abstracts an OpenGL Vertex Buffer Object.
|
|
|
type VBO struct {
|
|
type VBO struct {
|
|
|
- gs *GLS // reference to GLS state
|
|
|
|
|
|
|
+ gs *GLS // Reference to OpenGL state
|
|
|
handle uint32 // OpenGL handle for this VBO
|
|
handle uint32 // OpenGL handle for this VBO
|
|
|
- usage uint32 // Expected usage patter of the buffer
|
|
|
|
|
|
|
+ usage uint32 // Expected usage pattern of the buffer
|
|
|
update bool // Update flag
|
|
update bool // Update flag
|
|
|
buffer math32.ArrayF32 // Data buffer
|
|
buffer math32.ArrayF32 // Data buffer
|
|
|
attribs []VBOattrib // List of attributes
|
|
attribs []VBOattrib // List of attributes
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// VBOattrib describes one attribute of an OpenGL Vertex Buffer Object
|
|
|
|
|
|
|
+// VBOattrib describes one attribute of an OpenGL Vertex Buffer Object.
|
|
|
type VBOattrib struct {
|
|
type VBOattrib struct {
|
|
|
Name string // Name of of the attribute
|
|
Name string // Name of of the attribute
|
|
|
- ItemSize int32 // Number of elements for each item
|
|
|
|
|
|
|
+ ItemSize int32 // Number of elements
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// NewVBO creates and returns a pointer to a new OpenGL Vertex Buffer Object
|
|
|
|
|
|
|
+// NewVBO creates and returns a pointer to a new OpenGL Vertex Buffer Object.
|
|
|
func NewVBO() *VBO {
|
|
func NewVBO() *VBO {
|
|
|
|
|
|
|
|
vbo := new(VBO)
|
|
vbo := new(VBO)
|
|
@@ -33,7 +33,7 @@ func NewVBO() *VBO {
|
|
|
return vbo
|
|
return vbo
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// init initializes this VBO
|
|
|
|
|
|
|
+// init initializes the VBO.
|
|
|
func (vbo *VBO) init() {
|
|
func (vbo *VBO) init() {
|
|
|
|
|
|
|
|
vbo.gs = nil
|
|
vbo.gs = nil
|
|
@@ -43,7 +43,7 @@ func (vbo *VBO) init() {
|
|
|
vbo.attribs = make([]VBOattrib, 0)
|
|
vbo.attribs = make([]VBOattrib, 0)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// AddAttrib adds a new attribute to this VBO
|
|
|
|
|
|
|
+// AddAttrib adds a new attribute to the VBO.
|
|
|
func (vbo *VBO) AddAttrib(name string, itemSize int32) *VBO {
|
|
func (vbo *VBO) AddAttrib(name string, itemSize int32) *VBO {
|
|
|
|
|
|
|
|
vbo.attribs = append(vbo.attribs, VBOattrib{
|
|
vbo.attribs = append(vbo.attribs, VBOattrib{
|
|
@@ -53,8 +53,8 @@ func (vbo *VBO) AddAttrib(name string, itemSize int32) *VBO {
|
|
|
return vbo
|
|
return vbo
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Attrib finds and returns pointer the attribute with the specified name
|
|
|
|
|
-// or nil if not found
|
|
|
|
|
|
|
+// Attrib finds and returns a pointer to the VBO attribute with the specified name.
|
|
|
|
|
+// Returns nil if not found.
|
|
|
func (vbo *VBO) Attrib(name string) *VBOattrib {
|
|
func (vbo *VBO) Attrib(name string) *VBOattrib {
|
|
|
|
|
|
|
|
for _, attr := range vbo.attribs {
|
|
for _, attr := range vbo.attribs {
|
|
@@ -65,20 +65,26 @@ func (vbo *VBO) Attrib(name string) *VBOattrib {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// AttribAt returns pointer to the VBO attribute at the specified index
|
|
|
|
|
|
|
+// AttribAt returns a pointer to the VBO attribute at the specified index.
|
|
|
func (vbo *VBO) AttribAt(idx int) *VBOattrib {
|
|
func (vbo *VBO) AttribAt(idx int) *VBOattrib {
|
|
|
|
|
|
|
|
return &vbo.attribs[idx]
|
|
return &vbo.attribs[idx]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// AttribCount returns the current number of attributes for this VBO
|
|
|
|
|
|
|
+// AttribCount returns the current number of attributes for this VBO.
|
|
|
func (vbo *VBO) AttribCount() int {
|
|
func (vbo *VBO) AttribCount() int {
|
|
|
|
|
|
|
|
return len(vbo.attribs)
|
|
return len(vbo.attribs)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Dispose disposes of this VBO OpenGL resources
|
|
|
|
|
-// As currently the VBO is used only by the Geometry object
|
|
|
|
|
|
|
+// Attributes returns the attributes for this VBO.
|
|
|
|
|
+func (vbo *VBO) Attributes() []VBOattrib {
|
|
|
|
|
+
|
|
|
|
|
+ return vbo.attribs
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Dispose disposes of the OpenGL resources used by the VBO.
|
|
|
|
|
+// As currently the VBO is used only by Geometry objects
|
|
|
// it is not referenced counted.
|
|
// it is not referenced counted.
|
|
|
func (vbo *VBO) Dispose() {
|
|
func (vbo *VBO) Dispose() {
|
|
|
|
|
|
|
@@ -88,7 +94,7 @@ func (vbo *VBO) Dispose() {
|
|
|
vbo.gs = nil
|
|
vbo.gs = nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// SetBuffer sets the VBO buffer
|
|
|
|
|
|
|
+// SetBuffer sets the VBO buffer.
|
|
|
func (vbo *VBO) SetBuffer(buffer math32.ArrayF32) *VBO {
|
|
func (vbo *VBO) SetBuffer(buffer math32.ArrayF32) *VBO {
|
|
|
|
|
|
|
|
vbo.buffer = buffer
|
|
vbo.buffer = buffer
|
|
@@ -103,33 +109,58 @@ func (vbo *VBO) SetUsage(usage uint32) {
|
|
|
vbo.usage = usage
|
|
vbo.usage = usage
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Buffer returns pointer to the VBO buffer
|
|
|
|
|
|
|
+// Buffer returns a pointer to the VBO buffer.
|
|
|
func (vbo *VBO) Buffer() *math32.ArrayF32 {
|
|
func (vbo *VBO) Buffer() *math32.ArrayF32 {
|
|
|
|
|
|
|
|
return &vbo.buffer
|
|
return &vbo.buffer
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Update sets the update flag to force the VBO update
|
|
|
|
|
|
|
+// Update sets the update flag to force the VBO update.
|
|
|
func (vbo *VBO) Update() {
|
|
func (vbo *VBO) Update() {
|
|
|
|
|
|
|
|
vbo.update = true
|
|
vbo.update = true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Stride returns the stride of this VBO which is the number of bytes
|
|
|
|
|
-// used by one group attributes side by side in the buffer
|
|
|
|
|
-// Ex: x y z r g b x y z r g b ...x y z r g b
|
|
|
|
|
-// The stride will be: sizeof(float) * 6 = 24
|
|
|
|
|
|
|
+// AttribOffset returns the total number of elements from
|
|
|
|
|
+// all attributes preceding the specified attribute.
|
|
|
|
|
+func (vbo *VBO) AttribOffset(name string) int {
|
|
|
|
|
+
|
|
|
|
|
+ elementCount := 0
|
|
|
|
|
+ for _, attr := range vbo.attribs {
|
|
|
|
|
+ if attr.Name == name {
|
|
|
|
|
+ return elementCount
|
|
|
|
|
+ }
|
|
|
|
|
+ elementCount += int(attr.ItemSize)
|
|
|
|
|
+ }
|
|
|
|
|
+ return elementCount
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Stride returns the stride of the VBO, which is the number of elements in
|
|
|
|
|
+// one complete set of group attributes. E.g. for an interleaved VBO with two attributes:
|
|
|
|
|
+// "VertexPosition" (3 elements) and "VertexTexcoord" (2 elements), the stride would be 5:
|
|
|
|
|
+// [X, Y, Z, U, V], X, Y, Z, U, V, X, Y, Z, U, V... X, Y, Z, U, V.
|
|
|
func (vbo *VBO) Stride() int {
|
|
func (vbo *VBO) Stride() int {
|
|
|
|
|
|
|
|
stride := 0
|
|
stride := 0
|
|
|
- elsize := int(unsafe.Sizeof(float32(0)))
|
|
|
|
|
for _, attrib := range vbo.attribs {
|
|
for _, attrib := range vbo.attribs {
|
|
|
- stride += elsize * int(attrib.ItemSize)
|
|
|
|
|
|
|
+ stride += int(attrib.ItemSize)
|
|
|
}
|
|
}
|
|
|
return stride
|
|
return stride
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// Transfer is called internally and transfer the data in the VBO buffer to OpenGL if necessary
|
|
|
|
|
|
|
+// StrideSize returns the number of bytes used by one complete set of group attributes.
|
|
|
|
|
+// E.g. for an interleaved VBO with two attributes: "VertexPosition" (3 elements)
|
|
|
|
|
+// and "VertexTexcoord" (2 elements), the stride would be 5:
|
|
|
|
|
+// [X, Y, Z, U, V], X, Y, Z, U, V, X, Y, Z, U, V... X, Y, Z, U, V
|
|
|
|
|
+// and the stride size would be: sizeof(float)*stride = 4*5 = 20
|
|
|
|
|
+func (vbo *VBO) StrideSize() int {
|
|
|
|
|
+
|
|
|
|
|
+ stride := vbo.Stride()
|
|
|
|
|
+ elsize := int(unsafe.Sizeof(float32(0)))
|
|
|
|
|
+ return stride * elsize
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// Transfer (called internally) transfers the data from the VBO buffer to OpenGL if necessary.
|
|
|
func (vbo *VBO) Transfer(gs *GLS) {
|
|
func (vbo *VBO) Transfer(gs *GLS) {
|
|
|
|
|
|
|
|
// If the VBO buffer is empty, ignore
|
|
// If the VBO buffer is empty, ignore
|
|
@@ -141,8 +172,8 @@ func (vbo *VBO) Transfer(gs *GLS) {
|
|
|
if vbo.gs == nil {
|
|
if vbo.gs == nil {
|
|
|
vbo.handle = gs.GenBuffer()
|
|
vbo.handle = gs.GenBuffer()
|
|
|
gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
|
|
gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
|
|
|
- // Calculates stride
|
|
|
|
|
- stride := vbo.Stride()
|
|
|
|
|
|
|
+ // Calculates stride size
|
|
|
|
|
+ strideSize := vbo.StrideSize()
|
|
|
// For each attribute
|
|
// For each attribute
|
|
|
var items uint32
|
|
var items uint32
|
|
|
var offset uint32
|
|
var offset uint32
|
|
@@ -155,15 +186,18 @@ func (vbo *VBO) Transfer(gs *GLS) {
|
|
|
}
|
|
}
|
|
|
// Enables attribute and sets its stride and offset in the buffer
|
|
// Enables attribute and sets its stride and offset in the buffer
|
|
|
gs.EnableVertexAttribArray(uint32(loc))
|
|
gs.EnableVertexAttribArray(uint32(loc))
|
|
|
- gs.VertexAttribPointer(uint32(loc), attrib.ItemSize, FLOAT, false, int32(stride), offset)
|
|
|
|
|
|
|
+ gs.VertexAttribPointer(uint32(loc), attrib.ItemSize, FLOAT, false, int32(strideSize), offset)
|
|
|
items += uint32(attrib.ItemSize)
|
|
items += uint32(attrib.ItemSize)
|
|
|
offset = uint32(elsize) * items
|
|
offset = uint32(elsize) * items
|
|
|
}
|
|
}
|
|
|
vbo.gs = gs // this indicates that the vbo was initialized
|
|
vbo.gs = gs // this indicates that the vbo was initialized
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // If nothing has changed, no need to transfer data to OpenGL
|
|
|
if !vbo.update {
|
|
if !vbo.update {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
// Transfer the VBO data to OpenGL
|
|
// Transfer the VBO data to OpenGL
|
|
|
gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
|
|
gs.BindBuffer(ARRAY_BUFFER, vbo.handle)
|
|
|
gs.BufferData(ARRAY_BUFFER, vbo.buffer.Bytes(), &vbo.buffer[0], vbo.usage)
|
|
gs.BufferData(ARRAY_BUFFER, vbo.buffer.Bytes(), &vbo.buffer[0], vbo.usage)
|