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
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -9,44 +11,18 @@ import (
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// vf := VertexFormat{{Position, 2}, {Color, 4}, {TexCoord, 2}}
|
||||
type VertexFormat []VertexAttribute
|
||||
// VertexFormat{{Position, Vec2}, {Color, Vec4}, {TexCoord, Vec2}, {Visible, Bool}}
|
||||
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 {
|
||||
size := 0
|
||||
for _, va := range vf {
|
||||
size += va.Size
|
||||
total := 0
|
||||
for _, attr := range vf {
|
||||
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.
|
||||
type VertexUsage int
|
||||
|
||||
|
@ -94,34 +70,35 @@ type VertexArray struct {
|
|||
format VertexFormat
|
||||
stride int
|
||||
count int
|
||||
attrs map[VertexAttribute]int
|
||||
attrs map[Attr]int
|
||||
vao uint32
|
||||
vbo uint32
|
||||
mode VertexDrawMode
|
||||
}
|
||||
|
||||
// NewVertexArray creates a new vertex array and wraps another Doer around it.
|
||||
func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage VertexUsage, data []float64) (*VertexArray, error) {
|
||||
// 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) {
|
||||
va := &VertexArray{
|
||||
parent: parent,
|
||||
format: format,
|
||||
count: count,
|
||||
stride: format.Size(),
|
||||
count: len(data) / format.Size(),
|
||||
attrs: make(map[VertexAttribute]int),
|
||||
attrs: make(map[Attr]int),
|
||||
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
|
||||
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 {
|
||||
return nil, errors.New("failed to create vertex array: invalid vertex format: duplicate vertex attribute")
|
||||
}
|
||||
va.attrs[attr] = offset
|
||||
offset += attr.Size
|
||||
offset += attr.Type.Size()
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -132,20 +109,46 @@ func NewVertexArray(parent Doer, format VertexFormat, mode VertexDrawMode, usage
|
|||
|
||||
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))
|
||||
|
||||
emptyData := make([]byte, count*va.stride)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), uint32(usage))
|
||||
|
||||
offset := 0
|
||||
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(
|
||||
uint32(i),
|
||||
int32(attr.Size),
|
||||
gl.DOUBLE,
|
||||
size,
|
||||
xtype,
|
||||
false,
|
||||
int32(8*va.stride),
|
||||
gl.PtrOffset(8*offset),
|
||||
int32(va.stride),
|
||||
gl.PtrOffset(offset),
|
||||
)
|
||||
gl.EnableVertexAttribArray(uint32(i))
|
||||
offset += attr.Size
|
||||
offset += attr.Type.Size()
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
// Do not change this format!
|
||||
|
@ -196,33 +204,40 @@ func (va *VertexArray) Draw() {
|
|||
va.Do(func(Context) {})
|
||||
}
|
||||
|
||||
// Data returns a copy of data inside a vertex array (actually it's vertex buffer).
|
||||
func (va *VertexArray) Data() []float64 {
|
||||
data := make([]float64, va.count*va.format.Size())
|
||||
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")
|
||||
}
|
||||
// SetVertex sets the value of all attributes of a vertex.
|
||||
// Argument data must point to a slice/array containing the new vertex data.
|
||||
func (va *VertexArray) SetVertex(vertex int, data unsafe.Pointer) {
|
||||
if vertex < 0 || vertex >= va.count {
|
||||
panic("set vertex attribute error: invalid vertex index")
|
||||
}
|
||||
if _, ok := va.attrs[attr]; !ok {
|
||||
panic("set vertex attribute error: invalid vertex attribute")
|
||||
panic("set vertex error: invalid vertex index")
|
||||
}
|
||||
DoNoBlock(func() {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||
|
||||
offset := 8*va.stride*vertex + 8*va.attrs[attr]
|
||||
gl.BufferSubData(gl.ARRAY_BUFFER, offset, 8*len(data), gl.Ptr(data))
|
||||
offset := va.stride * vertex
|
||||
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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue