Use dep to vendor things

This commit is contained in:
2018-03-18 04:23:13 +00:00
parent d572a19352
commit 1ba64f2aa8
123 changed files with 34229 additions and 0 deletions

21
vendor/github.com/faiface/glhf/LICENSE generated vendored Normal file
View 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
View File

@@ -0,0 +1,191 @@
# glhf [![GoDoc](https://godoc.org/github.com/faiface/glhf?status.svg)](http://godoc.org/github.com/faiface/glhf) [![Report card](https://goreportcard.com/badge/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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
}