Use dep to vendor things
This commit is contained in:
21
vendor/github.com/faiface/glhf/LICENSE
generated
vendored
Normal file
21
vendor/github.com/faiface/glhf/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Michal Štrba
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
191
vendor/github.com/faiface/glhf/README.md
generated
vendored
Normal file
191
vendor/github.com/faiface/glhf/README.md
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
# glhf [](http://godoc.org/github.com/faiface/glhf) [](https://goreportcard.com/report/github.com/faiface/glhf)
|
||||
|
||||
open**GL** **H**ave **F**un - A Go package that makes life with OpenGL enjoyable.
|
||||
|
||||
```
|
||||
go get github.com/faiface/glhf
|
||||
```
|
||||
|
||||
## Main features
|
||||
|
||||
- Garbage collected OpenGL objects
|
||||
- Dynamically sized vertex slices (vertex arrays are boring)
|
||||
- Textures, Shaders, Frames (reasonably managed framebuffers)
|
||||
- Always possible to use standard OpenGL with `glhf`
|
||||
|
||||
## Motivation
|
||||
|
||||
OpenGL is verbose, it's usage patterns are repetitive and it's manual memory management doesn't fit
|
||||
Go's design. When making a game development library, it's usually desirable to create some
|
||||
higher-level abstractions around OpenGL. This library is a take on that.
|
||||
|
||||
## Contribute!
|
||||
|
||||
The library is young and many features are still missing. If you find a bug, have a proposal or a
|
||||
feature request, _do an issue_!. If you know how to implement something that's missing, _do a pull
|
||||
request_.
|
||||
|
||||
## Code
|
||||
|
||||
The following are parts of the demo program, which can be found in the [examples](https://github.com/faiface/glhf/tree/master/examples/demo).
|
||||
|
||||
```go
|
||||
// ... GLFW window creation and stuff ...
|
||||
|
||||
// vertex shader source
|
||||
var vertexShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec2 position;
|
||||
in vec2 texture;
|
||||
|
||||
out vec2 Texture;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
Texture = texture;
|
||||
}
|
||||
`
|
||||
|
||||
// fragment shader source
|
||||
var fragmentShader = `
|
||||
#version 330 core
|
||||
|
||||
in vec2 Texture;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main() {
|
||||
color = texture(tex, Texture);
|
||||
}
|
||||
`
|
||||
|
||||
var (
|
||||
// Here we define a vertex format of our vertex slice. It's actually a basic slice
|
||||
// literal.
|
||||
//
|
||||
// The vertex format consists of names and types of the attributes. The name is the
|
||||
// name that the attribute is referenced by inside a shader.
|
||||
vertexFormat = glhf.AttrFormat{
|
||||
{Name: "position", Type: glhf.Vec2},
|
||||
{Name: "texture", Type: glhf.Vec2},
|
||||
}
|
||||
|
||||
// Here we declare some variables for later use.
|
||||
shader *glhf.Shader
|
||||
texture *glhf.Texture
|
||||
slice *glhf.VertexSlice
|
||||
)
|
||||
|
||||
// Here we load an image from a file. The loadImage function is not within the library, it
|
||||
// just loads and returns a image.NRGBA.
|
||||
gopherImage, err := loadImage("celebrate.png")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Every OpenGL call needs to be done inside the main thread.
|
||||
mainthread.Call(func() {
|
||||
var err error
|
||||
|
||||
// Here we create a shader. The second argument is the format of the uniform
|
||||
// attributes. Since our shader has no uniform attributes, the format is empty.
|
||||
shader, err = glhf.NewShader(vertexFormat, glhf.AttrFormat{}, vertexShader, fragmentShader)
|
||||
|
||||
// If the shader compilation did not go successfully, an error with a full
|
||||
// description is returned.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// We create a texture from the loaded image.
|
||||
texture = glhf.NewTexture(
|
||||
gopherImage.Bounds().Dx(),
|
||||
gopherImage.Bounds().Dy(),
|
||||
true,
|
||||
gopherImage.Pix,
|
||||
)
|
||||
|
||||
// And finally, we make a vertex slice, which is basically a dynamically sized
|
||||
// vertex array. The length of the slice is 6 and the capacity is the same.
|
||||
//
|
||||
// The slice inherits the vertex format of the supplied shader. Also, it should
|
||||
// only be used with that shader.
|
||||
slice = glhf.MakeVertexSlice(shader, 6, 6)
|
||||
|
||||
// Before we use a slice, we need to Begin it. The same holds for all objects in
|
||||
// GLHF.
|
||||
slice.Begin()
|
||||
|
||||
// We assign data to the vertex slice. The values are in the order as in the vertex
|
||||
// format of the slice (shader). Each two floats correspond to an attribute of type
|
||||
// glhf.Vec2.
|
||||
slice.SetVertexData([]float32{
|
||||
-1, -1, 0, 1,
|
||||
+1, -1, 1, 1,
|
||||
+1, +1, 1, 0,
|
||||
|
||||
-1, -1, 0, 1,
|
||||
+1, +1, 1, 0,
|
||||
-1, +1, 0, 0,
|
||||
})
|
||||
|
||||
// When we're done with the slice, we End it.
|
||||
slice.End()
|
||||
})
|
||||
|
||||
shouldQuit := false
|
||||
for !shouldQuit {
|
||||
mainthread.Call(func() {
|
||||
// ... GLFW stuff ...
|
||||
|
||||
// Clear the window.
|
||||
glhf.Clear(1, 1, 1, 1)
|
||||
|
||||
// Here we Begin/End all necessary objects and finally draw the vertex
|
||||
// slice.
|
||||
shader.Begin()
|
||||
texture.Begin()
|
||||
slice.Begin()
|
||||
slice.Draw()
|
||||
slice.End()
|
||||
texture.End()
|
||||
shader.End()
|
||||
|
||||
// ... GLFW stuff ...
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## FAQ
|
||||
|
||||
### Which version of OpenGL does GLHF use?
|
||||
|
||||
It uses OpenGL 3.3 and uses
|
||||
[`github.com/go-gl/gl/v3.3-core/gl`](https://github.com/go-gl/gl/tree/master/v3.3-core/gl).
|
||||
|
||||
### Why do I have to use `github.com/faiface/mainthread` package with GLHF?
|
||||
|
||||
First of all, OpenGL has to be done from one thread and many operating systems require, that the one
|
||||
thread will be the main thread of your application.
|
||||
|
||||
But why that specific package? GLHF uses the `mainthread` package to do the garbage collection of
|
||||
OpenGL objects, which is super convenient. So in order for it to work correctly, you have to
|
||||
initialize the `mainthread` package through `mainthread.Run`. However, once you call this function
|
||||
there is no way to run functions on the main thread, except for through the `mainthread` package.
|
||||
|
||||
### Why is the important XY feature not included?
|
||||
|
||||
I probably didn't need it yet. If you want that features, create an issue or implement it and do a
|
||||
pull request.
|
||||
|
||||
### Does GLHF create windows for me?
|
||||
|
||||
No. You have to use another library for windowing, e.g.
|
||||
[github.com/go-gl/glfw/v3.2/glfw](https://github.com/go-gl/glfw/tree/master/v3.2/glfw).
|
||||
|
||||
### Why no tests?
|
||||
|
||||
If you find a way to automatically test OpenGL, I may add tests.
|
80
vendor/github.com/faiface/glhf/attr.go
generated
vendored
Normal file
80
vendor/github.com/faiface/glhf/attr.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package glhf
|
||||
|
||||
// AttrFormat defines names and types of OpenGL attributes (vertex format, uniform format, etc.).
|
||||
//
|
||||
// Example:
|
||||
// AttrFormat{{"position", Vec2}, {"color", Vec4}, {"texCoord": Vec2}}
|
||||
type AttrFormat []Attr
|
||||
|
||||
// Size returns the total size of all attributes of the AttrFormat.
|
||||
func (af AttrFormat) Size() int {
|
||||
total := 0
|
||||
for _, attr := range af {
|
||||
total += attr.Type.Size()
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// Attr represents an arbitrary OpenGL attribute, such as a vertex attribute or a shader
|
||||
// uniform attribute.
|
||||
type Attr struct {
|
||||
Name string
|
||||
Type AttrType
|
||||
}
|
||||
|
||||
// AttrType represents the type of an OpenGL attribute.
|
||||
type AttrType int
|
||||
|
||||
// List of all possible attribute types.
|
||||
const (
|
||||
Int AttrType = iota
|
||||
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 {
|
||||
switch at {
|
||||
case Int:
|
||||
return 4
|
||||
case Float:
|
||||
return 4
|
||||
case Vec2:
|
||||
return 2 * 4
|
||||
case Vec3:
|
||||
return 3 * 4
|
||||
case Vec4:
|
||||
return 4 * 4
|
||||
case Mat2:
|
||||
return 2 * 2 * 4
|
||||
case Mat23:
|
||||
return 2 * 3 * 4
|
||||
case Mat24:
|
||||
return 2 * 4 * 4
|
||||
case Mat3:
|
||||
return 3 * 3 * 4
|
||||
case Mat32:
|
||||
return 3 * 2 * 4
|
||||
case Mat34:
|
||||
return 3 * 4 * 4
|
||||
case Mat4:
|
||||
return 4 * 4 * 4
|
||||
case Mat42:
|
||||
return 4 * 2 * 4
|
||||
case Mat43:
|
||||
return 4 * 3 * 4
|
||||
default:
|
||||
panic("size of vertex attribute type: invalid type")
|
||||
}
|
||||
}
|
7
vendor/github.com/faiface/glhf/doc.go
generated
vendored
Normal file
7
vendor/github.com/faiface/glhf/doc.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
// Package glhf provides abstractions around the basic OpenGL primitives and operations.
|
||||
//
|
||||
// All calls should be done from the main thread using "github.com/faiface/mainthread" package.
|
||||
//
|
||||
// This package deliberately does not handle nor report trivial OpenGL errors, it's up to you to
|
||||
// cause none. It does of course report errors like shader compilation error and such.
|
||||
package glhf
|
108
vendor/github.com/faiface/glhf/frame.go
generated
vendored
Normal file
108
vendor/github.com/faiface/glhf/frame.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package glhf
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
)
|
||||
|
||||
// Frame is a fixed resolution texture that you can draw on.
|
||||
type Frame struct {
|
||||
fb, rf, df binder // framebuffer, read framebuffer, draw framebuffer
|
||||
tex *Texture
|
||||
}
|
||||
|
||||
// NewFrame creates a new fully transparent Frame with given dimensions in pixels.
|
||||
func NewFrame(width, height int, smooth bool) *Frame {
|
||||
f := &Frame{
|
||||
fb: binder{
|
||||
restoreLoc: gl.FRAMEBUFFER_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindFramebuffer(gl.FRAMEBUFFER, obj)
|
||||
},
|
||||
},
|
||||
rf: binder{
|
||||
restoreLoc: gl.READ_FRAMEBUFFER_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindFramebuffer(gl.READ_FRAMEBUFFER, obj)
|
||||
},
|
||||
},
|
||||
df: binder{
|
||||
restoreLoc: gl.DRAW_FRAMEBUFFER_BINDING,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindFramebuffer(gl.DRAW_FRAMEBUFFER, obj)
|
||||
},
|
||||
},
|
||||
tex: NewTexture(width, height, smooth, make([]uint8, width*height*4)),
|
||||
}
|
||||
|
||||
gl.GenFramebuffers(1, &f.fb.obj)
|
||||
|
||||
f.fb.bind()
|
||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, f.tex.tex.obj, 0)
|
||||
f.fb.restore()
|
||||
|
||||
runtime.SetFinalizer(f, (*Frame).delete)
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *Frame) delete() {
|
||||
mainthread.CallNonBlock(func() {
|
||||
gl.DeleteFramebuffers(1, &f.fb.obj)
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns the OpenGL framebuffer ID of this Frame.
|
||||
func (f *Frame) ID() uint32 {
|
||||
return f.fb.obj
|
||||
}
|
||||
|
||||
// Begin binds the Frame. All draw operations will target this Frame until End is called.
|
||||
func (f *Frame) Begin() {
|
||||
f.fb.bind()
|
||||
}
|
||||
|
||||
// End unbinds the Frame. All draw operations will go to whatever was bound before this Frame.
|
||||
func (f *Frame) End() {
|
||||
f.fb.restore()
|
||||
}
|
||||
|
||||
// Blit copies rectangle (sx0, sy0, sx1, sy1) in this Frame onto rectangle (dx0, dy0, dx1, dy1) in
|
||||
// dst Frame.
|
||||
//
|
||||
// If the dst Frame is nil, the destination will be the framebuffer 0, which is the screen.
|
||||
//
|
||||
// If the sizes of the rectangles don't match, the source will be stretched to fit the destination
|
||||
// rectangle. The stretch will be either smooth or pixely according to the source Frame's
|
||||
// smoothness.
|
||||
func (f *Frame) Blit(dst *Frame, sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int) {
|
||||
f.rf.obj = f.fb.obj
|
||||
if dst != nil {
|
||||
f.df.obj = dst.fb.obj
|
||||
} else {
|
||||
f.df.obj = 0
|
||||
}
|
||||
f.rf.bind()
|
||||
f.df.bind()
|
||||
|
||||
filter := gl.NEAREST
|
||||
if f.tex.smooth {
|
||||
filter = gl.LINEAR
|
||||
}
|
||||
|
||||
gl.BlitFramebuffer(
|
||||
int32(sx0), int32(sy0), int32(sx1), int32(sy1),
|
||||
int32(dx0), int32(dy0), int32(dx1), int32(dy1),
|
||||
gl.COLOR_BUFFER_BIT, uint32(filter),
|
||||
)
|
||||
|
||||
f.rf.restore()
|
||||
f.df.restore()
|
||||
}
|
||||
|
||||
// Texture returns the Frame's underlying Texture that the Frame draws on.
|
||||
func (f *Frame) Texture() *Texture {
|
||||
return f.tex
|
||||
}
|
11
vendor/github.com/faiface/glhf/interface.go
generated
vendored
Normal file
11
vendor/github.com/faiface/glhf/interface.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package glhf
|
||||
|
||||
// BeginEnder 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, you can bind a buffer and unbind a buffer, bind a texture and unbind it, use shader
|
||||
// and unuse it, and so on.
|
||||
type BeginEnder interface {
|
||||
Begin()
|
||||
End()
|
||||
}
|
51
vendor/github.com/faiface/glhf/orphan.go
generated
vendored
Normal file
51
vendor/github.com/faiface/glhf/orphan.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
package glhf
|
||||
|
||||
import "github.com/go-gl/gl/v3.3-core/gl"
|
||||
|
||||
// Init initializes OpenGL by loading function pointers from the active OpenGL context.
|
||||
// This function must be manually run inside the main thread (using "github.com/faiface/mainthread"
|
||||
// package).
|
||||
//
|
||||
// It must be called under the presence of an active OpenGL context, e.g., always after calling
|
||||
// window.MakeContextCurrent(). Also, always call this function when switching contexts.
|
||||
func Init() {
|
||||
err := gl.Init()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gl.Enable(gl.BLEND)
|
||||
gl.Enable(gl.SCISSOR_TEST)
|
||||
gl.BlendEquation(gl.FUNC_ADD)
|
||||
}
|
||||
|
||||
// Clear clears the current framebuffer or window with the given color.
|
||||
func Clear(r, g, b, a float32) {
|
||||
gl.ClearColor(r, g, b, a)
|
||||
gl.Clear(gl.COLOR_BUFFER_BIT)
|
||||
}
|
||||
|
||||
// Bounds sets the drawing bounds in pixels. Drawing outside bounds is always discarted.
|
||||
//
|
||||
// Calling this function is equivalent to setting viewport and scissor in OpenGL.
|
||||
func Bounds(x, y, w, h int) {
|
||||
gl.Viewport(int32(x), int32(y), int32(w), int32(h))
|
||||
gl.Scissor(int32(x), int32(y), int32(w), int32(h))
|
||||
}
|
||||
|
||||
// BlendFactor represents a source or destination blend factor.
|
||||
type BlendFactor int
|
||||
|
||||
// Here's the list of all blend factors.
|
||||
const (
|
||||
One = BlendFactor(gl.ONE)
|
||||
Zero = BlendFactor(gl.ZERO)
|
||||
SrcAlpha = BlendFactor(gl.SRC_ALPHA)
|
||||
DstAlpha = BlendFactor(gl.DST_ALPHA)
|
||||
OneMinusSrcAlpha = BlendFactor(gl.ONE_MINUS_SRC_ALPHA)
|
||||
OneMinusDstAlpha = BlendFactor(gl.ONE_MINUS_DST_ALPHA)
|
||||
)
|
||||
|
||||
// BlendFunc sets the source and destination blend factor.
|
||||
func BlendFunc(src, dst BlendFactor) {
|
||||
gl.BlendFunc(uint32(src), uint32(dst))
|
||||
}
|
224
vendor/github.com/faiface/glhf/shader.go
generated
vendored
Normal file
224
vendor/github.com/faiface/glhf/shader.go
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
package glhf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
)
|
||||
|
||||
// Shader is an OpenGL shader program.
|
||||
type Shader struct {
|
||||
program binder
|
||||
vertexFmt AttrFormat
|
||||
uniformFmt AttrFormat
|
||||
uniformLoc []int32
|
||||
}
|
||||
|
||||
// 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.
|
||||
func NewShader(vertexFmt, uniformFmt AttrFormat, vertexShader, fragmentShader string) (*Shader, error) {
|
||||
shader := &Shader{
|
||||
program: binder{
|
||||
restoreLoc: gl.CURRENT_PROGRAM,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.UseProgram(obj)
|
||||
},
|
||||
},
|
||||
vertexFmt: vertexFmt,
|
||||
uniformFmt: uniformFmt,
|
||||
uniformLoc: make([]int32, len(uniformFmt)),
|
||||
}
|
||||
|
||||
var vshader, fshader uint32
|
||||
|
||||
// vertex shader
|
||||
{
|
||||
vshader = gl.CreateShader(gl.VERTEX_SHADER)
|
||||
src, free := gl.Strs(vertexShader)
|
||||
defer free()
|
||||
length := int32(len(vertexShader))
|
||||
gl.ShaderSource(vshader, 1, src, &length)
|
||||
gl.CompileShader(vshader)
|
||||
|
||||
var success int32
|
||||
gl.GetShaderiv(vshader, gl.COMPILE_STATUS, &success)
|
||||
if success == gl.FALSE {
|
||||
var logLen int32
|
||||
gl.GetShaderiv(vshader, gl.INFO_LOG_LENGTH, &logLen)
|
||||
|
||||
infoLog := make([]byte, logLen)
|
||||
gl.GetShaderInfoLog(vshader, logLen, nil, &infoLog[0])
|
||||
return nil, fmt.Errorf("error compiling vertex shader: %s", string(infoLog))
|
||||
}
|
||||
|
||||
defer gl.DeleteShader(vshader)
|
||||
}
|
||||
|
||||
// fragment shader
|
||||
{
|
||||
fshader = gl.CreateShader(gl.FRAGMENT_SHADER)
|
||||
src, free := gl.Strs(fragmentShader)
|
||||
defer free()
|
||||
length := int32(len(fragmentShader))
|
||||
gl.ShaderSource(fshader, 1, src, &length)
|
||||
gl.CompileShader(fshader)
|
||||
|
||||
var success int32
|
||||
gl.GetShaderiv(fshader, gl.COMPILE_STATUS, &success)
|
||||
if success == gl.FALSE {
|
||||
var logLen int32
|
||||
gl.GetShaderiv(fshader, gl.INFO_LOG_LENGTH, &logLen)
|
||||
|
||||
infoLog := make([]byte, logLen)
|
||||
gl.GetShaderInfoLog(fshader, logLen, nil, &infoLog[0])
|
||||
return nil, fmt.Errorf("error compiling fragment shader: %s", string(infoLog))
|
||||
}
|
||||
|
||||
defer gl.DeleteShader(fshader)
|
||||
}
|
||||
|
||||
// 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
|
||||
gl.GetProgramiv(shader.program.obj, gl.LINK_STATUS, &success)
|
||||
if success == gl.FALSE {
|
||||
var logLen int32
|
||||
gl.GetProgramiv(shader.program.obj, gl.INFO_LOG_LENGTH, &logLen)
|
||||
|
||||
infoLog := make([]byte, logLen)
|
||||
gl.GetProgramInfoLog(shader.program.obj, logLen, nil, &infoLog[0])
|
||||
return nil, fmt.Errorf("error linking shader program: %s", string(infoLog))
|
||||
}
|
||||
}
|
||||
|
||||
// uniforms
|
||||
for i, uniform := range uniformFmt {
|
||||
loc := gl.GetUniformLocation(shader.program.obj, gl.Str(uniform.Name+"\x00"))
|
||||
shader.uniformLoc[i] = loc
|
||||
}
|
||||
|
||||
runtime.SetFinalizer(shader, (*Shader).delete)
|
||||
|
||||
return shader, nil
|
||||
}
|
||||
|
||||
func (s *Shader) delete() {
|
||||
mainthread.CallNonBlock(func() {
|
||||
gl.DeleteProgram(s.program.obj)
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns the OpenGL ID of this Shader.
|
||||
func (s *Shader) ID() uint32 {
|
||||
return s.program.obj
|
||||
}
|
||||
|
||||
// VertexFormat returns the vertex attribute format of this Shader. Do not change it.
|
||||
func (s *Shader) VertexFormat() AttrFormat {
|
||||
return s.vertexFmt
|
||||
}
|
||||
|
||||
// UniformFormat returns the uniform attribute format of this Shader. Do not change it.
|
||||
func (s *Shader) UniformFormat() AttrFormat {
|
||||
return s.uniformFmt
|
||||
}
|
||||
|
||||
// SetUniformAttr sets the value of a uniform attribute of this Shader. The attribute is
|
||||
// specified by the index in the Shader's uniform format.
|
||||
//
|
||||
// If the uniform attribute does not exist in the Shader, 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.
|
||||
//
|
||||
// The Shader must be bound before calling this method.
|
||||
func (s *Shader) SetUniformAttr(uniform int, value interface{}) (ok bool) {
|
||||
if s.uniformLoc[uniform] < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
switch s.uniformFmt[uniform].Type {
|
||||
case Int:
|
||||
value := value.(int32)
|
||||
gl.Uniform1iv(s.uniformLoc[uniform], 1, &value)
|
||||
case Float:
|
||||
value := value.(float32)
|
||||
gl.Uniform1fv(s.uniformLoc[uniform], 1, &value)
|
||||
case Vec2:
|
||||
value := value.(mgl32.Vec2)
|
||||
gl.Uniform2fv(s.uniformLoc[uniform], 1, &value[0])
|
||||
case Vec3:
|
||||
value := value.(mgl32.Vec3)
|
||||
gl.Uniform3fv(s.uniformLoc[uniform], 1, &value[0])
|
||||
case Vec4:
|
||||
value := value.(mgl32.Vec4)
|
||||
gl.Uniform4fv(s.uniformLoc[uniform], 1, &value[0])
|
||||
case Mat2:
|
||||
value := value.(mgl32.Mat2)
|
||||
gl.UniformMatrix2fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat23:
|
||||
value := value.(mgl32.Mat2x3)
|
||||
gl.UniformMatrix2x3fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat24:
|
||||
value := value.(mgl32.Mat2x4)
|
||||
gl.UniformMatrix2x4fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat3:
|
||||
value := value.(mgl32.Mat3)
|
||||
gl.UniformMatrix3fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat32:
|
||||
value := value.(mgl32.Mat3x2)
|
||||
gl.UniformMatrix3x2fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat34:
|
||||
value := value.(mgl32.Mat3x4)
|
||||
gl.UniformMatrix3x4fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat4:
|
||||
value := value.(mgl32.Mat4)
|
||||
gl.UniformMatrix4fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat42:
|
||||
value := value.(mgl32.Mat4x2)
|
||||
gl.UniformMatrix4x2fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
case Mat43:
|
||||
value := value.(mgl32.Mat4x3)
|
||||
gl.UniformMatrix4x3fv(s.uniformLoc[uniform], 1, false, &value[0])
|
||||
default:
|
||||
panic("set uniform attr: invalid attribute type")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Begin binds the Shader program. This is necessary before using the Shader.
|
||||
func (s *Shader) Begin() {
|
||||
s.program.bind()
|
||||
}
|
||||
|
||||
// End unbinds the Shader program and restores the previous one.
|
||||
func (s *Shader) End() {
|
||||
s.program.restore()
|
||||
}
|
148
vendor/github.com/faiface/glhf/texture.go
generated
vendored
Normal file
148
vendor/github.com/faiface/glhf/texture.go
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
package glhf
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
)
|
||||
|
||||
// Texture is an OpenGL texture.
|
||||
type Texture struct {
|
||||
tex binder
|
||||
width, height int
|
||||
smooth bool
|
||||
}
|
||||
|
||||
// NewTexture creates a new texture with the specified width and height with some initial
|
||||
// pixel values. The pixels must be a sequence of RGBA values (one byte per component).
|
||||
func NewTexture(width, height int, smooth bool, pixels []uint8) *Texture {
|
||||
tex := &Texture{
|
||||
tex: binder{
|
||||
restoreLoc: gl.TEXTURE_BINDING_2D,
|
||||
bindFunc: func(obj uint32) {
|
||||
gl.BindTexture(gl.TEXTURE_2D, obj)
|
||||
},
|
||||
},
|
||||
width: width,
|
||||
height: height,
|
||||
}
|
||||
|
||||
gl.GenTextures(1, &tex.tex.obj)
|
||||
|
||||
tex.Begin()
|
||||
defer tex.End()
|
||||
|
||||
// initial data
|
||||
gl.TexImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RGBA,
|
||||
int32(width),
|
||||
int32(height),
|
||||
0,
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
gl.Ptr(pixels),
|
||||
)
|
||||
|
||||
borderColor := mgl32.Vec4{0, 0, 0, 0}
|
||||
gl.TexParameterfv(gl.TEXTURE_2D, gl.TEXTURE_BORDER_COLOR, &borderColor[0])
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_BORDER)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_BORDER)
|
||||
|
||||
tex.SetSmooth(smooth)
|
||||
|
||||
runtime.SetFinalizer(tex, (*Texture).delete)
|
||||
|
||||
return tex
|
||||
}
|
||||
|
||||
func (t *Texture) delete() {
|
||||
mainthread.CallNonBlock(func() {
|
||||
gl.DeleteTextures(1, &t.tex.obj)
|
||||
})
|
||||
}
|
||||
|
||||
// ID returns the OpenGL ID of this Texture.
|
||||
func (t *Texture) ID() uint32 {
|
||||
return t.tex.obj
|
||||
}
|
||||
|
||||
// Width returns the width of the Texture in pixels.
|
||||
func (t *Texture) Width() int {
|
||||
return t.width
|
||||
}
|
||||
|
||||
// Height returns the height of the Texture in pixels.
|
||||
func (t *Texture) Height() int {
|
||||
return t.height
|
||||
}
|
||||
|
||||
// SetPixels sets the content of a sub-region of the Texture. Pixels must be an RGBA byte sequence.
|
||||
func (t *Texture) SetPixels(x, y, w, h int, pixels []uint8) {
|
||||
if len(pixels) != w*h*4 {
|
||||
panic("set pixels: wrong number of pixels")
|
||||
}
|
||||
gl.TexSubImage2D(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
int32(x),
|
||||
int32(y),
|
||||
int32(w),
|
||||
int32(h),
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
gl.Ptr(pixels),
|
||||
)
|
||||
}
|
||||
|
||||
// Pixels returns the content of a sub-region of the Texture as an RGBA byte sequence.
|
||||
func (t *Texture) Pixels(x, y, w, h int) []uint8 {
|
||||
pixels := make([]uint8, t.width*t.height*4)
|
||||
gl.GetTexImage(
|
||||
gl.TEXTURE_2D,
|
||||
0,
|
||||
gl.RGBA,
|
||||
gl.UNSIGNED_BYTE,
|
||||
gl.Ptr(pixels),
|
||||
)
|
||||
subPixels := make([]uint8, w*h*4)
|
||||
for i := 0; i < h; i++ {
|
||||
row := pixels[(i+y)*t.width*4+x*4 : (i+y)*t.width*4+(x+w)*4]
|
||||
subRow := subPixels[i*w*4 : (i+1)*w*4]
|
||||
copy(subRow, row)
|
||||
}
|
||||
return subPixels
|
||||
}
|
||||
|
||||
// SetSmooth sets whether the Texture should be drawn "smoothly" or "pixely".
|
||||
//
|
||||
// It affects how the Texture is drawn when zoomed. Smooth interpolates between the neighbour
|
||||
// pixels, while pixely always chooses the nearest pixel.
|
||||
func (t *Texture) SetSmooth(smooth bool) {
|
||||
t.smooth = smooth
|
||||
if smooth {
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||
} else {
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth returns whether the Texture is set to be drawn "smooth" or "pixely".
|
||||
func (t *Texture) Smooth() bool {
|
||||
return t.smooth
|
||||
}
|
||||
|
||||
// Begin binds the Texture. This is necessary before using the Texture.
|
||||
func (t *Texture) Begin() {
|
||||
t.tex.bind()
|
||||
}
|
||||
|
||||
// End unbinds the Texture and restores the previous one.
|
||||
func (t *Texture) End() {
|
||||
t.tex.restore()
|
||||
}
|
31
vendor/github.com/faiface/glhf/util.go
generated
vendored
Normal file
31
vendor/github.com/faiface/glhf/util.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package glhf
|
||||
|
||||
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))
|
||||
|
||||
if b.prev[len(b.prev)-1] != b.obj {
|
||||
b.bindFunc(b.obj)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *binder) restore() *binder {
|
||||
if b.prev[len(b.prev)-1] != b.obj {
|
||||
b.bindFunc(b.prev[len(b.prev)-1])
|
||||
}
|
||||
b.prev = b.prev[:len(b.prev)-1]
|
||||
return b
|
||||
}
|
285
vendor/github.com/faiface/glhf/vertex.go
generated
vendored
Normal file
285
vendor/github.com/faiface/glhf/vertex.go
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
package glhf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/go-gl/gl/v3.3-core/gl"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// VertexSlice points to a portion of (or possibly whole) vertex array. It is used as a pointer,
|
||||
// contrary to Go's builtin slices. This is, so that append can be 'in-place'. That's for the good,
|
||||
// because Begin/End-ing a VertexSlice would become super confusing, if append returned a new
|
||||
// VertexSlice.
|
||||
//
|
||||
// It also implements all basic slice-like operations: appending, sub-slicing, etc.
|
||||
//
|
||||
// Note that you need to Begin a VertexSlice before getting or updating it's elements or drawing it.
|
||||
// After you're done with it, you need to End it.
|
||||
type VertexSlice struct {
|
||||
va *vertexArray
|
||||
i, j int
|
||||
}
|
||||
|
||||
// MakeVertexSlice allocates a new vertex array with specified capacity and returns a VertexSlice
|
||||
// that points to it's first len elements.
|
||||
//
|
||||
// Note, that a vertex array is specialized for a specific shader and can't be used with another
|
||||
// shader.
|
||||
func MakeVertexSlice(shader *Shader, len, cap int) *VertexSlice {
|
||||
if len > cap {
|
||||
panic("failed to make vertex slice: len > cap")
|
||||
}
|
||||
return &VertexSlice{
|
||||
va: newVertexArray(shader, cap),
|
||||
i: 0,
|
||||
j: len,
|
||||
}
|
||||
}
|
||||
|
||||
// VertexFormat returns the format of vertex attributes inside the underlying vertex array of this
|
||||
// VertexSlice.
|
||||
func (vs *VertexSlice) VertexFormat() AttrFormat {
|
||||
return vs.va.format
|
||||
}
|
||||
|
||||
// Stride returns the number of float32 elements occupied by one vertex.
|
||||
func (vs *VertexSlice) Stride() int {
|
||||
return vs.va.stride / 4
|
||||
}
|
||||
|
||||
// Len returns the length of the VertexSlice (number of vertices).
|
||||
func (vs *VertexSlice) Len() int {
|
||||
return vs.j - vs.i
|
||||
}
|
||||
|
||||
// Cap returns the capacity of an underlying vertex array.
|
||||
func (vs *VertexSlice) Cap() int {
|
||||
return vs.va.cap - vs.i
|
||||
}
|
||||
|
||||
// SetLen resizes the VertexSlice to length len.
|
||||
func (vs *VertexSlice) SetLen(len int) {
|
||||
vs.End() // vs must have been Begin-ed before calling this method
|
||||
*vs = vs.grow(len)
|
||||
vs.Begin()
|
||||
}
|
||||
|
||||
// grow returns supplied vs with length changed to len. Allocates new underlying vertex array if
|
||||
// necessary. The original content is preserved.
|
||||
func (vs VertexSlice) grow(len int) VertexSlice {
|
||||
if len <= vs.Cap() {
|
||||
// capacity sufficient
|
||||
return VertexSlice{
|
||||
va: vs.va,
|
||||
i: vs.i,
|
||||
j: vs.i + len,
|
||||
}
|
||||
}
|
||||
|
||||
// grow the capacity
|
||||
newCap := vs.Cap()
|
||||
if newCap < 1024 {
|
||||
newCap += newCap
|
||||
} else {
|
||||
newCap += newCap / 4
|
||||
}
|
||||
if newCap < len {
|
||||
newCap = len
|
||||
}
|
||||
newVs := VertexSlice{
|
||||
va: newVertexArray(vs.va.shader, newCap),
|
||||
i: 0,
|
||||
j: len,
|
||||
}
|
||||
// preserve the original content
|
||||
newVs.Begin()
|
||||
newVs.Slice(0, vs.Len()).SetVertexData(vs.VertexData())
|
||||
newVs.End()
|
||||
return newVs
|
||||
}
|
||||
|
||||
// Slice returns a sub-slice of this VertexSlice covering the range [i, j) (relative to this
|
||||
// VertexSlice).
|
||||
//
|
||||
// Note, that the returned VertexSlice shares an underlying vertex array with the original
|
||||
// VertexSlice. Modifying the contents of one modifies corresponding contents of the other.
|
||||
func (vs *VertexSlice) Slice(i, j int) *VertexSlice {
|
||||
if i < 0 || j < i || j > vs.va.cap {
|
||||
panic("failed to slice vertex slice: index out of range")
|
||||
}
|
||||
return &VertexSlice{
|
||||
va: vs.va,
|
||||
i: vs.i + i,
|
||||
j: vs.i + j,
|
||||
}
|
||||
}
|
||||
|
||||
// SetVertexData sets the contents of the VertexSlice.
|
||||
//
|
||||
// The data is a slice of float32's, where each vertex attribute occupies a certain number of
|
||||
// elements. Namely, Float occupies 1, Vec2 occupies 2, Vec3 occupies 3 and Vec4 occupies 4. The
|
||||
// attribues in the data slice must be in the same order as in the vertex format of this Vertex
|
||||
// Slice.
|
||||
//
|
||||
// If the length of vertices does not match the length of the VertexSlice, this methdo panics.
|
||||
func (vs *VertexSlice) SetVertexData(data []float32) {
|
||||
if len(data)/vs.Stride() != vs.Len() {
|
||||
fmt.Println(len(data)/vs.Stride(), vs.Len())
|
||||
panic("set vertex data: wrong length of vertices")
|
||||
}
|
||||
vs.va.setVertexData(vs.i, vs.j, data)
|
||||
}
|
||||
|
||||
// VertexData returns the contents of the VertexSlice.
|
||||
//
|
||||
// The data is in the same format as with SetVertexData.
|
||||
func (vs *VertexSlice) VertexData() []float32 {
|
||||
return vs.va.vertexData(vs.i, vs.j)
|
||||
}
|
||||
|
||||
// Draw draws the content of the VertexSlice.
|
||||
func (vs *VertexSlice) Draw() {
|
||||
vs.va.draw(vs.i, vs.j)
|
||||
}
|
||||
|
||||
// Begin binds the underlying vertex array. Calling this method is necessary before using the VertexSlice.
|
||||
func (vs *VertexSlice) Begin() {
|
||||
vs.va.begin()
|
||||
}
|
||||
|
||||
// End unbinds the underlying vertex array. Call this method when you're done with VertexSlice.
|
||||
func (vs *VertexSlice) End() {
|
||||
vs.va.end()
|
||||
}
|
||||
|
||||
type vertexArray struct {
|
||||
vao, vbo binder
|
||||
cap int
|
||||
format AttrFormat
|
||||
stride int
|
||||
offset []int
|
||||
shader *Shader
|
||||
}
|
||||
|
||||
const vertexArrayMinCap = 4
|
||||
|
||||
func newVertexArray(shader *Shader, cap int) *vertexArray {
|
||||
if cap < vertexArrayMinCap {
|
||||
cap = vertexArrayMinCap
|
||||
}
|
||||
|
||||
va := &vertexArray{
|
||||
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)
|
||||
},
|
||||
},
|
||||
cap: cap,
|
||||
format: shader.VertexFormat(),
|
||||
stride: shader.VertexFormat().Size(),
|
||||
offset: make([]int, len(shader.VertexFormat())),
|
||||
shader: shader,
|
||||
}
|
||||
|
||||
offset := 0
|
||||
for i, attr := range va.format {
|
||||
switch attr.Type {
|
||||
case Float, Vec2, Vec3, Vec4:
|
||||
default:
|
||||
panic(errors.New("failed to create vertex array: invalid attribute type"))
|
||||
}
|
||||
va.offset[i] = offset
|
||||
offset += attr.Type.Size()
|
||||
}
|
||||
|
||||
gl.GenVertexArrays(1, &va.vao.obj)
|
||||
|
||||
va.vao.bind()
|
||||
|
||||
gl.GenBuffers(1, &va.vbo.obj)
|
||||
defer va.vbo.bind().restore()
|
||||
|
||||
emptyData := make([]byte, cap*va.stride)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(emptyData), gl.Ptr(emptyData), gl.DYNAMIC_DRAW)
|
||||
|
||||
for i, attr := range va.format {
|
||||
loc := gl.GetAttribLocation(shader.program.obj, gl.Str(attr.Name+"\x00"))
|
||||
|
||||
var size int32
|
||||
switch attr.Type {
|
||||
case Float:
|
||||
size = 1
|
||||
case Vec2:
|
||||
size = 2
|
||||
case Vec3:
|
||||
size = 3
|
||||
case Vec4:
|
||||
size = 4
|
||||
}
|
||||
|
||||
gl.VertexAttribPointer(
|
||||
uint32(loc),
|
||||
size,
|
||||
gl.FLOAT,
|
||||
false,
|
||||
int32(va.stride),
|
||||
gl.PtrOffset(va.offset[i]),
|
||||
)
|
||||
gl.EnableVertexAttribArray(uint32(loc))
|
||||
}
|
||||
|
||||
va.vao.restore()
|
||||
|
||||
runtime.SetFinalizer(va, (*vertexArray).delete)
|
||||
|
||||
return va
|
||||
}
|
||||
|
||||
func (va *vertexArray) delete() {
|
||||
mainthread.CallNonBlock(func() {
|
||||
gl.DeleteVertexArrays(1, &va.vao.obj)
|
||||
gl.DeleteBuffers(1, &va.vbo.obj)
|
||||
})
|
||||
}
|
||||
|
||||
func (va *vertexArray) begin() {
|
||||
va.vao.bind()
|
||||
va.vbo.bind()
|
||||
}
|
||||
|
||||
func (va *vertexArray) end() {
|
||||
va.vbo.restore()
|
||||
va.vao.restore()
|
||||
}
|
||||
|
||||
func (va *vertexArray) draw(i, j int) {
|
||||
gl.DrawArrays(gl.TRIANGLES, int32(i), int32(i+j))
|
||||
}
|
||||
|
||||
func (va *vertexArray) setVertexData(i, j int, data []float32) {
|
||||
if j-i == 0 {
|
||||
// avoid setting 0 bytes of buffer data
|
||||
return
|
||||
}
|
||||
gl.BufferSubData(gl.ARRAY_BUFFER, i*va.stride, len(data)*4, gl.Ptr(data))
|
||||
}
|
||||
|
||||
func (va *vertexArray) vertexData(i, j int) []float32 {
|
||||
if j-i == 0 {
|
||||
// avoid getting 0 bytes of buffer data
|
||||
return nil
|
||||
}
|
||||
data := make([]float32, (j-i)*va.stride/4)
|
||||
gl.GetBufferSubData(gl.ARRAY_BUFFER, i*va.stride, len(data)*4, gl.Ptr(data))
|
||||
return data
|
||||
}
|
Reference in New Issue
Block a user