use new attr
This commit is contained in:
parent
9d4111282e
commit
96f134d4c4
|
@ -0,0 +1,69 @@
|
||||||
|
package pixelgl
|
||||||
|
|
||||||
|
// Attr represents an arbitrary OpenGL attribute, such as a vertex attribute or a shader uniform attribute.
|
||||||
|
type Attr struct {
|
||||||
|
Purpose AttrPurpose
|
||||||
|
Type AttrType
|
||||||
|
}
|
||||||
|
|
||||||
|
// AttrPurpose specified a purpose of an attribute. Feel free to create your own purposes for your own needs.
|
||||||
|
type AttrPurpose int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Position of a vertex
|
||||||
|
Position AttrPurpose = iota
|
||||||
|
// Color of a vertex
|
||||||
|
Color
|
||||||
|
// TexCoord are texture coordinates
|
||||||
|
TexCoord
|
||||||
|
// Transform is an object transformation matrix
|
||||||
|
Transform
|
||||||
|
// Camera is a camera view matrix
|
||||||
|
Camera
|
||||||
|
)
|
||||||
|
|
||||||
|
// AttrType represents the type of an OpenGL attribute.
|
||||||
|
//
|
||||||
|
// Important note: Int is 32-bit and Float is 64-bit.
|
||||||
|
type AttrType int
|
||||||
|
|
||||||
|
// List of all possible attribute types.
|
||||||
|
const (
|
||||||
|
Bool AttrType = iota
|
||||||
|
Int
|
||||||
|
Float
|
||||||
|
Vec2
|
||||||
|
Vec3
|
||||||
|
Vec4
|
||||||
|
Mat2
|
||||||
|
Mat23
|
||||||
|
Mat24
|
||||||
|
Mat3
|
||||||
|
Mat32
|
||||||
|
Mat34
|
||||||
|
Mat4
|
||||||
|
Mat42
|
||||||
|
Mat43
|
||||||
|
)
|
||||||
|
|
||||||
|
// Size returns the size of a type in bytes.
|
||||||
|
func (at AttrType) Size() int {
|
||||||
|
sizeOf := map[AttrType]int{
|
||||||
|
Bool: 1,
|
||||||
|
Int: 4,
|
||||||
|
Float: 8,
|
||||||
|
Vec2: 2 * 8,
|
||||||
|
Vec3: 3 * 8,
|
||||||
|
Vec4: 4 * 8,
|
||||||
|
Mat2: 2 * 2 * 8,
|
||||||
|
Mat23: 2 * 3 * 8,
|
||||||
|
Mat24: 2 * 4 * 8,
|
||||||
|
Mat3: 3 * 3 * 8,
|
||||||
|
Mat32: 3 * 2 * 8,
|
||||||
|
Mat34: 3 * 4 * 8,
|
||||||
|
Mat4: 4 * 4 * 8,
|
||||||
|
Mat42: 4 * 2 * 8,
|
||||||
|
Mat43: 4 * 3 * 8,
|
||||||
|
}
|
||||||
|
return sizeOf[at]
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package pixelgl
|
package pixelgl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -9,44 +11,18 @@ import (
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// vf := VertexFormat{{Position, 2}, {Color, 4}, {TexCoord, 2}}
|
// VertexFormat{{Position, Vec2}, {Color, Vec4}, {TexCoord, Vec2}, {Visible, Bool}}
|
||||||
type VertexFormat []VertexAttribute
|
type VertexFormat []Attr
|
||||||
|
|
||||||
// Size returns the total size of all vertex attributes in a vertex format.
|
// Size calculates the total size of a single vertex in this vertex format (sum of the sizes of all vertex attributes).
|
||||||
func (vf VertexFormat) Size() int {
|
func (vf VertexFormat) Size() int {
|
||||||
size := 0
|
total := 0
|
||||||
for _, va := range vf {
|
for _, attr := range vf {
|
||||||
size += va.Size
|
total += attr.Type.Size()
|
||||||
}
|
}
|
||||||
return size
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
)
|
|
||||||
|
|
||||||
// VertexUsage specifies how often the vertex array data will be updated.
|
// VertexUsage specifies how often the vertex array data will be updated.
|
||||||
type VertexUsage int
|
type VertexUsage int
|
||||||
|
|
||||||
|
@ -94,34 +70,35 @@ type VertexArray struct {
|
||||||
format VertexFormat
|
format VertexFormat
|
||||||
stride int
|
stride int
|
||||||
count int
|
count int
|
||||||
attrs map[VertexAttribute]int
|
attrs map[Attr]int
|
||||||
vao uint32
|
vao uint32
|
||||||
vbo uint32
|
vbo uint32
|
||||||
mode VertexDrawMode
|
mode VertexDrawMode
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVertexArray creates a new 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, data []float64) (*VertexArray, error) {
|
func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage VertexUsage, count int) (*VertexArray, error) {
|
||||||
va := &VertexArray{
|
va := &VertexArray{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
format: format,
|
format: format,
|
||||||
|
count: count,
|
||||||
stride: format.Size(),
|
stride: format.Size(),
|
||||||
count: len(data) / format.Size(),
|
attrs: make(map[Attr]int),
|
||||||
attrs: make(map[VertexAttribute]int),
|
|
||||||
mode: mode,
|
mode: mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(data)%format.Size() != 0 {
|
|
||||||
return nil, errors.New("failed to create vertex array: data length not divisable by format size")
|
|
||||||
}
|
|
||||||
|
|
||||||
offset := 0
|
offset := 0
|
||||||
for _, attr := range format {
|
for _, attr := range format {
|
||||||
|
switch attr.Type {
|
||||||
|
case Bool, Int, Float, Vec2, Vec3, Vec4:
|
||||||
|
default:
|
||||||
|
return nil, errors.New("failed to create vertex array: invalid vertex format: invalid attribute type")
|
||||||
|
}
|
||||||
if _, ok := va.attrs[attr]; ok {
|
if _, ok := va.attrs[attr]; ok {
|
||||||
return nil, errors.New("failed to create vertex array: invalid vertex format: duplicate vertex attribute")
|
return nil, errors.New("failed to create vertex array: invalid vertex format: duplicate vertex attribute")
|
||||||
}
|
}
|
||||||
va.attrs[attr] = offset
|
va.attrs[attr] = offset
|
||||||
offset += attr.Size
|
offset += attr.Type.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -132,20 +109,46 @@ func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage
|
||||||
|
|
||||||
gl.GenBuffers(1, &va.vbo)
|
gl.GenBuffers(1, &va.vbo)
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||||
gl.BufferData(gl.ARRAY_BUFFER, 8*len(data), gl.Ptr(data), uint32(usage))
|
|
||||||
|
emptyData := make([]byte, count*va.stride)
|
||||||
|
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), uint32(usage))
|
||||||
|
|
||||||
offset := 0
|
offset := 0
|
||||||
for i, attr := range format {
|
for i, attr := range format {
|
||||||
|
//XXX: ugly but OpenGL is so inconsistent
|
||||||
|
|
||||||
|
var size int32
|
||||||
|
switch attr.Type {
|
||||||
|
case Bool, Int, Float:
|
||||||
|
size = 1
|
||||||
|
case Vec2:
|
||||||
|
size = 2
|
||||||
|
case Vec3:
|
||||||
|
size = 3
|
||||||
|
case Vec4:
|
||||||
|
size = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
var xtype uint32
|
||||||
|
switch attr.Type {
|
||||||
|
case Bool:
|
||||||
|
xtype = gl.BOOL
|
||||||
|
case Int:
|
||||||
|
xtype = gl.INT
|
||||||
|
case Float, Vec2, Vec3, Vec4:
|
||||||
|
xtype = gl.DOUBLE
|
||||||
|
}
|
||||||
|
|
||||||
gl.VertexAttribPointer(
|
gl.VertexAttribPointer(
|
||||||
uint32(i),
|
uint32(i),
|
||||||
int32(attr.Size),
|
size,
|
||||||
gl.DOUBLE,
|
xtype,
|
||||||
false,
|
false,
|
||||||
int32(8*va.stride),
|
int32(va.stride),
|
||||||
gl.PtrOffset(8*offset),
|
gl.PtrOffset(offset),
|
||||||
)
|
)
|
||||||
gl.EnableVertexAttribArray(uint32(i))
|
gl.EnableVertexAttribArray(uint32(i))
|
||||||
offset += attr.Size
|
offset += attr.Type.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||||
|
@ -169,6 +172,11 @@ func (va *VertexArray) Delete() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Count returns the number of vertices in a vertex array.
|
||||||
|
func (va *VertexArray) Count() int {
|
||||||
|
return va.count
|
||||||
|
}
|
||||||
|
|
||||||
// VertexFormat returns the format of the vertices inside a vertex array.
|
// VertexFormat returns the format of the vertices inside a vertex array.
|
||||||
//
|
//
|
||||||
// Do not change this format!
|
// Do not change this format!
|
||||||
|
@ -196,33 +204,40 @@ func (va *VertexArray) Draw() {
|
||||||
va.Do(func(Context) {})
|
va.Do(func(Context) {})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data returns a copy of data inside a vertex array (actually it's vertex buffer).
|
// SetVertex sets the value of all attributes of a vertex.
|
||||||
func (va *VertexArray) Data() []float64 {
|
// Argument data must point to a slice/array containing the new vertex data.
|
||||||
data := make([]float64, va.count*va.format.Size())
|
func (va *VertexArray) SetVertex(vertex int, data unsafe.Pointer) {
|
||||||
Do(func() {
|
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
|
||||||
gl.GetBufferSubData(gl.ARRAY_BUFFER, 0, 8*len(data), gl.Ptr(data))
|
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
|
||||||
})
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetVertexAttribute sets the value of the specified vertex attribute of the specified vertex.
|
|
||||||
func (va *VertexArray) SetVertexAttribute(vertex int, attr VertexAttribute, data []float64) {
|
|
||||||
if len(data) != attr.Size {
|
|
||||||
panic("set vertex attribute error: invalid data length")
|
|
||||||
}
|
|
||||||
if vertex < 0 || vertex >= va.count {
|
if vertex < 0 || vertex >= va.count {
|
||||||
panic("set vertex attribute error: invalid vertex index")
|
panic("set vertex error: invalid vertex index")
|
||||||
}
|
|
||||||
if _, ok := va.attrs[attr]; !ok {
|
|
||||||
panic("set vertex attribute error: invalid vertex attribute")
|
|
||||||
}
|
}
|
||||||
DoNoBlock(func() {
|
DoNoBlock(func() {
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||||
|
|
||||||
offset := 8*va.stride*vertex + 8*va.attrs[attr]
|
offset := va.stride * vertex
|
||||||
gl.BufferSubData(gl.ARRAY_BUFFER, offset, 8*len(data), gl.Ptr(data))
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, va.format.Size(), data)
|
||||||
|
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
|
if err := getLastGLErr(); err != nil {
|
||||||
|
panic(errors.Wrap(err, "set vertex error"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVertexAttribute sets the value of the specified vertex attribute of the specified vertex.
|
||||||
|
// Argument data must point to a slice/array containing the new attribute data.
|
||||||
|
func (va *VertexArray) SetVertexAttribute(vertex int, attr Attr, data unsafe.Pointer) {
|
||||||
|
if vertex < 0 || vertex >= va.count {
|
||||||
|
panic("set vertex attribute error: invalid vertex index")
|
||||||
|
}
|
||||||
|
if _, ok := va.attrs[attr]; !ok {
|
||||||
|
return // ignore non-existing attributes
|
||||||
|
}
|
||||||
|
DoNoBlock(func() {
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||||
|
|
||||||
|
offset := va.stride*vertex + va.attrs[attr]
|
||||||
|
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), data)
|
||||||
|
|
||||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue