mirror of
https://github.com/Kugelschieber/go-game.git
synced 2026-01-18 14:50:28 +00:00
Rendering now works! Added shaders for reference.
This commit is contained in:
1
ToDo.md
1
ToDo.md
@@ -3,3 +3,4 @@
|
|||||||
* ~~cleanup resources~~
|
* ~~cleanup resources~~
|
||||||
* more logging
|
* more logging
|
||||||
* limit FPS
|
* limit FPS
|
||||||
|
* fullscreen
|
||||||
|
|||||||
129
game.go
129
game.go
@@ -14,6 +14,31 @@ const (
|
|||||||
default_height = uint32(400)
|
default_height = uint32(400)
|
||||||
default_title = "Game"
|
default_title = "Game"
|
||||||
default_exit_on_close = true
|
default_exit_on_close = true
|
||||||
|
|
||||||
|
// constants for default 2D shader
|
||||||
|
Default_shader_2D_vertex_attrib = "vertex"
|
||||||
|
Default_shader_2D_texcoord_attrib = "texCoord"
|
||||||
|
Default_shader_2D_ortho = "o"
|
||||||
|
Default_shader_2D_model = "m"
|
||||||
|
Default_shader_2D_tex = "tex"
|
||||||
|
|
||||||
|
default_shader_2d_vertex_src = `#version 130
|
||||||
|
uniform mat3 o, m;
|
||||||
|
in vec2 vertex;
|
||||||
|
in vec2 texCoord;
|
||||||
|
out vec2 tc;
|
||||||
|
void main(){
|
||||||
|
tc = texCoord;
|
||||||
|
gl_Position = vec4(o*m*vec3(vertex, 1.0), 1.0);
|
||||||
|
}`
|
||||||
|
default_shader_2d_fragment_src = `#version 130
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
in vec2 tc;
|
||||||
|
out vec4 color;
|
||||||
|
void main(){
|
||||||
|
color = texture(tex, tc);
|
||||||
|
}`
|
||||||
)
|
)
|
||||||
|
|
||||||
// If set in RunOptions, the function will be called on window resize.
|
// If set in RunOptions, the function will be called on window resize.
|
||||||
@@ -46,6 +71,10 @@ var (
|
|||||||
clearBuffer []uint32
|
clearBuffer []uint32
|
||||||
viewportWidth int
|
viewportWidth int
|
||||||
viewportHeight int
|
viewportHeight int
|
||||||
|
|
||||||
|
// Default resources
|
||||||
|
DefaultCamera *Camera
|
||||||
|
Default2DShader *Shader
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -130,7 +159,7 @@ func Run(game Game, options *RunOptions) {
|
|||||||
|
|
||||||
// init go-game
|
// init go-game
|
||||||
log.Print("Initializing goga")
|
log.Print("Initializing goga")
|
||||||
initGoga()
|
initGoga(int(width), int(height))
|
||||||
|
|
||||||
if options != nil && options.Width > 0 && options.Height > 0 {
|
if options != nil && options.Width > 0 && options.Height > 0 {
|
||||||
SetViewport(0, 0, int32(options.Width), int32(options.Height))
|
SetViewport(0, 0, int32(options.Width), int32(options.Height))
|
||||||
@@ -176,6 +205,60 @@ func Run(game Game, options *RunOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initGoga(width, height int) {
|
||||||
|
// default camera
|
||||||
|
DefaultCamera = NewCamera(0, 0, width, height)
|
||||||
|
DefaultCamera.CalcRatio()
|
||||||
|
DefaultCamera.CalcOrtho()
|
||||||
|
|
||||||
|
// default shader
|
||||||
|
shader, err := NewShader(default_shader_2d_vertex_src, default_shader_2d_fragment_src)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Default2DShader = shader
|
||||||
|
Default2DShader.BindAttrib(Default_shader_2D_vertex_attrib)
|
||||||
|
Default2DShader.BindAttrib(Default_shader_2D_texcoord_attrib)
|
||||||
|
|
||||||
|
// settings and registration
|
||||||
|
ClearColorBuffer(true)
|
||||||
|
EnableAlphaBlending(true)
|
||||||
|
AddLoader(&PngLoader{gl.LINEAR, false})
|
||||||
|
AddSystem(NewSpriteRenderer(nil, nil, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
func cleanup() {
|
||||||
|
// cleanup resources
|
||||||
|
log.Printf("Cleaning up %v resources", len(resources))
|
||||||
|
|
||||||
|
for _, res := range resources {
|
||||||
|
if drop, ok := res.(Dropable); ok {
|
||||||
|
drop.Drop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup systems
|
||||||
|
log.Printf("Cleaning up %v systems", len(systems))
|
||||||
|
|
||||||
|
for _, system := range systems {
|
||||||
|
system.Cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup scenes
|
||||||
|
log.Printf("Cleaning up %v scenes", len(scenes))
|
||||||
|
|
||||||
|
for _, scene := range scenes {
|
||||||
|
scene.Cleanup()
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup default
|
||||||
|
log.Print("Cleaning up default resources")
|
||||||
|
|
||||||
|
Default2DShader.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
// Stops the game and closes the window.
|
// Stops the game and closes the window.
|
||||||
func Stop() {
|
func Stop() {
|
||||||
log.Print("Stopping main loop")
|
log.Print("Stopping main loop")
|
||||||
@@ -202,10 +285,24 @@ func ClearDepthBuffer(do bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enables/Disables alpha blending by source alpha channel.
|
||||||
|
// BLEND = SRC_ALPHA | ONE_MINUS_SRC_ALPHA
|
||||||
|
func EnableAlphaBlending(enable bool) {
|
||||||
|
if enable {
|
||||||
|
gl.Enable(gl.BLEND)
|
||||||
|
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
|
||||||
|
} else {
|
||||||
|
gl.Disable(gl.BLEND)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sets GL viewport.
|
// Sets GL viewport.
|
||||||
func SetViewport(x, y, width, height int32) {
|
func SetViewport(x, y, width, height int32) {
|
||||||
viewportWidth = int(width)
|
viewportWidth = int(width)
|
||||||
viewportHeight = int(height)
|
viewportHeight = int(height)
|
||||||
|
DefaultCamera.SetViewport(int(x), int(y), viewportWidth, viewportHeight)
|
||||||
|
DefaultCamera.CalcRatio()
|
||||||
|
DefaultCamera.CalcOrtho()
|
||||||
gl.Viewport(x, y, width, height)
|
gl.Viewport(x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,33 +329,3 @@ func removeClearBuffer(buffer uint32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initGoga() {
|
|
||||||
ClearColorBuffer(true)
|
|
||||||
AddLoader(&PngLoader{gl.LINEAR, false})
|
|
||||||
}
|
|
||||||
|
|
||||||
func cleanup() {
|
|
||||||
// cleanup resources
|
|
||||||
log.Print("Cleaning up resources")
|
|
||||||
|
|
||||||
for _, res := range resources {
|
|
||||||
if drop, ok := res.(Dropable); ok {
|
|
||||||
drop.Drop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup systems
|
|
||||||
log.Print("Cleaning up systems")
|
|
||||||
|
|
||||||
for _, system := range systems {
|
|
||||||
system.Cleanup()
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup scenes
|
|
||||||
log.Print("Cleaning up scenes")
|
|
||||||
|
|
||||||
for _, scene := range scenes {
|
|
||||||
scene.Cleanup()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
69
gl_util.go
69
gl_util.go
@@ -13,3 +13,72 @@ func CheckGLError() {
|
|||||||
log.Print(error)
|
log.Print(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates three VBOs for a 2D rectangle.
|
||||||
|
func CreateRectMesh(flip bool) (*VBO, *VBO, *VBO) {
|
||||||
|
ib, vb, tb := createIndexVertexTexCoordBuffer()
|
||||||
|
|
||||||
|
indexData := []uint32{0, 1, 2, 1, 2, 3}
|
||||||
|
vertexData := []float32{0, 0, 1, 0, 0, 1, 1, 1}
|
||||||
|
texData := make([]float32, 8)
|
||||||
|
|
||||||
|
if flip {
|
||||||
|
texData = []float32{0, 0, 1, 0, 0, 1, 1, 1}
|
||||||
|
} else {
|
||||||
|
texData = []float32{0, 1, 1, 1, 0, 0, 1, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
ib.Fill(gl.Ptr(indexData), 4, 6, gl.STATIC_DRAW)
|
||||||
|
vb.Fill(gl.Ptr(vertexData), 4, 8, gl.STATIC_DRAW)
|
||||||
|
tb.Fill(gl.Ptr(texData), 4, 8, gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
return ib, vb, tb
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates three VBOs for a 3D cube mesh.
|
||||||
|
// Texture coordinates won't map properly.
|
||||||
|
// This function is supposed to be used for 3D testing.
|
||||||
|
func CreateCubeMesh() (*VBO, *VBO, *VBO) {
|
||||||
|
ib, vb, tb := createIndexVertexTexCoordBuffer()
|
||||||
|
|
||||||
|
indexData := []uint32{3, 1, 0,
|
||||||
|
0, 2, 3,
|
||||||
|
7, 5, 1,
|
||||||
|
1, 3, 7,
|
||||||
|
6, 4, 5,
|
||||||
|
5, 7, 6,
|
||||||
|
2, 0, 4,
|
||||||
|
4, 6, 2,
|
||||||
|
7, 3, 2,
|
||||||
|
2, 6, 7,
|
||||||
|
1, 5, 4,
|
||||||
|
4, 0, 1}
|
||||||
|
vertexData := []float32{0, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
1, 1, 0,
|
||||||
|
0, 0, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
0, 1, 1,
|
||||||
|
1, 1, 1}
|
||||||
|
texData := []float32{0, 0,
|
||||||
|
1, 0,
|
||||||
|
0, 1,
|
||||||
|
1, 1,
|
||||||
|
1, 1,
|
||||||
|
0, 1,
|
||||||
|
1, 0,
|
||||||
|
0, 0}
|
||||||
|
|
||||||
|
ib.Fill(gl.Ptr(indexData), 4, 36, gl.STATIC_DRAW)
|
||||||
|
vb.Fill(gl.Ptr(vertexData), 4, 24, gl.STATIC_DRAW)
|
||||||
|
tb.Fill(gl.Ptr(texData), 4, 12, gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
return ib, vb, tb
|
||||||
|
}
|
||||||
|
|
||||||
|
func createIndexVertexTexCoordBuffer() (*VBO, *VBO, *VBO) {
|
||||||
|
return NewVBO(gl.ELEMENT_ARRAY_BUFFER),
|
||||||
|
NewVBO(gl.ARRAY_BUFFER),
|
||||||
|
NewVBO(gl.ARRAY_BUFFER)
|
||||||
|
}
|
||||||
|
|||||||
85
pos.go
Normal file
85
pos.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package goga
|
||||||
|
|
||||||
|
// Position component for 2D objects.
|
||||||
|
type Pos2D struct {
|
||||||
|
Pos, Size, Scale, RotPoint Vec2
|
||||||
|
Rot float64
|
||||||
|
Visible bool
|
||||||
|
M Mat3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a default initialized Pos2D.
|
||||||
|
func NewPos2D() *Pos2D {
|
||||||
|
m := Mat3{}
|
||||||
|
m.Identity()
|
||||||
|
return &Pos2D{Size: Vec2{1, 1}, Scale: Vec2{1, 1}, Visible: true, M: m}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates model matrix for 2D positioning.
|
||||||
|
func (p *Pos2D) CalcModel() *Mat3 {
|
||||||
|
p.M.Identity()
|
||||||
|
p.M.Translate(Vec2{p.Pos.X + p.RotPoint.X, p.Pos.Y + p.RotPoint.Y})
|
||||||
|
p.M.Rotate(p.Rot)
|
||||||
|
p.M.Translate(Vec2{-p.RotPoint.X, -p.RotPoint.Y})
|
||||||
|
p.M.Scale(p.Size)
|
||||||
|
p.M.Scale(p.Scale)
|
||||||
|
|
||||||
|
return &p.M
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the center of object.
|
||||||
|
// Assumes y = 0 is bottom left corner, if not you have to subtract height of object.
|
||||||
|
func (p *Pos2D) GetCenter() Vec2 {
|
||||||
|
return Vec2{p.Pos.X + (p.Size.X*p.Scale.X)/2, p.Pos.Y + (p.Size.Y*p.Scale.Y)/2}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true when given point is within rectangle of this object.
|
||||||
|
func (p *Pos2D) PointInRect(point Vec2) bool {
|
||||||
|
return point.X > p.Pos.X && point.X < p.Pos.X+p.Size.X*p.Scale.X && point.Y > p.Pos.Y && point.Y < p.Pos.Y+p.Size.Y*p.Scale.Y
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position component for 3D objects
|
||||||
|
type Pos3D struct {
|
||||||
|
Pos, Size, Scale, RotPoint, Rot Vec3
|
||||||
|
Visible bool
|
||||||
|
M Mat4
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a default initialized Pos3D.
|
||||||
|
func NewPos3D() *Pos3D {
|
||||||
|
m := Mat4{}
|
||||||
|
m.Identity()
|
||||||
|
return &Pos3D{Size: Vec3{1, 1, 1}, Scale: Vec3{1, 1, 1}, Visible: true, M: m}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates model matrix for 3D positioning.
|
||||||
|
func (p *Pos3D) CalcModel() *Mat4 {
|
||||||
|
p.M.Identity()
|
||||||
|
p.M.Translate(Vec3{p.Pos.X + p.RotPoint.X, p.Pos.Y + p.RotPoint.Y, p.Pos.Z + p.RotPoint.Z})
|
||||||
|
p.M.Rotate(p.Rot.X, Vec3{1, 0, 0})
|
||||||
|
p.M.Rotate(p.Rot.Y, Vec3{0, 1, 0})
|
||||||
|
p.M.Rotate(p.Rot.Z, Vec3{0, 0, 1})
|
||||||
|
p.M.Translate(Vec3{-p.RotPoint.X, -p.RotPoint.Y, -p.RotPoint.Z})
|
||||||
|
p.M.Scale(p.Size)
|
||||||
|
p.M.Scale(p.Scale)
|
||||||
|
|
||||||
|
return &p.M
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the center of object.
|
||||||
|
// Assumes y = 0 is bottom left corner, if not you have to subtract height of object.
|
||||||
|
func (p *Pos3D) GetCenter() Vec3 {
|
||||||
|
return Vec3{p.Pos.X + (p.Size.X*p.Scale.X)/2, p.Pos.Y + (p.Size.Y*p.Scale.Y)/2, p.Pos.Z + (p.Size.Z*p.Scale.Z)/2}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Centers given sprite within rectangle.
|
||||||
|
// Does nothing if sprite is nil.
|
||||||
|
// TODO
|
||||||
|
/*func CenterSprite(sprite *Sprite, x, y, width, height int) {
|
||||||
|
if sprite == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.Pos.X = (float64(width-x) - sprite.Size.X) / 2
|
||||||
|
sprite.Pos.Y = (float64(height-y) - sprite.Size.Y) / 2
|
||||||
|
}*/
|
||||||
21
shader.go
21
shader.go
@@ -3,6 +3,7 @@ package goga
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/go-gl/gl/v4.5-core/gl"
|
"github.com/go-gl/gl/v4.5-core/gl"
|
||||||
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,8 +27,9 @@ func NewShader(vertexShader, fragmentShader string) (*Shader, error) {
|
|||||||
shader.program = gl.CreateProgram()
|
shader.program = gl.CreateProgram()
|
||||||
shader.vertex = gl.CreateShader(gl.VERTEX_SHADER)
|
shader.vertex = gl.CreateShader(gl.VERTEX_SHADER)
|
||||||
shader.fragment = gl.CreateShader(gl.FRAGMENT_SHADER)
|
shader.fragment = gl.CreateShader(gl.FRAGMENT_SHADER)
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
if err := compileShader(&shader.vertex, vertexShader+NullTerminator); err != nil {
|
if err := compileShader(shader.vertex, vertexShader+NullTerminator); err != nil {
|
||||||
gl.DeleteShader(shader.vertex)
|
gl.DeleteShader(shader.vertex)
|
||||||
gl.DeleteShader(shader.fragment)
|
gl.DeleteShader(shader.fragment)
|
||||||
shader.Drop()
|
shader.Drop()
|
||||||
@@ -35,7 +37,7 @@ func NewShader(vertexShader, fragmentShader string) (*Shader, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := compileShader(&shader.fragment, fragmentShader+NullTerminator); err != nil {
|
if err := compileShader(shader.fragment, fragmentShader+NullTerminator); err != nil {
|
||||||
gl.DeleteShader(shader.vertex)
|
gl.DeleteShader(shader.vertex)
|
||||||
gl.DeleteShader(shader.fragment)
|
gl.DeleteShader(shader.fragment)
|
||||||
shader.Drop()
|
shader.Drop()
|
||||||
@@ -54,21 +56,26 @@ func NewShader(vertexShader, fragmentShader string) (*Shader, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
// we don't need to keep them in memory
|
// we don't need to keep them in memory
|
||||||
gl.DetachShader(shader.program, shader.vertex)
|
gl.DetachShader(shader.program, shader.vertex)
|
||||||
gl.DetachShader(shader.program, shader.fragment)
|
gl.DetachShader(shader.program, shader.fragment)
|
||||||
gl.DeleteShader(shader.vertex)
|
gl.DeleteShader(shader.vertex)
|
||||||
gl.DeleteShader(shader.fragment)
|
gl.DeleteShader(shader.fragment)
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
return shader, nil
|
return shader, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileShader(shader *uint32, source string) error {
|
func compileShader(shader uint32, source string) error {
|
||||||
csrc := gl.Str(source)
|
log.Print("Compiling shader: " + source)
|
||||||
gl.ShaderSource(*shader, 1, &csrc, nil)
|
csrc, free := gl.Strs(source)
|
||||||
gl.CompileShader(*shader)
|
gl.ShaderSource(shader, 1, csrc, nil)
|
||||||
|
gl.CompileShader(shader)
|
||||||
|
free()
|
||||||
|
|
||||||
if err := shaderCheckError(*shader); err != nil {
|
if err := shaderCheckError(shader); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
shader/basic2D.fs
Normal file
12
shader/basic2D.fs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#version 130
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
color = texture(tex, tc);
|
||||||
|
}
|
||||||
13
shader/basic2D.vs
Normal file
13
shader/basic2D.vs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#version 130
|
||||||
|
|
||||||
|
uniform mat3 o, m;
|
||||||
|
|
||||||
|
in vec2 vertex;
|
||||||
|
in vec2 texCoord;
|
||||||
|
|
||||||
|
out vec2 tc;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
tc = texCoord;
|
||||||
|
gl_Position = vec4(o*m*vec3(vertex, 1.0), 1.0);
|
||||||
|
}
|
||||||
12
shader/basic3D.fs
Normal file
12
shader/basic3D.fs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#version 130
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
color = texture(tex, tc);
|
||||||
|
}
|
||||||
13
shader/basic3D.vs
Normal file
13
shader/basic3D.vs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#version 130
|
||||||
|
|
||||||
|
uniform mat4 pv, m;
|
||||||
|
|
||||||
|
in vec3 vertex;
|
||||||
|
in vec2 texCoord;
|
||||||
|
|
||||||
|
out vec2 tc;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
tc = texCoord;
|
||||||
|
gl_Position = pv*m*vec4(vertex, 1.0);
|
||||||
|
}
|
||||||
13
shader/text.fs
Normal file
13
shader/text.fs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#version 130
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec4 color;
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
|
||||||
|
out vec4 c;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
c = texture(tex, tc)*color;
|
||||||
|
}
|
||||||
13
shader/text.vs
Normal file
13
shader/text.vs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#version 130
|
||||||
|
|
||||||
|
uniform mat3 o, m;
|
||||||
|
|
||||||
|
in vec2 vertex;
|
||||||
|
in vec2 texCoord;
|
||||||
|
|
||||||
|
out vec2 tc;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
tc = texCoord;
|
||||||
|
gl_Position = vec4(o*m*vec3(vertex, 1.0), 1.0);
|
||||||
|
}
|
||||||
163
sprite.go
Normal file
163
sprite.go
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package goga
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-gl/gl/v4.5-core/gl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sprite_renderer_name = "spriteRenderer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Sprite is an actor having a 2D position and a texture.
|
||||||
|
type Sprite struct {
|
||||||
|
*Actor
|
||||||
|
*Pos2D
|
||||||
|
*Tex
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sprite renderer is a system rendering sprites.
|
||||||
|
// It has a 2D position componente, to move all sprites at once.
|
||||||
|
type SpriteRenderer struct {
|
||||||
|
Pos2D
|
||||||
|
|
||||||
|
Shader *Shader
|
||||||
|
Camera *Camera
|
||||||
|
|
||||||
|
sprites []Sprite
|
||||||
|
index, vertex, texCoord *VBO
|
||||||
|
vao *VAO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new sprite with given texture.
|
||||||
|
func NewSprite(tex *Tex) *Sprite {
|
||||||
|
sprite := &Sprite{}
|
||||||
|
sprite.Actor = NewActor()
|
||||||
|
sprite.Pos2D = NewPos2D()
|
||||||
|
sprite.Tex = tex
|
||||||
|
sprite.Size = Vec2{tex.GetSize().X, tex.GetSize().Y}
|
||||||
|
sprite.Scale = Vec2{1, 1}
|
||||||
|
sprite.Visible = true
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
|
return sprite
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new sprite renderer using given shader and camera.
|
||||||
|
// If shader and/or camera are nil, the default one will be used.
|
||||||
|
func NewSpriteRenderer(shader *Shader, camera *Camera, flip bool) *SpriteRenderer {
|
||||||
|
if shader == nil {
|
||||||
|
shader = Default2DShader
|
||||||
|
}
|
||||||
|
|
||||||
|
if camera == nil {
|
||||||
|
camera = DefaultCamera
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer := &SpriteRenderer{}
|
||||||
|
renderer.Shader = shader
|
||||||
|
renderer.Camera = camera
|
||||||
|
renderer.sprites = make([]Sprite, 0)
|
||||||
|
renderer.index, renderer.vertex, renderer.texCoord = CreateRectMesh(flip)
|
||||||
|
renderer.Size = Vec2{1, 1}
|
||||||
|
renderer.Scale = Vec2{1, 1}
|
||||||
|
|
||||||
|
renderer.vao = NewVAO()
|
||||||
|
renderer.vao.Bind()
|
||||||
|
renderer.Shader.EnableVertexAttribArrays()
|
||||||
|
renderer.index.Bind()
|
||||||
|
renderer.vertex.Bind()
|
||||||
|
renderer.vertex.AttribPointer(shader.GetAttribLocation(Default_shader_2D_vertex_attrib), 2, gl.FLOAT, false, 0)
|
||||||
|
renderer.texCoord.Bind()
|
||||||
|
renderer.texCoord.AttribPointer(shader.GetAttribLocation(Default_shader_2D_texcoord_attrib), 2, gl.FLOAT, false, 0)
|
||||||
|
renderer.vao.Unbind()
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
|
return renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frees recources created by sprite renderer.
|
||||||
|
// This is called automatically when system gets removed.
|
||||||
|
func (s *SpriteRenderer) Cleanup() {
|
||||||
|
s.index.Drop()
|
||||||
|
s.vertex.Drop()
|
||||||
|
s.texCoord.Drop()
|
||||||
|
s.vao.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds sprite to the renderer.
|
||||||
|
func (s *SpriteRenderer) Add(actor interface{}) bool {
|
||||||
|
sprite, ok := actor.(*Sprite)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
s.sprites = append(s.sprites, *sprite)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes sprite from renderer.
|
||||||
|
func (s *SpriteRenderer) Remove(actor interface{}) bool {
|
||||||
|
sprite, ok := actor.(Sprite)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sp := range s.sprites {
|
||||||
|
if sp == sprite {
|
||||||
|
s.sprites = append(s.sprites[:i], s.sprites[i+1:]...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes sprite from renderer by ID.
|
||||||
|
func (s *SpriteRenderer) RemoveById(id ActorId) bool {
|
||||||
|
for i, sprite := range s.sprites {
|
||||||
|
if sprite.Actor.GetId() == id {
|
||||||
|
s.sprites = append(s.sprites[:i], s.sprites[i+1:]...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes all sprites from renderer.
|
||||||
|
func (s *SpriteRenderer) RemoveAll() {
|
||||||
|
s.sprites = make([]Sprite, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns number of sprites.
|
||||||
|
func (s *SpriteRenderer) Len() int {
|
||||||
|
return len(s.sprites)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SpriteRenderer) GetName() string {
|
||||||
|
return sprite_renderer_name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renders sprites.
|
||||||
|
func (s *SpriteRenderer) Update(delta float64) {
|
||||||
|
s.Shader.Bind()
|
||||||
|
s.Shader.SendMat3(Default_shader_2D_ortho, *MultMat3(s.Camera.CalcOrtho(), s.CalcModel()))
|
||||||
|
s.Shader.SendUniform1i(Default_shader_2D_tex, 0)
|
||||||
|
s.vao.Bind()
|
||||||
|
|
||||||
|
for i := range s.sprites {
|
||||||
|
if !s.sprites[i].Visible {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Shader.SendMat3(Default_shader_2D_model, *s.sprites[i].CalcModel())
|
||||||
|
s.sprites[i].Tex.Bind()
|
||||||
|
|
||||||
|
gl.DrawElements(gl.TRIANGLES, 6, gl.UNSIGNED_INT, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,8 +10,8 @@ import ()
|
|||||||
type System interface {
|
type System interface {
|
||||||
Update(float64)
|
Update(float64)
|
||||||
Cleanup()
|
Cleanup()
|
||||||
Add(*Actor) bool
|
Add(interface{}) bool
|
||||||
Remove(*Actor) bool
|
Remove(interface{}) bool
|
||||||
RemoveById(ActorId) bool
|
RemoveById(ActorId) bool
|
||||||
RemoveAll()
|
RemoveAll()
|
||||||
Len() int
|
Len() int
|
||||||
|
|||||||
Reference in New Issue
Block a user