add fast VertexArray.SetVertex and VertexArray.Set methods
This commit is contained in:
parent
6986e8a000
commit
800add157d
68
graphics.go
68
graphics.go
|
@ -209,6 +209,8 @@ func NewMultiShape(parent pixelgl.Doer, shapes ...*Shape) *MultiShape {
|
|||
}
|
||||
})
|
||||
|
||||
//TODO: optimize with VertexArray.Set
|
||||
|
||||
offset = 0
|
||||
for _, shape := range shapes {
|
||||
for i := 0; i < shape.VertexArray().VertexNum(); i++ {
|
||||
|
@ -272,6 +274,8 @@ func NewSprite(parent pixelgl.Doer, picture *Picture) *Sprite {
|
|||
}
|
||||
})
|
||||
|
||||
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
||||
|
||||
w, h := picture.Bounds().Size.XY()
|
||||
for i, p := range []Vec{V(0, 0), V(w, 0), V(w, h), V(0, h)} {
|
||||
texCoord := V(
|
||||
|
@ -279,11 +283,15 @@ func NewSprite(parent pixelgl.Doer, picture *Picture) *Sprite {
|
|||
(picture.Bounds().Y()+p.Y())/float64(picture.Texture().Height()),
|
||||
)
|
||||
|
||||
va.SetVertexAttr(i, positionVec2, mgl32.Vec2{float32(p.X()), float32(p.Y())})
|
||||
va.SetVertexAttr(i, colorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||
va.SetVertexAttr(i, texCoordVec2, mgl32.Vec2{float32(texCoord.X()), float32(texCoord.Y())})
|
||||
vertices[i] = map[pixelgl.Attr]interface{}{
|
||||
positionVec2: mgl32.Vec2{float32(p.X()), float32(p.Y())},
|
||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||
texCoordVec2: mgl32.Vec2{float32(texCoord.X()), float32(texCoord.Y())},
|
||||
}
|
||||
}
|
||||
|
||||
va.Set(vertices)
|
||||
|
||||
return &Sprite{NewShape(parent, picture, color.White, Position(0), va)}
|
||||
}
|
||||
|
||||
|
@ -312,11 +320,17 @@ func NewLineColor(parent pixelgl.Doer, c color.Color, a, b Vec, width float64) *
|
|||
}
|
||||
})
|
||||
|
||||
vertices := make([]map[pixelgl.Attr]interface{}, 4)
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
va.SetVertexAttr(i, colorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||
va.SetVertexAttr(i, texCoordVec2, mgl32.Vec2{-1, -1})
|
||||
vertices[i] = map[pixelgl.Attr]interface{}{
|
||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||
texCoordVec2: mgl32.Vec2{-1, -1},
|
||||
}
|
||||
}
|
||||
|
||||
va.Set(vertices)
|
||||
|
||||
lc := &LineColor{NewShape(parent, nil, c, Position(0), va), a, b, width}
|
||||
lc.setPoints()
|
||||
return lc
|
||||
|
@ -392,12 +406,18 @@ func NewPolygonColor(parent pixelgl.Doer, c color.Color, points ...Vec) *Polygon
|
|||
}
|
||||
})
|
||||
|
||||
vertices := make([]map[pixelgl.Attr]interface{}, len(points))
|
||||
|
||||
for i, p := range points {
|
||||
va.SetVertexAttr(i, positionVec2, mgl32.Vec2{float32(p.X()), float32(p.Y())})
|
||||
va.SetVertexAttr(i, colorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||
va.SetVertexAttr(i, texCoordVec2, mgl32.Vec2{-1, -1})
|
||||
vertices[i] = map[pixelgl.Attr]interface{}{
|
||||
positionVec2: mgl32.Vec2{float32(p.X()), float32(p.Y())},
|
||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||
texCoordVec2: mgl32.Vec2{-1, -1},
|
||||
}
|
||||
}
|
||||
|
||||
va.Set(vertices)
|
||||
|
||||
return &PolygonColor{NewShape(parent, nil, c, Position(0), va), points}
|
||||
}
|
||||
|
||||
|
@ -455,25 +475,33 @@ func NewEllipseColor(parent pixelgl.Doer, c color.Color, radius Vec, fill float6
|
|||
}
|
||||
})
|
||||
|
||||
vertices := make([]map[pixelgl.Attr]interface{}, (n+1)*2)
|
||||
|
||||
for k := 0; k < n+1; k++ {
|
||||
i, j := k*2, k*2+1
|
||||
angle := math.Pi * 2 * float64(k%n) / n
|
||||
|
||||
va.SetVertexAttr(i, positionVec2, mgl32.Vec2{
|
||||
float32(math.Cos(angle) * radius.X()),
|
||||
float32(math.Sin(angle) * radius.Y()),
|
||||
})
|
||||
va.SetVertexAttr(i, colorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||
va.SetVertexAttr(i, texCoordVec2, mgl32.Vec2{-1, -1})
|
||||
vertices[i] = map[pixelgl.Attr]interface{}{
|
||||
positionVec2: mgl32.Vec2{
|
||||
float32(math.Cos(angle) * radius.X()),
|
||||
float32(math.Sin(angle) * radius.Y()),
|
||||
},
|
||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||
texCoordVec2: mgl32.Vec2{-1, -1},
|
||||
}
|
||||
|
||||
va.SetVertexAttr(j, positionVec2, mgl32.Vec2{
|
||||
float32(math.Cos(angle) * radius.X() * (1 - fill)),
|
||||
float32(math.Sin(angle) * radius.Y() * (1 - fill)),
|
||||
})
|
||||
va.SetVertexAttr(j, colorVec4, mgl32.Vec4{1, 1, 1, 1})
|
||||
va.SetVertexAttr(j, texCoordVec2, mgl32.Vec2{-1, -1})
|
||||
vertices[j] = map[pixelgl.Attr]interface{}{
|
||||
positionVec2: mgl32.Vec2{
|
||||
float32(math.Cos(angle) * radius.X() * (1 - fill)),
|
||||
float32(math.Sin(angle) * radius.Y() * (1 - fill)),
|
||||
},
|
||||
colorVec4: mgl32.Vec4{1, 1, 1, 1},
|
||||
texCoordVec2: mgl32.Vec2{-1, -1},
|
||||
}
|
||||
}
|
||||
|
||||
va.Set(vertices)
|
||||
|
||||
return &EllipseColor{NewShape(parent, nil, c, Position(0), va), radius, fill}
|
||||
}
|
||||
|
||||
|
|
|
@ -273,6 +273,98 @@ func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok
|
|||
return value, true
|
||||
}
|
||||
|
||||
// SetVertex sets values of the attributes specified in the supplied map. All other attributes will be set to zero.
|
||||
//
|
||||
// Not existing attributes are silently skipped.
|
||||
func (va *VertexArray) SetVertex(vertex int, values map[Attr]interface{}) {
|
||||
if vertex < 0 || vertex >= va.vertexNum {
|
||||
panic("set vertex: invalid vertex index")
|
||||
}
|
||||
|
||||
data := make([]float32, va.format.Size()/4)
|
||||
|
||||
for attr, value := range values {
|
||||
if !va.format.Contains(attr) {
|
||||
continue
|
||||
}
|
||||
|
||||
offset := va.offset[attr.Name]
|
||||
|
||||
switch attr.Type {
|
||||
case Float:
|
||||
value := value.(float32)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], []float32{value})
|
||||
case Vec2:
|
||||
value := value.(mgl32.Vec2)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
case Vec3:
|
||||
value := value.(mgl32.Vec3)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
case Vec4:
|
||||
value := value.(mgl32.Vec4)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
default:
|
||||
panic("set vertex: invalid attribute type")
|
||||
}
|
||||
}
|
||||
|
||||
DoNoBlock(func() {
|
||||
va.vbo.bind()
|
||||
|
||||
offset := va.stride * vertex
|
||||
gl.BufferSubData(gl.ARRAY_BUFFER, offset, len(data)*4, gl.Ptr(data))
|
||||
|
||||
va.vbo.restore()
|
||||
})
|
||||
}
|
||||
|
||||
// Set sets values of vertex attributes of all vertices as specified in the supplied slice of maps. If the length of vertices
|
||||
// does not match the number of vertices in the vertex array, this method panics.
|
||||
//
|
||||
// Not existing attributes are silently skipped.
|
||||
func (va *VertexArray) Set(vertices []map[Attr]interface{}) {
|
||||
if len(vertices) != va.vertexNum {
|
||||
panic("set vertex array: wrong number of supplied vertices")
|
||||
}
|
||||
|
||||
data := make([]float32, va.vertexNum*va.format.Size()/4)
|
||||
|
||||
for vertex := range vertices {
|
||||
for attr, value := range vertices[vertex] {
|
||||
if !va.format.Contains(attr) {
|
||||
continue
|
||||
}
|
||||
|
||||
offset := va.stride*vertex + va.offset[attr.Name]
|
||||
|
||||
switch attr.Type {
|
||||
case Float:
|
||||
value := value.(float32)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], []float32{value})
|
||||
case Vec2:
|
||||
value := value.(mgl32.Vec2)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
case Vec3:
|
||||
value := value.(mgl32.Vec3)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
case Vec4:
|
||||
value := value.(mgl32.Vec4)
|
||||
copy(data[offset/4:offset/4+attr.Type.Size()/4], value[:])
|
||||
default:
|
||||
panic("set vertex: invalid attribute type")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoNoBlock(func() {
|
||||
va.vbo.bind()
|
||||
|
||||
gl.BufferSubData(gl.ARRAY_BUFFER, 0, len(data)*4, gl.Ptr(data))
|
||||
|
||||
va.vbo.restore()
|
||||
})
|
||||
}
|
||||
|
||||
// Do binds a vertex arrray and it's associated vertex buffer, executes sub, and unbinds the vertex array and it's vertex buffer.
|
||||
func (va *VertexArray) Do(sub func(Context)) {
|
||||
va.parent.Do(func(ctx Context) {
|
||||
|
|
Loading…
Reference in New Issue