mirror of
https://github.com/Kugelschieber/go-game.git
synced 2026-01-18 06:40:28 +00:00
Removed shader, added 3D rendering (no demo yet, coming next), started bitmap font rendering, a few fixes and improvements.
This commit is contained in:
@@ -5,7 +5,11 @@ Game engine written in Go using OpenGL and GLFW. Mostly for 2D rendering, but al
|
|||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
go-game requires OpenGL and GLFW. The following three steps install everything you need:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
go get github.com/go-gl/gl/v4.5-core/gl
|
||||||
|
go get github.com/go-gl/glfw/v3.1/glfw
|
||||||
go get github.com/DeKugelschieber/go-game
|
go get github.com/DeKugelschieber/go-game
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -23,3 +27,7 @@ You can find some examples within the demo folder. For full reference visit: htt
|
|||||||
- 3.1
|
- 3.1
|
||||||
|
|
||||||
To use an older GL version, you need to replace the GL imports in package goga. It should mostly be compatible down to 3.x.
|
To use an older GL version, you need to replace the GL imports in package goga. It should mostly be compatible down to 3.x.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|||||||
53
demo/model/assets/cube.ply
Normal file
53
demo/model/assets/cube.ply
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
ply
|
||||||
|
format ascii 1.0
|
||||||
|
comment Created by Blender 2.69 (sub 0) - www.blender.org, source file: ''
|
||||||
|
element vertex 26
|
||||||
|
property float x
|
||||||
|
property float y
|
||||||
|
property float z
|
||||||
|
property float nx
|
||||||
|
property float ny
|
||||||
|
property float nz
|
||||||
|
property float s
|
||||||
|
property float t
|
||||||
|
element face 12
|
||||||
|
property list uchar uint vertex_indices
|
||||||
|
end_header
|
||||||
|
1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.499999 0.500000
|
||||||
|
1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 0.499999 0.749956
|
||||||
|
-1.000000 -1.000000 -1.000000 0.000000 0.000000 -1.000000 0.250043 0.749957
|
||||||
|
1.000000 0.999999 1.000000 -0.000000 -0.000000 1.000000 0.499998 0.250043
|
||||||
|
-1.000000 1.000000 1.000000 -0.000000 -0.000000 1.000000 0.250041 0.250044
|
||||||
|
0.999999 -1.000001 1.000000 -0.000000 -0.000000 1.000000 0.499996 0.000087
|
||||||
|
1.000000 1.000000 -1.000000 1.000000 0.000000 -0.000000 0.749956 0.749956
|
||||||
|
1.000000 0.999999 1.000000 1.000000 0.000000 -0.000000 0.749956 0.999913
|
||||||
|
1.000000 -1.000000 -1.000000 1.000000 0.000000 -0.000000 0.499999 0.749956
|
||||||
|
1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.499999 0.749956
|
||||||
|
0.999999 -1.000001 1.000000 -0.000000 -1.000000 -0.000000 0.500000 0.999913
|
||||||
|
-1.000000 -1.000000 -1.000000 -0.000000 -1.000000 -0.000000 0.250043 0.749957
|
||||||
|
-1.000000 -1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.250043 0.749957
|
||||||
|
-1.000000 -1.000000 1.000000 -1.000000 0.000000 -0.000000 0.250043 0.999913
|
||||||
|
-1.000000 1.000000 1.000000 -1.000000 0.000000 -0.000000 0.000087 0.999913
|
||||||
|
1.000000 0.999999 1.000000 0.000000 1.000000 0.000000 0.499998 0.250043
|
||||||
|
1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 0.499999 0.500000
|
||||||
|
-1.000000 1.000000 1.000000 0.000000 1.000000 0.000000 0.250041 0.250044
|
||||||
|
-1.000000 1.000000 -1.000000 0.000000 0.000000 -1.000000 0.250042 0.500001
|
||||||
|
1.000000 0.999999 1.000000 1.000000 -0.000001 0.000000 0.749956 0.999913
|
||||||
|
0.999999 -1.000001 1.000000 1.000000 -0.000001 0.000000 0.500000 0.999913
|
||||||
|
1.000000 -1.000000 -1.000000 1.000000 -0.000001 0.000000 0.499999 0.749956
|
||||||
|
-1.000000 1.000000 -1.000000 0.000000 1.000000 0.000000 0.250042 0.500001
|
||||||
|
-1.000000 -1.000000 1.000000 0.000000 -0.000000 1.000000 0.250040 0.000088
|
||||||
|
-1.000000 1.000000 -1.000000 -1.000000 0.000000 -0.000000 0.000087 0.749957
|
||||||
|
-1.000000 -1.000000 1.000000 -0.000000 -1.000000 0.000000 0.250043 0.999913
|
||||||
|
3 0 1 2
|
||||||
|
3 3 4 5
|
||||||
|
3 6 7 8
|
||||||
|
3 9 10 11
|
||||||
|
3 12 13 14
|
||||||
|
3 15 16 17
|
||||||
|
3 18 0 2
|
||||||
|
3 19 20 21
|
||||||
|
3 16 22 17
|
||||||
|
3 4 23 5
|
||||||
|
3 24 12 14
|
||||||
|
3 10 25 11
|
||||||
BIN
demo/model/assets/cube.png
Normal file
BIN
demo/model/assets/cube.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
117
game.go
117
game.go
@@ -22,14 +22,15 @@ const (
|
|||||||
Default_shader_2D_model = "m"
|
Default_shader_2D_model = "m"
|
||||||
Default_shader_2D_tex = "tex"
|
Default_shader_2D_tex = "tex"
|
||||||
|
|
||||||
|
// source for 2D shader
|
||||||
default_shader_2d_vertex_src = `#version 130
|
default_shader_2d_vertex_src = `#version 130
|
||||||
uniform mat3 o, m;
|
uniform mat3 o, m;
|
||||||
in vec2 vertex;
|
in vec2 vertex;
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
out vec2 tc;
|
out vec2 tc;
|
||||||
void main(){
|
void main(){
|
||||||
tc = texCoord;
|
tc = texCoord;
|
||||||
gl_Position = vec4(o*m*vec3(vertex, 1.0), 1.0);
|
gl_Position = vec4(o*m*vec3(vertex, 1.0), 1.0);
|
||||||
}`
|
}`
|
||||||
default_shader_2d_fragment_src = `#version 130
|
default_shader_2d_fragment_src = `#version 130
|
||||||
precision highp float;
|
precision highp float;
|
||||||
@@ -37,7 +38,61 @@ const (
|
|||||||
in vec2 tc;
|
in vec2 tc;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
void main(){
|
void main(){
|
||||||
color = texture(tex, tc);
|
color = texture(tex, tc);
|
||||||
|
}`
|
||||||
|
|
||||||
|
// constants for default 3D shader
|
||||||
|
Default_shader_3D_vertex_attrib = "vertex"
|
||||||
|
Default_shader_3D_texcoord_attrib = "texCoord"
|
||||||
|
Default_shader_3D_pv = "pv"
|
||||||
|
Default_shader_3D_model = "m"
|
||||||
|
Default_shader_3D_tex = "tex"
|
||||||
|
|
||||||
|
// source for 3D shader
|
||||||
|
default_shader_3d_vertex_src = `#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);
|
||||||
|
}`
|
||||||
|
default_shader_3d_fragment_src = `#version 130
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
in vec2 tc;
|
||||||
|
out vec4 color;
|
||||||
|
void main(){
|
||||||
|
color = texture(tex, tc);
|
||||||
|
}`
|
||||||
|
|
||||||
|
// constants for default text shader
|
||||||
|
Default_shader_text_vertex_attrib = "vertex"
|
||||||
|
Default_shader_text_texcoord_attrib = "texCoord"
|
||||||
|
Default_shader_text_ortho = "o"
|
||||||
|
Default_shader_text_model = "m"
|
||||||
|
Default_shader_text_tex = "tex"
|
||||||
|
Default_shader_text_color = "color"
|
||||||
|
|
||||||
|
// source for text shader
|
||||||
|
default_shader_text_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_text_fragment_src = `#version 130
|
||||||
|
precision highp float;
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec4 color;
|
||||||
|
in vec2 tc;
|
||||||
|
out vec4 c;
|
||||||
|
void main(){
|
||||||
|
c = texture(tex, tc)*color;
|
||||||
}`
|
}`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,8 +128,10 @@ var (
|
|||||||
viewportHeight int
|
viewportHeight int
|
||||||
|
|
||||||
// Default resources
|
// Default resources
|
||||||
DefaultCamera *Camera
|
DefaultCamera *Camera
|
||||||
Default2DShader *Shader
|
Default2DShader *Shader
|
||||||
|
Default3DShader *Shader
|
||||||
|
DefaultTextShader *Shader
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -211,7 +268,7 @@ func initGoga(width, height int) {
|
|||||||
DefaultCamera.CalcRatio()
|
DefaultCamera.CalcRatio()
|
||||||
DefaultCamera.CalcOrtho()
|
DefaultCamera.CalcOrtho()
|
||||||
|
|
||||||
// default shader
|
// default 2D shader
|
||||||
shader, err := NewShader(default_shader_2d_vertex_src, default_shader_2d_fragment_src)
|
shader, err := NewShader(default_shader_2d_vertex_src, default_shader_2d_fragment_src)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -222,25 +279,52 @@ func initGoga(width, height int) {
|
|||||||
Default2DShader.BindAttrib(Default_shader_2D_vertex_attrib)
|
Default2DShader.BindAttrib(Default_shader_2D_vertex_attrib)
|
||||||
Default2DShader.BindAttrib(Default_shader_2D_texcoord_attrib)
|
Default2DShader.BindAttrib(Default_shader_2D_texcoord_attrib)
|
||||||
|
|
||||||
|
// default 3D shader
|
||||||
|
shader, err = NewShader(default_shader_3d_vertex_src, default_shader_3d_fragment_src)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Default3DShader = shader
|
||||||
|
Default3DShader.BindAttrib(Default_shader_3D_vertex_attrib)
|
||||||
|
Default3DShader.BindAttrib(Default_shader_3D_texcoord_attrib)
|
||||||
|
|
||||||
|
// default text shader
|
||||||
|
shader, err = NewShader(default_shader_text_vertex_src, default_shader_text_fragment_src)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTextShader = shader
|
||||||
|
DefaultTextShader.BindAttrib(Default_shader_text_vertex_attrib)
|
||||||
|
DefaultTextShader.BindAttrib(Default_shader_text_texcoord_attrib)
|
||||||
|
|
||||||
// settings and registration
|
// settings and registration
|
||||||
ClearColorBuffer(true)
|
ClearColorBuffer(true)
|
||||||
EnableAlphaBlending(true)
|
EnableAlphaBlending(true)
|
||||||
AddLoader(&PngLoader{gl.LINEAR, false})
|
AddLoader(&PngLoader{gl.LINEAR, false})
|
||||||
AddLoader(&PlyLoader{gl.STATIC_DRAW})
|
AddLoader(&PlyLoader{gl.STATIC_DRAW})
|
||||||
AddSystem(NewSpriteRenderer(nil, nil, false))
|
AddSystem(NewSpriteRenderer(nil, nil, false))
|
||||||
|
AddSystem(NewModelRenderer(nil, nil, false))
|
||||||
AddSystem(NewCulling2D(0, 0, width, height))
|
AddSystem(NewCulling2D(0, 0, width, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanup() {
|
func cleanup() {
|
||||||
// cleanup resources
|
// cleanup resources
|
||||||
log.Printf("Cleaning up %v resources", len(resources))
|
log.Printf("Trying to cleaning up %v resources", len(resources))
|
||||||
|
dropped := 0
|
||||||
|
|
||||||
for _, res := range resources {
|
for _, res := range resources {
|
||||||
if drop, ok := res.(Dropable); ok {
|
if drop, ok := res.(Dropable); ok {
|
||||||
drop.Drop()
|
drop.Drop()
|
||||||
|
dropped++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("Dropped %v resources", dropped)
|
||||||
|
|
||||||
// cleanup systems
|
// cleanup systems
|
||||||
log.Printf("Cleaning up %v systems", len(systems))
|
log.Printf("Cleaning up %v systems", len(systems))
|
||||||
|
|
||||||
@@ -259,6 +343,7 @@ func cleanup() {
|
|||||||
log.Print("Cleaning up default resources")
|
log.Print("Cleaning up default resources")
|
||||||
|
|
||||||
Default2DShader.Drop()
|
Default2DShader.Drop()
|
||||||
|
DefaultTextShader.Drop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stops the game and closes the window.
|
// Stops the game and closes the window.
|
||||||
@@ -287,6 +372,15 @@ func ClearDepthBuffer(do bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeClearBuffer(buffer uint32) {
|
||||||
|
for i, b := range clearBuffer {
|
||||||
|
if b == buffer {
|
||||||
|
clearBuffer = append(clearBuffer[:i], clearBuffer[i+1:]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Enables/Disables alpha blending by source alpha channel.
|
// Enables/Disables alpha blending by source alpha channel.
|
||||||
// BLEND = SRC_ALPHA | ONE_MINUS_SRC_ALPHA
|
// BLEND = SRC_ALPHA | ONE_MINUS_SRC_ALPHA
|
||||||
func EnableAlphaBlending(enable bool) {
|
func EnableAlphaBlending(enable bool) {
|
||||||
@@ -332,12 +426,3 @@ func GetWidth() int {
|
|||||||
func GetHeight() int {
|
func GetHeight() int {
|
||||||
return viewportHeight
|
return viewportHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeClearBuffer(buffer uint32) {
|
|
||||||
for i, buffer := range clearBuffer {
|
|
||||||
if buffer == buffer {
|
|
||||||
clearBuffer = append(clearBuffer[:i], clearBuffer[i+1:]...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
19
loader.go
19
loader.go
@@ -75,6 +75,25 @@ type Ply struct {
|
|||||||
IndexBuffer, VertexBuffer, TexCoordBuffer, NormalBuffer *VBO
|
IndexBuffer, VertexBuffer, TexCoordBuffer, NormalBuffer *VBO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drops contained GL buffers.
|
||||||
|
func (p *Ply) Drop() {
|
||||||
|
if p.IndexBuffer != nil {
|
||||||
|
p.IndexBuffer.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.VertexBuffer != nil {
|
||||||
|
p.VertexBuffer.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.TexCoordBuffer != nil {
|
||||||
|
p.TexCoordBuffer.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.NormalBuffer != nil {
|
||||||
|
p.NormalBuffer.Drop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the name of this resource.
|
// Returns the name of this resource.
|
||||||
func (p *Ply) GetName() string {
|
func (p *Ply) GetName() string {
|
||||||
return p.name
|
return p.name
|
||||||
|
|||||||
193
model.go
Normal file
193
model.go
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
package goga
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-gl/gl/v4.5-core/gl"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
model_renderer_name = "modelRenderer"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Component representing a 3D mesh.
|
||||||
|
type Mesh struct {
|
||||||
|
Index, Vertex, TexCoord *VBO
|
||||||
|
Vao *VAO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new mesh with given GL buffers.
|
||||||
|
// The VAO must be prepared by ModelRenderer.
|
||||||
|
func NewMesh(index, vertex, texcoord *VBO) *Mesh {
|
||||||
|
mesh := &Mesh{}
|
||||||
|
mesh.Index = index
|
||||||
|
mesh.Vertex = vertex
|
||||||
|
mesh.TexCoord = texcoord
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drops the VBOs and VAO contained in mesh.
|
||||||
|
// This must not be done, if mesh was filled from outer source (like a ply file).
|
||||||
|
func (m *Mesh) Drop() {
|
||||||
|
m.Index.Drop()
|
||||||
|
m.Vertex.Drop()
|
||||||
|
m.TexCoord.Drop()
|
||||||
|
m.Vao.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Model is an actor having a 3D position, a texture and a 3D mesh.
|
||||||
|
type Model struct {
|
||||||
|
*Actor
|
||||||
|
*Pos3D
|
||||||
|
*Tex
|
||||||
|
*Mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new model with given mesh and texture.
|
||||||
|
func NewModel(mesh *Mesh, tex *Tex) *Model {
|
||||||
|
model := &Model{}
|
||||||
|
model.Actor = NewActor()
|
||||||
|
model.Pos3D = NewPos3D()
|
||||||
|
model.Tex = tex
|
||||||
|
model.Mesh = mesh
|
||||||
|
model.Size = Vec3{1, 1, 1}
|
||||||
|
model.Scale = Vec3{1, 1, 1}
|
||||||
|
model.Visible = true
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
|
return model
|
||||||
|
}
|
||||||
|
|
||||||
|
// The model renderer is a system rendering models.
|
||||||
|
// It has a 3D position component, to move all models at once.
|
||||||
|
type ModelRenderer struct {
|
||||||
|
Pos3D
|
||||||
|
|
||||||
|
Shader *Shader
|
||||||
|
Camera *Camera
|
||||||
|
ortho bool
|
||||||
|
|
||||||
|
models []Model
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new model renderer using given shader and camera.
|
||||||
|
// If shader and/or camera are nil, the default one will be used.
|
||||||
|
// Orth can be set to true, to use orthogonal projection.
|
||||||
|
func NewModelRenderer(shader *Shader, camera *Camera, ortho bool) *ModelRenderer {
|
||||||
|
if shader == nil {
|
||||||
|
shader = Default3DShader
|
||||||
|
}
|
||||||
|
|
||||||
|
if camera == nil {
|
||||||
|
camera = DefaultCamera
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer := &ModelRenderer{}
|
||||||
|
renderer.Shader = shader
|
||||||
|
renderer.Camera = camera
|
||||||
|
renderer.ortho = ortho
|
||||||
|
renderer.models = make([]Model, 0)
|
||||||
|
renderer.Size = Vec3{1, 1, 1}
|
||||||
|
renderer.Scale = Vec3{1, 1, 1}
|
||||||
|
|
||||||
|
CheckGLError()
|
||||||
|
|
||||||
|
return renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ModelRenderer) Cleanup() {}
|
||||||
|
|
||||||
|
// Prepares a model to be rendered by setting up its VAO.
|
||||||
|
func (s *ModelRenderer) Prepare(model *Model) {
|
||||||
|
model.Vao = NewVAO()
|
||||||
|
model.Vao.Bind()
|
||||||
|
s.Shader.EnableVertexAttribArrays()
|
||||||
|
model.Index.Bind()
|
||||||
|
model.Vertex.Bind()
|
||||||
|
model.Vertex.AttribPointer(s.Shader.GetAttribLocation(Default_shader_3D_vertex_attrib), 3, gl.FLOAT, false, 0)
|
||||||
|
model.TexCoord.Bind()
|
||||||
|
model.TexCoord.AttribPointer(s.Shader.GetAttribLocation(Default_shader_3D_texcoord_attrib), 2, gl.FLOAT, false, 0)
|
||||||
|
model.Vao.Unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds model to the renderer.
|
||||||
|
// Perpare it first!
|
||||||
|
func (s *ModelRenderer) Add(actor *Actor, pos *Pos3D, tex *Tex, mesh *Mesh) bool {
|
||||||
|
id := actor.GetId()
|
||||||
|
|
||||||
|
for _, model := range s.models {
|
||||||
|
if id == model.Actor.GetId() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.models = append(s.models, Model{actor, pos, tex, mesh})
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes model from renderer.
|
||||||
|
func (s *ModelRenderer) Remove(actor *Actor) bool {
|
||||||
|
return s.RemoveById(actor.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes model from renderer by ID.
|
||||||
|
func (s *ModelRenderer) RemoveById(id ActorId) bool {
|
||||||
|
for i, model := range s.models {
|
||||||
|
if model.Actor.GetId() == id {
|
||||||
|
s.models = append(s.models[:i], s.models[i+1:]...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes all sprites.
|
||||||
|
func (s *ModelRenderer) RemoveAll() {
|
||||||
|
s.models = make([]Model, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns number of sprites.
|
||||||
|
func (s *ModelRenderer) Len() int {
|
||||||
|
return len(s.models)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ModelRenderer) GetName() string {
|
||||||
|
return model_renderer_name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render models.
|
||||||
|
func (s *ModelRenderer) Update(delta float64) {
|
||||||
|
s.Shader.Bind()
|
||||||
|
s.Shader.SendUniform1i(Default_shader_3D_tex, 0)
|
||||||
|
|
||||||
|
if s.ortho {
|
||||||
|
s.Shader.SendMat4(Default_shader_3D_pv, *MultMat4(s.Camera.CalcOrtho3D(), s.CalcModel()))
|
||||||
|
} else {
|
||||||
|
pv := s.Camera.CalcProjection()
|
||||||
|
pv.Mult(s.Camera.CalcView())
|
||||||
|
s.Shader.SendMat4(Default_shader_3D_pv, *pv)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tid uint32
|
||||||
|
|
||||||
|
for i := range s.models {
|
||||||
|
if !s.models[i].Visible {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Shader.SendMat4(Default_shader_3D_model, *s.models[i].CalcModel())
|
||||||
|
s.models[i].Vao.Bind()
|
||||||
|
|
||||||
|
// prevent texture switching when not neccessary
|
||||||
|
if tid != s.models[i].Tex.GetId() {
|
||||||
|
tid = s.models[i].Tex.GetId()
|
||||||
|
s.models[i].Tex.Bind()
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.DrawElements(gl.TRIANGLES, s.models[i].Index.Size(), gl.UNSIGNED_INT, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
18
res_util.go
18
res_util.go
@@ -21,3 +21,21 @@ func GetTex(name string) (*Tex, error) {
|
|||||||
|
|
||||||
return tex, nil
|
return tex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finds and returns a Ply resource.
|
||||||
|
// If not found or when the resource is of wrong type, an error will be returned.
|
||||||
|
func GetPly(name string) (*Ply, error) {
|
||||||
|
res := GetResByName(name)
|
||||||
|
|
||||||
|
if res == nil {
|
||||||
|
return nil, errors.New("Resource not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
ply, ok := res.(*Ply)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("Resource was not of type *Ply")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ply, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#version 130
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
in vec2 tc;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
void main(){
|
|
||||||
color = texture(tex, tc);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
#version 130
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
in vec2 tc;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
|
|
||||||
void main(){
|
|
||||||
color = texture(tex, tc);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#version 130
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform vec4 color;
|
|
||||||
|
|
||||||
in vec2 tc;
|
|
||||||
|
|
||||||
out vec4 c;
|
|
||||||
|
|
||||||
void main(){
|
|
||||||
c = texture(tex, tc)*color;
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
29
sprite.go
29
sprite.go
@@ -15,19 +15,6 @@ type Sprite struct {
|
|||||||
*Tex
|
*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.
|
// Creates a new sprite with given texture.
|
||||||
func NewSprite(tex *Tex) *Sprite {
|
func NewSprite(tex *Tex) *Sprite {
|
||||||
sprite := &Sprite{}
|
sprite := &Sprite{}
|
||||||
@@ -43,6 +30,19 @@ func NewSprite(tex *Tex) *Sprite {
|
|||||||
return sprite
|
return sprite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The sprite renderer is a system rendering sprites.
|
||||||
|
// It has a 2D position component, 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 renderer using given shader and camera.
|
// Creates a new sprite renderer using given shader and camera.
|
||||||
// If shader and/or camera are nil, the default one will be used.
|
// If shader and/or camera are nil, the default one will be used.
|
||||||
func NewSpriteRenderer(shader *Shader, camera *Camera, flip bool) *SpriteRenderer {
|
func NewSpriteRenderer(shader *Shader, camera *Camera, flip bool) *SpriteRenderer {
|
||||||
@@ -132,7 +132,7 @@ func (s *SpriteRenderer) GetName() string {
|
|||||||
return sprite_renderer_name
|
return sprite_renderer_name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renders sprites.
|
// Render sprites.
|
||||||
func (s *SpriteRenderer) Update(delta float64) {
|
func (s *SpriteRenderer) Update(delta float64) {
|
||||||
s.Shader.Bind()
|
s.Shader.Bind()
|
||||||
s.Shader.SendMat3(Default_shader_2D_ortho, *MultMat3(s.Camera.CalcOrtho(), s.CalcModel()))
|
s.Shader.SendMat3(Default_shader_2D_ortho, *MultMat3(s.Camera.CalcOrtho(), s.CalcModel()))
|
||||||
@@ -147,6 +147,7 @@ func (s *SpriteRenderer) Update(delta float64) {
|
|||||||
|
|
||||||
s.Shader.SendMat3(Default_shader_2D_model, *s.sprites[i].CalcModel())
|
s.Shader.SendMat3(Default_shader_2D_model, *s.sprites[i].CalcModel())
|
||||||
|
|
||||||
|
// prevent texture switching when not neccessary
|
||||||
if tid != s.sprites[i].Tex.GetId() {
|
if tid != s.sprites[i].Tex.GetId() {
|
||||||
tid = s.sprites[i].Tex.GetId()
|
tid = s.sprites[i].Tex.GetId()
|
||||||
s.sprites[i].Tex.Bind()
|
s.sprites[i].Tex.Bind()
|
||||||
|
|||||||
402
text.go
Normal file
402
text.go
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
package goga
|
||||||
|
|
||||||
|
/*
|
||||||
|
import (
|
||||||
|
"core"
|
||||||
|
"dp"
|
||||||
|
"encoding/json"
|
||||||
|
"geo"
|
||||||
|
"github.com/go-gl/gl/v4.5-core/gl"
|
||||||
|
"io/ioutil"
|
||||||
|
"util"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
char_padding = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Returns a new renderable text object.
|
||||||
|
func NewText(font *Font, text string) *Text {
|
||||||
|
t := &Text{id: core.NextId()}
|
||||||
|
t.text = text
|
||||||
|
t.index = dp.NewVBO(gl.ELEMENT_ARRAY_BUFFER)
|
||||||
|
t.vertex = dp.NewVBO(gl.ARRAY_BUFFER)
|
||||||
|
t.texCoord = dp.NewVBO(gl.ARRAY_BUFFER)
|
||||||
|
t.vao = dp.NewVAO()
|
||||||
|
t.SetText(font, text)
|
||||||
|
t.Size = geo.Vec2{1, 1}
|
||||||
|
t.Scale = geo.Vec2{1, 1}
|
||||||
|
t.Visible = true
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
type Character struct {
|
||||||
|
char byte
|
||||||
|
min, max, size geo.Vec2
|
||||||
|
offset float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Font struct {
|
||||||
|
Tex *dp.Tex
|
||||||
|
tileSize float64
|
||||||
|
CharPadding geo.Vec2
|
||||||
|
Space, Tab, Line float64
|
||||||
|
chars []Character
|
||||||
|
}
|
||||||
|
|
||||||
|
type jsonChar struct {
|
||||||
|
Char string
|
||||||
|
X, Y, Offset float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new font from texture. Characters must be added afterwards.
|
||||||
|
// The characters must be placed within a grid,
|
||||||
|
// the second parameter describes the width and height of one tile in pixel.
|
||||||
|
func NewFont(tex *dp.Tex, tileSize int) *Font {
|
||||||
|
font := &Font{}
|
||||||
|
font.Tex = tex
|
||||||
|
font.tileSize = float64(tileSize)
|
||||||
|
font.CharPadding = geo.Vec2{0.05, 0.05}
|
||||||
|
font.Space = 0.3
|
||||||
|
font.Tab = 1.2
|
||||||
|
font.Line = 1
|
||||||
|
font.chars = make([]Character, 0)
|
||||||
|
|
||||||
|
return font
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loads characters from JSON file.
|
||||||
|
// Format:
|
||||||
|
//
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// "char": "a",
|
||||||
|
// "x": 0,
|
||||||
|
// "y": 0,
|
||||||
|
// "offset": 0
|
||||||
|
// },
|
||||||
|
// ...
|
||||||
|
// ]
|
||||||
|
//
|
||||||
|
// Where x and y start in the upper left corner of the texture, both of type int.
|
||||||
|
// Offset is optional and can be used to move a character up or down (relative to others).
|
||||||
|
// If cut is set to true, the characters will be true typed.
|
||||||
|
func (f *Font) LoadFromJson(path string, cut bool) error {
|
||||||
|
// load file content
|
||||||
|
content, err := ioutil.ReadFile(path)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// read json
|
||||||
|
chars := make([]jsonChar, 0)
|
||||||
|
|
||||||
|
if err = json.Unmarshal(content, &chars); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.extractChars(chars, cut)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) extractChars(chars []jsonChar, cut bool) {
|
||||||
|
for _, char := range chars {
|
||||||
|
if len(char.Char) != 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var min, max, size geo.Vec2
|
||||||
|
|
||||||
|
if !cut {
|
||||||
|
min = geo.Vec2{char.X * f.tileSize, char.Y * f.tileSize}
|
||||||
|
max = geo.Vec2{min.X + f.tileSize, min.Y + f.tileSize}
|
||||||
|
size = geo.Vec2{1, 1}
|
||||||
|
} else {
|
||||||
|
min, max, size = f.cutChar(int(char.X), int(char.Y))
|
||||||
|
}
|
||||||
|
|
||||||
|
f.chars = append(f.chars, Character{char.Char[0], min, max, size, char.Offset})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) cutChar(x, y int) (geo.Vec2, geo.Vec2, geo.Vec2) {
|
||||||
|
minX := int(f.Tex.GetSize().X)
|
||||||
|
minY := int(f.Tex.GetSize().Y)
|
||||||
|
maxX := 0
|
||||||
|
maxY := 0
|
||||||
|
rgba := f.Tex.GetRGBA()
|
||||||
|
|
||||||
|
for ry := y * int(f.tileSize); ry < (y+1)*int(f.tileSize); ry++ {
|
||||||
|
for rx := x * int(f.tileSize); rx < (x+1)*int(f.tileSize); rx++ {
|
||||||
|
_, _, _, a := rgba.At(rx, ry).RGBA()
|
||||||
|
|
||||||
|
if a == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if rx < minX {
|
||||||
|
minX = rx
|
||||||
|
} else if rx > maxX {
|
||||||
|
maxX = rx
|
||||||
|
}
|
||||||
|
|
||||||
|
if ry < minY {
|
||||||
|
minY = ry
|
||||||
|
} else if ry > maxY {
|
||||||
|
maxY = ry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minX -= char_padding
|
||||||
|
maxX += char_padding
|
||||||
|
minY -= char_padding
|
||||||
|
maxY += char_padding
|
||||||
|
|
||||||
|
texSize := f.Tex.GetSize()
|
||||||
|
min := geo.Vec2{float64(minX) / texSize.X, float64(maxY) / texSize.Y}
|
||||||
|
max := geo.Vec2{float64(maxX) / texSize.X, float64(minY) / texSize.Y}
|
||||||
|
|
||||||
|
// size
|
||||||
|
size := geo.Vec2{float64(maxX-minX) / f.tileSize, float64(maxY-minY) / f.tileSize}
|
||||||
|
|
||||||
|
return min, max, size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Font) getChar(char byte) *Character {
|
||||||
|
for _, character := range f.chars {
|
||||||
|
if character.char == char {
|
||||||
|
return &character
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Text struct {
|
||||||
|
*Actor
|
||||||
|
*Pos2D
|
||||||
|
|
||||||
|
id int
|
||||||
|
text string
|
||||||
|
bounds geo.Vec2
|
||||||
|
|
||||||
|
index, vertex, texCoord *dp.VBO
|
||||||
|
vao *dp.VAO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes GL buffers bound to this text.
|
||||||
|
func (t *Text) Drop() {
|
||||||
|
t.index.Drop()
|
||||||
|
t.vertex.Drop()
|
||||||
|
t.texCoord.Drop()
|
||||||
|
t.vao.Drop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the given string as text and (re)creates buffers.
|
||||||
|
func (t *Text) SetText(font *Font, text string) {
|
||||||
|
t.text = text
|
||||||
|
|
||||||
|
indices := make([]uint32, len(text)*6)
|
||||||
|
vertices := make([]float32, len(text)*8)
|
||||||
|
texCoords := make([]float32, len(text)*8)
|
||||||
|
chars := 0
|
||||||
|
|
||||||
|
// create indices
|
||||||
|
var index uint32 = 0
|
||||||
|
|
||||||
|
for i := 0; i < len(text)*6; i += 6 {
|
||||||
|
indices[i] = index
|
||||||
|
indices[i+1] = index + 1
|
||||||
|
indices[i+2] = index + 2
|
||||||
|
indices[i+3] = index + 1
|
||||||
|
indices[i+4] = index + 2
|
||||||
|
indices[i+5] = index + 3
|
||||||
|
|
||||||
|
index += 4
|
||||||
|
}
|
||||||
|
|
||||||
|
// create vertices/texCoords
|
||||||
|
index = 0
|
||||||
|
offset := geo.Vec2{}
|
||||||
|
var width, height float64
|
||||||
|
|
||||||
|
for i := 0; i < len(text)*8 && int(index) < len(text); i += 8 {
|
||||||
|
c := font.getChar(text[index])
|
||||||
|
index++
|
||||||
|
|
||||||
|
// whitespace and new line
|
||||||
|
if text[index-1] == ' ' {
|
||||||
|
offset.X += font.Space
|
||||||
|
i -= 8
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if text[index-1] == '\n' {
|
||||||
|
offset.X = 0
|
||||||
|
offset.Y -= font.Line
|
||||||
|
i -= 8
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if text[index-1] == '\t' {
|
||||||
|
offset.X += font.Tab
|
||||||
|
i -= 8
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// character not found
|
||||||
|
if c == nil {
|
||||||
|
i -= 8
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// usual character
|
||||||
|
vertices[i] = float32(offset.X)
|
||||||
|
vertices[i+1] = float32(offset.Y + c.offset)
|
||||||
|
vertices[i+2] = float32(offset.X + c.size.X)
|
||||||
|
vertices[i+3] = float32(offset.Y + c.offset)
|
||||||
|
vertices[i+4] = float32(offset.X)
|
||||||
|
vertices[i+5] = float32(offset.Y + c.size.Y + c.offset)
|
||||||
|
vertices[i+6] = float32(offset.X + c.size.X)
|
||||||
|
vertices[i+7] = float32(offset.Y + c.size.Y + c.offset)
|
||||||
|
|
||||||
|
texCoords[i] = float32(c.min.X)
|
||||||
|
texCoords[i+1] = float32(c.min.Y)
|
||||||
|
texCoords[i+2] = float32(c.max.X)
|
||||||
|
texCoords[i+3] = float32(c.min.Y)
|
||||||
|
texCoords[i+4] = float32(c.min.X)
|
||||||
|
texCoords[i+5] = float32(c.max.Y)
|
||||||
|
texCoords[i+6] = float32(c.max.X)
|
||||||
|
texCoords[i+7] = float32(c.max.Y)
|
||||||
|
|
||||||
|
offset.X += c.size.X + font.CharPadding.X
|
||||||
|
chars++
|
||||||
|
|
||||||
|
if offset.X > width {
|
||||||
|
width = offset.X
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset.Y*-1+font.Line > height {
|
||||||
|
height = offset.Y*-1 + font.Line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.bounds = geo.Vec2{width, height}
|
||||||
|
|
||||||
|
// fill GL buffer
|
||||||
|
t.index.Fill(gl.Ptr(indices[:chars*6]), 4, chars*6, gl.STATIC_DRAW)
|
||||||
|
t.vertex.Fill(gl.Ptr(vertices[:chars*8]), 4, chars*8, gl.STATIC_DRAW)
|
||||||
|
t.texCoord.Fill(gl.Ptr(texCoords[:chars*8]), 4, chars*8, gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
util.CheckGLError()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Text) GetId() int {
|
||||||
|
return t.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the text as string.
|
||||||
|
func (t *Text) GetText() string {
|
||||||
|
return t.text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns bounds of text, which is the size of characters.
|
||||||
|
func (t *Text) GetBounds() geo.Vec2 {
|
||||||
|
return geo.Vec2{t.bounds.X * t.Size.X * t.Scale.X, t.bounds.Y * t.Size.Y * t.Scale.Y}
|
||||||
|
}
|
||||||
|
|
||||||
|
type TextRenderer struct {
|
||||||
|
Pos2D
|
||||||
|
|
||||||
|
Shader *dp.Shader
|
||||||
|
Camera *Camera
|
||||||
|
Font *Font
|
||||||
|
Color geo.Vec4
|
||||||
|
texts []*Text
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new text renderer using given shader, camera and font.
|
||||||
|
// If shader and/or camera are nil, the default one will be used.
|
||||||
|
func NewTextRenderer(shader *dp.Shader, camera *Camera, font *Font) *TextRenderer {
|
||||||
|
renderer := &TextRenderer{}
|
||||||
|
renderer.Shader = shader
|
||||||
|
renderer.Camera = camera
|
||||||
|
renderer.Font = font
|
||||||
|
renderer.Color = geo.Vec4{1, 1, 1, 1}
|
||||||
|
renderer.texts = make([]*Text, 0)
|
||||||
|
renderer.Size = geo.Vec2{1, 1}
|
||||||
|
renderer.Scale = geo.Vec2{1, 1}
|
||||||
|
|
||||||
|
return renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a text for rendering.
|
||||||
|
func (r *TextRenderer) Prepare(text *Text) {
|
||||||
|
text.vao = dp.NewVAO()
|
||||||
|
text.vao.Bind()
|
||||||
|
r.Shader.EnableVertexAttribArrays()
|
||||||
|
text.index.Bind()
|
||||||
|
text.vertex.Bind()
|
||||||
|
text.vertex.AttribPointer(r.Shader.GetAttribLocation(TEXTRENDERER_VERTEX_ATTRIB), 2, gl.FLOAT, false, 0)
|
||||||
|
text.texCoord.Bind()
|
||||||
|
text.texCoord.AttribPointer(r.Shader.GetAttribLocation(TEXTRENDERER_TEXCOORD_ATTRIB), 2, gl.FLOAT, false, 0)
|
||||||
|
text.vao.Unbind()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds text to the renderer.
|
||||||
|
func (r *TextRenderer) Add(text *Text) {
|
||||||
|
r.texts = append(r.texts, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns text by ID.
|
||||||
|
func (r *TextRenderer) Get(id int) *Text {
|
||||||
|
for _, text := range r.texts {
|
||||||
|
if text.GetId() == id {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes text from renderer by ID.
|
||||||
|
func (r *TextRenderer) Remove(id int) *Text {
|
||||||
|
for i, text := range r.texts {
|
||||||
|
if text.GetId() == id {
|
||||||
|
r.texts = append(r.texts[:i], r.texts[i+1:]...)
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes all sprites.
|
||||||
|
func (r *TextRenderer) Clear() {
|
||||||
|
r.texts = make([]*Text, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renders sprites.
|
||||||
|
func (r *TextRenderer) Render() {
|
||||||
|
r.Shader.Bind()
|
||||||
|
r.Shader.SendMat3(TEXTRENDERER_ORTHO, *geo.MultMat3(r.Camera.CalcOrtho(), r.CalcModel()))
|
||||||
|
r.Shader.SendUniform1i(TEXTRENDERER_TEX, 0)
|
||||||
|
r.Shader.SendUniform4f(TEXTRENDERER_COLOR, float32(r.Color.X), float32(r.Color.Y), float32(r.Color.Z), float32(r.Color.W))
|
||||||
|
r.Font.Tex.Bind()
|
||||||
|
|
||||||
|
for i := range r.texts {
|
||||||
|
if !r.texts[i].Visible {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.texts[i].vao.Bind()
|
||||||
|
r.Shader.SendMat3(TEXTRENDERER_MODEL, *r.texts[i].CalcModel())
|
||||||
|
|
||||||
|
gl.DrawElements(gl.TRIANGLES, r.texts[i].index.Size(), gl.UNSIGNED_INT, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user