same for pixelgl
This commit is contained in:
parent
9096277914
commit
727c9bd772
|
@ -8,9 +8,9 @@ type AttrFormat map[string]AttrType
|
||||||
|
|
||||||
// Contains checks whether a format contains a specific attribute.
|
// Contains checks whether a format contains a specific attribute.
|
||||||
//
|
//
|
||||||
// It does a little more than a hard check: e.g. if you query a Vec2 attribute, but the format contains Vec3,
|
// It does a little more than a hard check: e.g. if you query a Vec2 attribute, but the format
|
||||||
// Contains returns true, because Vec2 is assignable to Vec3. Specifically, Float -> Vec2 -> Vec3 -> Vec4 (transitively).
|
// contains Vec3, Contains returns true, because Vec2 is assignable to Vec3. Specifically,
|
||||||
// This however does not work for matrices or ints.
|
// Float -> Vec2 -> Vec3 -> Vec4 (transitively). This however does not work for matrices or ints.
|
||||||
func (af AttrFormat) Contains(attr Attr) bool {
|
func (af AttrFormat) Contains(attr Attr) bool {
|
||||||
if typ, ok := af[attr.Name]; ok {
|
if typ, ok := af[attr.Name]; ok {
|
||||||
if (Float <= typ && typ <= Vec4) && (Float <= attr.Type && attr.Type <= typ) {
|
if (Float <= typ && typ <= Vec4) && (Float <= attr.Type && attr.Type <= typ) {
|
||||||
|
@ -30,7 +30,8 @@ func (af AttrFormat) Size() int {
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attr represents an arbitrary OpenGL attribute, such as a vertex attribute or a shader uniform attribute.
|
// Attr represents an arbitrary OpenGL attribute, such as a vertex attribute or a shader
|
||||||
|
// uniform attribute.
|
||||||
type Attr struct {
|
type Attr struct {
|
||||||
Name string
|
Name string
|
||||||
Type AttrType
|
Type AttrType
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Package pixelgl provides higher-level abstractions around the basic OpenGL primitives and operations.
|
// Package pixelgl provides higher-level abstractions around the basic OpenGL primitives and
|
||||||
|
// operations.
|
||||||
//
|
//
|
||||||
// This package deliberately does not handle nor report OpenGL errors, it's up to you to cause none.
|
// This package deliberately does not handle nor report OpenGL errors, it's up to you to
|
||||||
|
// cause none.
|
||||||
package pixelgl
|
package pixelgl
|
||||||
|
|
|
@ -2,15 +2,16 @@ package pixelgl
|
||||||
|
|
||||||
// Doer is an interface for manipulating OpenGL state.
|
// Doer is an interface for manipulating OpenGL state.
|
||||||
//
|
//
|
||||||
// OpenGL is a state machine. Every object can 'enter' it's state and 'leave' it's state. For example,
|
// OpenGL is a state machine. Every object can 'enter' it's state and 'leave' it's state. For
|
||||||
// you can bind a buffer and unbind a buffer, bind a texture and unbind it, use shader and unuse it, and so on.
|
// example, you can bind a buffer and unbind a buffer, bind a texture and unbind it, use shader
|
||||||
|
// and unuse it, and so on.
|
||||||
//
|
//
|
||||||
// This interface provides a clever and flexible way to do it. A typical workflow of an OpenGL object is that
|
// This interface provides a clever and flexible way to do it. A typical workflow of an OpenGL
|
||||||
// you enter (load, bind) that object's state, then do something with it, and then leave the state. That 'something'
|
// object is that you enter (load, bind) that object's state, then do something with it, and
|
||||||
// in between, let's call it sub (as in subroutine).
|
// then leave the state. That 'something' in between, let's call it sub (as in subroutine).
|
||||||
//
|
//
|
||||||
// The recommended way to implement a Doer is to wrap another Doer (vertex array wraps texture and so on), let's call
|
// The recommended way to implement a Doer is to wrap another Doer (vertex array wraps texture
|
||||||
// it parent. Then the Do method will look like this:
|
// and so on), let's call it parent. Then the Do method will look like this:
|
||||||
//
|
//
|
||||||
// func (o *MyObject) Do(sub func(Context)) {
|
// func (o *MyObject) Do(sub func(Context)) {
|
||||||
// o.parent.Do(func(ctx Context) {
|
// o.parent.Do(func(ctx Context) {
|
||||||
|
@ -20,21 +21,23 @@ package pixelgl
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// It might seem difficult to grasp this kind of recursion at first, but it's really simple. What it's basically saying
|
// It might seem difficult to grasp this kind of recursion at first, but it's really simple. What
|
||||||
// is: "Hey parent, enter your state, then let me enter mine, then I'll do whatever I'm supposed to do in the middle.
|
// it's basically saying is: "Hey parent, enter your state, then let me enter mine, then I'll
|
||||||
// After that I'll leave my state and please leave your state too parent."
|
// do whatever I'm supposed to do in the middle. After that I'll leave my state and please
|
||||||
|
// leave your state too parent."
|
||||||
//
|
//
|
||||||
// Also notice, that the functions are passing a Context around. This context contains the most important state variables.
|
// Also notice, that the functions are passing a Context around. This context contains the
|
||||||
// Usually, you just pass it as you received it. If you want to pass a changed context to your child (e.g. your a shader),
|
// most important state variables. Usually, you just pass it as you received it. If you want
|
||||||
// use ctx.With* methods.
|
// to pass a changed context to your child (e.g. your a shader), use ctx.With* methods.
|
||||||
//
|
//
|
||||||
// If possible and makes sense, Do method should be reentrant.
|
// If possible and makes sense, Do method should be reentrant.
|
||||||
type Doer interface {
|
type Doer interface {
|
||||||
Do(sub func(Context))
|
Do(sub func(Context))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context takes state from one object to another. OpenGL is a state machine, so we have to approach it like that.
|
// Context takes state from one object to another. OpenGL is a state machine, so we have
|
||||||
// However, global variables are evil, so we have Context, that transfers important OpenGL state from one object to another.
|
// to approach it like that. However, global variables are evil, so we have Context, that
|
||||||
|
// transfers important OpenGL state from one object to another.
|
||||||
//
|
//
|
||||||
// This type does *not* represent an OpenGL context in the OpenGL terminology.
|
// This type does *not* represent an OpenGL context in the OpenGL terminology.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
|
|
|
@ -17,9 +17,11 @@ type Shader struct {
|
||||||
uniforms map[string]int32
|
uniforms map[string]int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewShader creates a new shader program from the specified vertex shader and fragment shader sources.
|
// NewShader creates a new shader program from the specified vertex shader and fragment shader
|
||||||
|
// sources.
|
||||||
//
|
//
|
||||||
// Note that vertexShader and fragmentShader parameters must contain the source code, they're not filenames.
|
// Note that vertexShader and fragmentShader parameters must contain the source code, they're
|
||||||
|
// not filenames.
|
||||||
func NewShader(parent Doer, vertexFmt, uniformFmt AttrFormat, vertexShader, fragmentShader string) (*Shader, error) {
|
func NewShader(parent Doer, vertexFmt, uniformFmt AttrFormat, vertexShader, fragmentShader string) (*Shader, error) {
|
||||||
shader := &Shader{
|
shader := &Shader{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
|
@ -144,7 +146,8 @@ func (s *Shader) UniformFormat() AttrFormat {
|
||||||
//
|
//
|
||||||
// If the attribute does not exist, this method returns false.
|
// 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):
|
// 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: Int}: int32
|
||||||
// Attr{Type: Float}: float32
|
// Attr{Type: Float}: float32
|
||||||
// Attr{Type: Vec2}: mgl32.Vec2
|
// Attr{Type: Vec2}: mgl32.Vec2
|
||||||
|
|
|
@ -6,7 +6,8 @@ import (
|
||||||
"github.com/go-gl/gl/v3.3-core/gl"
|
"github.com/go-gl/gl/v3.3-core/gl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Due to the limitations of OpenGL and operating systems, all OpenGL related calls must be done from the main thread.
|
// Due to the limitations of OpenGL and operating systems, all OpenGL related calls must be
|
||||||
|
// done from the main thread.
|
||||||
|
|
||||||
var callQueue = make(chan func(), 32)
|
var callQueue = make(chan func(), 32)
|
||||||
|
|
||||||
|
@ -14,11 +15,11 @@ func init() {
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run is essentialy the "main" function of the pixelgl package.
|
// Run is essentialy the "main" function of the pixelgl package. Run this function from the
|
||||||
// Run this function from the main function (because that's guaranteed to run in the main thread).
|
// main function (because that's guaranteed to run in the main thread).
|
||||||
//
|
//
|
||||||
// This function reserves the main thread for the OpenGL stuff and runs a supplied run function in a
|
// This function reserves the main thread for the OpenGL stuff and runs a supplied run function
|
||||||
// separate goroutine.
|
// in a separate goroutine.
|
||||||
//
|
//
|
||||||
// Run returns when the provided run function finishes.
|
// Run returns when the provided run function finishes.
|
||||||
func Run(run func()) {
|
func Run(run func()) {
|
||||||
|
@ -43,8 +44,8 @@ loop:
|
||||||
// Init initializes OpenGL by loading the function pointers from the active OpenGL context.
|
// Init initializes OpenGL by loading the function pointers from the active OpenGL context.
|
||||||
// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
|
// This function must be manually run inside the main thread (Do, DoErr, DoVal, etc.).
|
||||||
//
|
//
|
||||||
// It must be called under the presence of an active OpenGL context, e.g., always after calling window.MakeContextCurrent().
|
// It must be called under the presence of an active OpenGL context, e.g., always after calling
|
||||||
// Also, always call this function when switching contexts.
|
// window.MakeContextCurrent(). Also, always call this function when switching contexts.
|
||||||
func Init() {
|
func Init() {
|
||||||
err := gl.Init()
|
err := gl.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -54,14 +55,13 @@ func Init() {
|
||||||
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoNoBlock executes a function inside the main OpenGL thread.
|
// DoNoBlock executes a function inside the main OpenGL thread. DoNoBlock does not wait until
|
||||||
// DoNoBlock does not wait until the function finishes.
|
// the function finishes.
|
||||||
func DoNoBlock(f func()) {
|
func DoNoBlock(f func()) {
|
||||||
callQueue <- f
|
callQueue <- f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do executes a function inside the main OpenGL thread.
|
// Do executes a function inside the main OpenGL thread. Do blocks until the function finishes.
|
||||||
// Do blocks until the function finishes.
|
|
||||||
//
|
//
|
||||||
// All OpenGL calls must be done in the dedicated thread.
|
// All OpenGL calls must be done in the dedicated thread.
|
||||||
func Do(f func()) {
|
func Do(f func()) {
|
||||||
|
|
|
@ -23,8 +23,9 @@ type VertexArray struct {
|
||||||
|
|
||||||
// NewVertexArray creates a new empty vertex array and wraps another Doer around it.
|
// NewVertexArray creates a new empty vertex array and wraps another Doer around it.
|
||||||
//
|
//
|
||||||
// You cannot specify vertex attributes in this constructor, only their count. Use SetVertexAttribute* methods to
|
// You cannot specify vertex attributes in this constructor, only their count. Use
|
||||||
// set the vertex attributes. Use indices to specify how you want to combine vertices into triangles.
|
// SetVertexAttribute* methods to set the vertex attributes. Use indices to specify how you
|
||||||
|
// want to combine vertices into triangles.
|
||||||
func NewVertexArray(parent Doer, format AttrFormat, numVertices int, indices []int) (*VertexArray, error) {
|
func NewVertexArray(parent Doer, format AttrFormat, numVertices int, indices []int) (*VertexArray, error) {
|
||||||
va := &VertexArray{
|
va := &VertexArray{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
|
@ -144,9 +145,9 @@ func (va *VertexArray) Draw() {
|
||||||
va.Do(func(Context) {})
|
va.Do(func(Context) {})
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIndices sets the indices of triangles to be drawn. Triangles will be formed from the vertices of the array
|
// SetIndices sets the indices of triangles to be drawn. Triangles will be formed from the
|
||||||
// as defined by these indices. The first drawn triangle is specified by the first three indices, the second by
|
// vertices of the array as defined by these indices. The first drawn triangle is specified by
|
||||||
// the fourth through sixth and so on.
|
// the first three indices, the second by the fourth through sixth and so on.
|
||||||
func (va *VertexArray) SetIndices(indices []int) {
|
func (va *VertexArray) SetIndices(indices []int) {
|
||||||
if len(indices)%3 != 0 {
|
if len(indices)%3 != 0 {
|
||||||
panic("vertex array set indices: number of indices not divisible by 3")
|
panic("vertex array set indices: number of indices not divisible by 3")
|
||||||
|
@ -180,10 +181,11 @@ func (va *VertexArray) Indices() []int {
|
||||||
|
|
||||||
// SetVertexAttr sets the value of the specified vertex attribute of the specified vertex.
|
// SetVertexAttr sets the value of the specified vertex attribute of the specified vertex.
|
||||||
//
|
//
|
||||||
// If the vertex attribute does not exist, this method returns false. If the vertex is out of range,
|
// If the vertex attribute does not exist, this method returns false. If the vertex is out of
|
||||||
// this method panics.
|
// range, this method panics.
|
||||||
//
|
//
|
||||||
// Supplied value must correspond to the type of the attribute. Correct types are these (righ-hand is the type of the 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: Float}: float32
|
||||||
// Attr{Type: Vec2}: mgl32.Vec2
|
// Attr{Type: Vec2}: mgl32.Vec2
|
||||||
// Attr{Type: Vec3}: mgl32.Vec3
|
// Attr{Type: Vec3}: mgl32.Vec3
|
||||||
|
@ -228,8 +230,8 @@ func (va *VertexArray) SetVertexAttr(vertex int, attr Attr, value interface{}) (
|
||||||
|
|
||||||
// VertexAttr returns the current value of the specified vertex attribute of the specified vertex.
|
// VertexAttr returns the current value of the specified vertex attribute of the specified vertex.
|
||||||
//
|
//
|
||||||
// If the vertex attribute does not exist, this method returns nil and false. If the vertex is out of range,
|
// If the vertex attribute does not exist, this method returns nil and false. If the vertex is
|
||||||
// this method panics.
|
// out of range, this method panics.
|
||||||
//
|
//
|
||||||
// The type of the returned value follows the same rules as with SetVertexAttr.
|
// The type of the returned value follows the same rules as with SetVertexAttr.
|
||||||
func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok bool) {
|
func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok bool) {
|
||||||
|
@ -273,7 +275,8 @@ func (va *VertexArray) VertexAttr(vertex int, attr Attr) (value interface{}, ok
|
||||||
return value, true
|
return value, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVertex sets values of the attributes specified in the supplied map. All other attributes will be set to zero.
|
// 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.
|
// Not existing attributes are silently skipped.
|
||||||
func (va *VertexArray) SetVertex(vertex int, values map[Attr]interface{}) {
|
func (va *VertexArray) SetVertex(vertex int, values map[Attr]interface{}) {
|
||||||
|
@ -361,8 +364,9 @@ func (va *VertexArray) Vertex(vertex int) (values map[Attr]interface{}) {
|
||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVertices sets values of vertex attributes of all vertices as specified in the supplied slice of maps. If the length of vertices
|
// SetVertices sets values of vertex attributes of all vertices as specified in the supplied
|
||||||
// does not match the number of vertices in the vertex array, this method panics.
|
// 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.
|
// Not existing attributes are silently skipped.
|
||||||
func (va *VertexArray) SetVertices(vertices []map[Attr]interface{}) {
|
func (va *VertexArray) SetVertices(vertices []map[Attr]interface{}) {
|
||||||
|
@ -405,7 +409,8 @@ func (va *VertexArray) SetVertices(vertices []map[Attr]interface{}) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertices returns values of vertex attributes of all vertices in a vertex array in a slice of maps.
|
// Vertices returns values of vertex attributes of all vertices in a vertex array in a slice
|
||||||
|
// of maps.
|
||||||
func (va *VertexArray) Vertices() (vertices []map[Attr]interface{}) {
|
func (va *VertexArray) Vertices() (vertices []map[Attr]interface{}) {
|
||||||
data := make([]float32, va.numVertices*va.format.Size()/4)
|
data := make([]float32, va.numVertices*va.format.Size()/4)
|
||||||
|
|
||||||
|
@ -448,7 +453,8 @@ func (va *VertexArray) Vertices() (vertices []map[Attr]interface{}) {
|
||||||
return vertices
|
return vertices
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do binds a vertex arrray and it's associated vertex buffer, executes sub, and unbinds the vertex array and it's vertex buffer.
|
// 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)) {
|
func (va *VertexArray) Do(sub func(Context)) {
|
||||||
va.parent.Do(func(ctx Context) {
|
va.parent.Do(func(ctx Context) {
|
||||||
DoNoBlock(func() {
|
DoNoBlock(func() {
|
||||||
|
|
Loading…
Reference in New Issue