replace reentrancy by enabled by more general binder
This commit is contained in:
parent
cbfc770d4f
commit
1b01cba814
|
@ -16,9 +16,8 @@ type UniformFormat map[string]Attr
|
|||
|
||||
// Shader is an OpenGL shader program.
|
||||
type Shader struct {
|
||||
enabled bool
|
||||
parent Doer
|
||||
program uint32
|
||||
program binder
|
||||
vertexFormat VertexFormat
|
||||
uniformFormat UniformFormat
|
||||
uniforms map[Attr]int32
|
||||
|
@ -30,6 +29,12 @@ type Shader struct {
|
|||
func NewShader(parent Doer, vertexFormat VertexFormat, uniformFormat UniformFormat, vertexShader, fragmentShader string) (*Shader, error) {
|
||||
shader := &Shader{
|
||||
parent: parent,
|
||||
program: binder{
|
||||
restoreLoc: gl.CURRENT_PROGRAM,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.UseProgram(obj)
|
||||
},
|
||||
},
|
||||
vertexFormat: vertexFormat,
|
||||
uniformFormat: uniformFormat,
|
||||
uniforms: make(map[Attr]int32),
|
||||
|
@ -86,31 +91,31 @@ func NewShader(parent Doer, vertexFormat VertexFormat, uniformFormat UniformForm
|
|||
|
||||
// shader program
|
||||
{
|
||||
shader.program = gl.CreateProgram()
|
||||
gl.AttachShader(shader.program, vshader)
|
||||
gl.AttachShader(shader.program, fshader)
|
||||
gl.LinkProgram(shader.program)
|
||||
shader.program.obj = gl.CreateProgram()
|
||||
gl.AttachShader(shader.program.obj, vshader)
|
||||
gl.AttachShader(shader.program.obj, fshader)
|
||||
gl.LinkProgram(shader.program.obj)
|
||||
|
||||
var (
|
||||
success int32
|
||||
infoLog = make([]byte, 512)
|
||||
)
|
||||
gl.GetProgramiv(shader.program, gl.LINK_STATUS, &success)
|
||||
gl.GetProgramiv(shader.program.obj, gl.LINK_STATUS, &success)
|
||||
if success == 0 {
|
||||
gl.GetProgramInfoLog(shader.program, int32(len(infoLog)), nil, &infoLog[0])
|
||||
gl.GetProgramInfoLog(shader.program.obj, int32(len(infoLog)), nil, &infoLog[0])
|
||||
return fmt.Errorf("error linking shader program: %s", string(infoLog))
|
||||
}
|
||||
}
|
||||
|
||||
// uniforms
|
||||
for uname, utype := range uniformFormat {
|
||||
ulocation := gl.GetUniformLocation(shader.program, gl.Str(uname+"\x00"))
|
||||
ulocation := gl.GetUniformLocation(shader.program.obj, gl.Str(uname+"\x00"))
|
||||
if ulocation == -1 {
|
||||
gl.DeleteProgram(shader.program)
|
||||
gl.DeleteProgram(shader.program.obj)
|
||||
return fmt.Errorf("shader does not contain uniform '%s'", uname)
|
||||
}
|
||||
if _, ok := shader.uniforms[utype]; ok {
|
||||
gl.DeleteProgram(shader.program)
|
||||
gl.DeleteProgram(shader.program.obj)
|
||||
return fmt.Errorf("failed to create shader: invalid uniform format: duplicate uniform attribute")
|
||||
}
|
||||
shader.uniforms[utype] = ulocation
|
||||
|
@ -130,14 +135,14 @@ func NewShader(parent Doer, vertexFormat VertexFormat, uniformFormat UniformForm
|
|||
func (s *Shader) Delete() {
|
||||
s.parent.Do(func(ctx Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.DeleteProgram(s.program)
|
||||
gl.DeleteProgram(s.program.obj)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns an OpenGL identifier of a shader program.
|
||||
func (s *Shader) ID() uint32 {
|
||||
return s.program
|
||||
return s.program.obj
|
||||
}
|
||||
|
||||
// VertexFormat returns the vertex attribute format of this shader. Do not change it.
|
||||
|
@ -150,245 +155,94 @@ func (s *Shader) UniformFormat() UniformFormat {
|
|||
return s.uniformFormat
|
||||
}
|
||||
|
||||
// SetUniformInt sets the value of an uniform attribute Attr{Purpose: purpose, Type: Int}.
|
||||
// SetUniformAttr sets the value of a uniform attribute of a shader.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformInt(purpose AttrPurpose, value int32) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Int}
|
||||
// If the attribute does not exist, this method returns false.
|
||||
//
|
||||
// Supplied value must correspond to the type of the attribute. Correct types are these (right-hand is the type of the value):
|
||||
// Attr{Type: Int}: int32
|
||||
// Attr{Type: Float}: float32
|
||||
// Attr{Type: Vec2}: mgl32.Vec2
|
||||
// Attr{Type: Vec3}: mgl32.Vec3
|
||||
// Attr{Type: Vec4}: mgl32.Vec4
|
||||
// Attr{Type: Mat2}: mgl32.Mat2
|
||||
// Attr{Type: Mat23}: mgl32.Mat2x3
|
||||
// Attr{Type: Mat24}: mgl32.Mat2x4
|
||||
// Attr{Type: Mat3}: mgl32.Mat3
|
||||
// Attr{Type: Mat32}: mgl32.Mat3x2
|
||||
// Attr{Type: Mat34}: mgl32.Mat3x4
|
||||
// Attr{Type: Mat4}: mgl32.Mat4
|
||||
// Attr{Type: Mat42}: mgl32.Mat4x2
|
||||
// Attr{Type: Mat43}: mgl32.Mat4x3
|
||||
// No other types are supported.
|
||||
func (s *Shader) SetUniformAttr(attr Attr, value interface{}) (ok bool) {
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.Uniform1i(s.uniforms[attr], value)
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformFloat sets the value of an uniform attribute Attr{Purpose: purpose, Type: Float}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformFloat(purpose AttrPurpose, value float32) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Float}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.Uniform1f(s.uniforms[attr], value)
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
defer s.program.bind().restore()
|
||||
|
||||
// SetUniformVec2 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Vec2}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformVec2(purpose AttrPurpose, value mgl32.Vec2) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Vec2}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.Uniform2f(s.uniforms[attr], value[0], value[1])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformVec3 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Vec3}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformVec3(purpose AttrPurpose, value mgl32.Vec3) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Vec3}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.Uniform3f(s.uniforms[attr], value[0], value[1], value[2])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformVec4 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Vec4}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformVec4(purpose AttrPurpose, value mgl32.Vec4) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Vec4}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.Uniform4f(s.uniforms[attr], value[0], value[1], value[2], value[3])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat2 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat2}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat2(purpose AttrPurpose, value mgl32.Mat2) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat2}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
switch attr.Type {
|
||||
case Int:
|
||||
value := value.(int32)
|
||||
gl.Uniform1iv(s.uniforms[attr], 1, &value)
|
||||
case Float:
|
||||
value := value.(float32)
|
||||
gl.Uniform1fv(s.uniforms[attr], 1, &value)
|
||||
case Vec2:
|
||||
value := value.(mgl32.Vec2)
|
||||
gl.Uniform2fv(s.uniforms[attr], 1, &value[0])
|
||||
case Vec3:
|
||||
value := value.(mgl32.Vec3)
|
||||
gl.Uniform3fv(s.uniforms[attr], 1, &value[0])
|
||||
case Vec4:
|
||||
value := value.(mgl32.Vec4)
|
||||
gl.Uniform4fv(s.uniforms[attr], 1, &value[0])
|
||||
case Mat2:
|
||||
value := value.(mgl32.Mat2)
|
||||
gl.UniformMatrix2fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat23 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat23}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat23(purpose AttrPurpose, value mgl32.Mat2x3) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat23}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat23:
|
||||
value := value.(mgl32.Mat2x3)
|
||||
gl.UniformMatrix2x3fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat24 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat24}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat24(purpose AttrPurpose, value mgl32.Mat2x4) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat24}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat24:
|
||||
value := value.(mgl32.Mat2x4)
|
||||
gl.UniformMatrix2x4fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat3 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat3}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat3(purpose AttrPurpose, value mgl32.Mat3) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat3}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat3:
|
||||
value := value.(mgl32.Mat3)
|
||||
gl.UniformMatrix3fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat32 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat32}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat32(purpose AttrPurpose, value mgl32.Mat3x2) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat32}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat32:
|
||||
value := value.(mgl32.Mat3x2)
|
||||
gl.UniformMatrix3x2fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat34 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat34}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat34(purpose AttrPurpose, value mgl32.Mat3x4) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat34}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat34:
|
||||
value := value.(mgl32.Mat3x4)
|
||||
gl.UniformMatrix3x4fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat4 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat4}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat4(purpose AttrPurpose, value mgl32.Mat4) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat4}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat4:
|
||||
value := value.(mgl32.Mat4)
|
||||
gl.UniformMatrix4fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat42 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat42}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat42(purpose AttrPurpose, value mgl32.Mat4x2) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat42}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat42:
|
||||
value := value.(mgl32.Mat4x2)
|
||||
gl.UniformMatrix4x2fv(s.uniforms[attr], 1, false, &value[0])
|
||||
})
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// SetUniformMat43 sets the value of an uniform attribute Attr{Purpose: purpose, Type: Mat43}.
|
||||
//
|
||||
// Returns false if the attribute does not exist.
|
||||
func (s *Shader) SetUniformMat43(purpose AttrPurpose, value mgl32.Mat4x3) (ok bool) {
|
||||
attr := Attr{Purpose: purpose, Type: Mat43}
|
||||
if _, ok := s.uniforms[attr]; !ok {
|
||||
return false
|
||||
}
|
||||
s.Do(func(Context) {
|
||||
DoNoBlock(func() {
|
||||
case Mat43:
|
||||
value := value.(mgl32.Mat4x3)
|
||||
gl.UniformMatrix4x3fv(s.uniforms[attr], 1, false, &value[0])
|
||||
default:
|
||||
panic("set uniform attr: invalid attribute type")
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Do stars using a shader, executes sub, and stops using it.
|
||||
func (s *Shader) Do(sub func(Context)) {
|
||||
s.parent.Do(func(ctx Context) {
|
||||
if s.enabled {
|
||||
sub(ctx.WithShader(s))
|
||||
return
|
||||
}
|
||||
DoNoBlock(func() {
|
||||
gl.UseProgram(s.program)
|
||||
s.program.bind()
|
||||
})
|
||||
s.enabled = true
|
||||
sub(ctx.WithShader(s))
|
||||
s.enabled = false
|
||||
DoNoBlock(func() {
|
||||
gl.UseProgram(0)
|
||||
s.program.restore()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ import "github.com/go-gl/gl/v3.3-core/gl"
|
|||
|
||||
// Texture is an OpenGL texture.
|
||||
type Texture struct {
|
||||
enabled bool
|
||||
parent Doer
|
||||
tex uint32
|
||||
tex binder
|
||||
width, height int
|
||||
}
|
||||
|
||||
|
@ -15,14 +14,20 @@ type Texture struct {
|
|||
func NewTexture(parent Doer, width, height int, pixels []uint8) (*Texture, error) {
|
||||
texture := &Texture{
|
||||
parent: parent,
|
||||
tex: binder{
|
||||
restoreLoc: gl.TEXTURE_BINDING_2D,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindTexture(gl.TEXTURE_2D, obj)
|
||||
},
|
||||
},
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
|
||||
parent.Do(func(ctx Context) {
|
||||
Do(func() {
|
||||
gl.GenTextures(1, &texture.tex)
|
||||
gl.BindTexture(gl.TEXTURE_2D, texture.tex)
|
||||
gl.GenTextures(1, &texture.tex.obj)
|
||||
defer texture.tex.bind().restore()
|
||||
|
||||
gl.TexImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
|
@ -37,8 +42,6 @@ func NewTexture(parent Doer, width, height int, pixels []uint8) (*Texture, error
|
|||
)
|
||||
|
||||
gl.GenerateMipmap(gl.TEXTURE_2D)
|
||||
|
||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -49,14 +52,14 @@ func NewTexture(parent Doer, width, height int, pixels []uint8) (*Texture, error
|
|||
func (t *Texture) Delete() {
|
||||
t.parent.Do(func(ctx Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.DeleteTextures(1, &t.tex)
|
||||
gl.DeleteTextures(1, &t.tex.obj)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns an OpenGL identifier of a texture.
|
||||
func (t *Texture) ID() uint32 {
|
||||
return t.tex
|
||||
return t.tex.obj
|
||||
}
|
||||
|
||||
// Width returns the width of a texture in pixels.
|
||||
|
@ -72,18 +75,12 @@ func (t *Texture) Height() int {
|
|||
// Do bind a texture, executes sub, and unbinds the texture.
|
||||
func (t *Texture) Do(sub func(Context)) {
|
||||
t.parent.Do(func(ctx Context) {
|
||||
if t.enabled {
|
||||
sub(ctx)
|
||||
return
|
||||
}
|
||||
DoNoBlock(func() {
|
||||
gl.BindTexture(gl.TEXTURE_2D, t.tex)
|
||||
t.tex.bind()
|
||||
})
|
||||
t.enabled = true
|
||||
sub(ctx)
|
||||
t.enabled = false
|
||||
DoNoBlock(func() {
|
||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||
t.tex.restore()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package pixelgl
|
||||
|
||||
import "github.com/go-gl/gl/v3.3-core/gl"
|
||||
|
||||
type binder struct {
|
||||
restoreLoc uint32
|
||||
bindFunc func(uint32)
|
||||
|
||||
obj uint32
|
||||
|
||||
prev []uint32
|
||||
}
|
||||
|
||||
func (b *binder) bind() *binder {
|
||||
var prev int32
|
||||
gl.GetIntegerv(b.restoreLoc, &prev)
|
||||
b.prev = append(b.prev, uint32(prev))
|
||||
|
||||
b.bindFunc(b.obj)
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *binder) restore() *binder {
|
||||
b.bindFunc(b.prev[len(b.prev)-1])
|
||||
b.prev = b.prev[:len(b.prev)-1]
|
||||
return b
|
||||
}
|
|
@ -43,9 +43,8 @@ const (
|
|||
// 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 {
|
||||
enabled bool
|
||||
parent Doer
|
||||
vao, vbo, ebo uint32
|
||||
vao, vbo, ebo binder
|
||||
vertexNum, indexNum int
|
||||
format VertexFormat
|
||||
usage VertexUsage
|
||||
|
@ -60,9 +59,27 @@ type VertexArray struct {
|
|||
func NewVertexArray(parent Doer, format VertexFormat, usage VertexUsage, vertexNum int, indices []int) (*VertexArray, error) {
|
||||
va := &VertexArray{
|
||||
parent: parent,
|
||||
vao: binder{
|
||||
restoreLoc: gl.VERTEX_ARRAY_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindVertexArray(obj)
|
||||
},
|
||||
},
|
||||
vbo: binder{
|
||||
restoreLoc: gl.ARRAY_BUFFER_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, obj)
|
||||
},
|
||||
},
|
||||
ebo: binder{
|
||||
restoreLoc: gl.ELEMENT_ARRAY_BUFFER_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, obj)
|
||||
},
|
||||
},
|
||||
vertexNum: vertexNum,
|
||||
format: format,
|
||||
usage: usage,
|
||||
vertexNum: vertexNum,
|
||||
stride: format.Size(),
|
||||
attrs: make(map[Attr]int),
|
||||
}
|
||||
|
@ -83,16 +100,17 @@ func NewVertexArray(parent Doer, format VertexFormat, usage VertexUsage, vertexN
|
|||
|
||||
parent.Do(func(ctx Context) {
|
||||
Do(func() {
|
||||
gl.GenVertexArrays(1, &va.vao)
|
||||
gl.BindVertexArray(va.vao)
|
||||
gl.GenVertexArrays(1, &va.vao.obj)
|
||||
va.vao.bind()
|
||||
|
||||
gl.GenBuffers(1, &va.vbo)
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||
gl.GenBuffers(1, &va.vbo.obj)
|
||||
defer va.vbo.bind().restore()
|
||||
|
||||
emptyData := make([]byte, vertexNum*va.stride)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), uint32(usage))
|
||||
|
||||
gl.GenBuffers(1, &va.ebo)
|
||||
gl.GenBuffers(1, &va.ebo.obj)
|
||||
defer va.ebo.bind().restore()
|
||||
|
||||
offset := 0
|
||||
for i, attr := range format {
|
||||
|
@ -120,12 +138,7 @@ func NewVertexArray(parent Doer, format VertexFormat, usage VertexUsage, vertexN
|
|||
offset += attr.Type.Size()
|
||||
}
|
||||
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, va.ebo) // need to bind EBO, so that VAO registers it
|
||||
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
gl.BindVertexArray(0)
|
||||
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
|
||||
va.vao.restore()
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -138,15 +151,15 @@ func NewVertexArray(parent Doer, format VertexFormat, usage VertexUsage, vertexN
|
|||
func (va *VertexArray) Delete() {
|
||||
va.parent.Do(func(ctx Context) {
|
||||
DoNoBlock(func() {
|
||||
gl.DeleteVertexArrays(1, &va.vao)
|
||||
gl.DeleteBuffers(1, &va.vbo)
|
||||
gl.DeleteVertexArrays(1, &va.vao.obj)
|
||||
gl.DeleteBuffers(1, &va.vbo.obj)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns an OpenGL identifier of a vertex array.
|
||||
func (va *VertexArray) ID() uint32 {
|
||||
return va.vao
|
||||
return va.vao.obj
|
||||
}
|
||||
|
||||
// VertexNum returns the number of vertices in a vertex array.
|
||||
|
@ -184,9 +197,8 @@ func (va *VertexArray) SetIndices(indices []int) {
|
|||
}
|
||||
va.indexNum = len(indices32)
|
||||
DoNoBlock(func() {
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, va.ebo)
|
||||
defer va.ebo.bind().restore()
|
||||
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, 4*len(indices32), gl.Ptr(indices32), uint32(va.usage))
|
||||
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -195,7 +207,7 @@ func (va *VertexArray) SetIndices(indices []int) {
|
|||
// If the vertex attribute does not exist, this method returns false. If the vertex is out of range,
|
||||
// this method panics.
|
||||
//
|
||||
// Supplied value must correspond to the type of the attribute. Correct types are these (righ-hand is the type of value):
|
||||
// Supplied value must correspond to the type of the attribute. Correct types are these (righ-hand is the type of the value):
|
||||
// Attr{Type: Float}: float32
|
||||
// Attr{Type: Vec2}: mgl32.Vec2
|
||||
// Attr{Type: Vec3}: mgl32.Vec3
|
||||
|
@ -211,7 +223,7 @@ func (va *VertexArray) SetVertexAttr(vertex int, attr Attr, value interface{}) (
|
|||
}
|
||||
|
||||
DoNoBlock(func() {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||
defer va.vbo.bind().restore()
|
||||
|
||||
offset := va.stride*vertex + va.attrs[attr]
|
||||
|
||||
|
@ -228,9 +240,9 @@ func (va *VertexArray) SetVertexAttr(vertex int, attr Attr, value interface{}) (
|
|||
case Vec4:
|
||||
value := value.(mgl32.Vec4)
|
||||
gl.BufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&value))
|
||||
default:
|
||||
panic("set vertex attr: invalid attribute type")
|
||||
}
|
||||
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
})
|
||||
|
||||
return true
|
||||
|
@ -251,8 +263,8 @@ func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok
|
|||
return nil, false
|
||||
}
|
||||
|
||||
DoNoBlock(func() {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, va.vbo)
|
||||
Do(func() {
|
||||
defer va.vbo.bind().restore()
|
||||
|
||||
offset := va.stride*vertex + va.attrs[attr]
|
||||
|
||||
|
@ -274,8 +286,6 @@ func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok
|
|||
gl.GetBufferSubData(gl.ARRAY_BUFFER, offset, attr.Type.Size(), unsafe.Pointer(&data))
|
||||
value = data
|
||||
}
|
||||
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
|
||||
})
|
||||
|
||||
return value, true
|
||||
|
@ -284,19 +294,13 @@ func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok
|
|||
// 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) {
|
||||
if va.enabled {
|
||||
sub(ctx)
|
||||
return
|
||||
}
|
||||
DoNoBlock(func() {
|
||||
gl.BindVertexArray(va.vao)
|
||||
va.vao.bind()
|
||||
})
|
||||
va.enabled = true
|
||||
sub(ctx)
|
||||
va.enabled = false
|
||||
DoNoBlock(func() {
|
||||
gl.DrawElements(gl.TRIANGLES, int32(va.indexNum), gl.UNSIGNED_INT, gl.PtrOffset(0))
|
||||
gl.BindVertexArray(0)
|
||||
va.vao.restore()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue