forked from 4ydx/gltext
/
bounding_box.go
179 lines (140 loc) · 4.24 KB
/
bounding_box.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2012 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package gltext
import (
"fmt"
"github.com/go-gl/gl/v3.3-core/gl"
"github.com/go-gl/mathgl/mgl32"
)
var boxVertexShaderSource string = `
#version 330
uniform mat4 orthographic_matrix;
uniform vec2 final_position;
in vec4 centered_position;
void main() {
vec4 center = orthographic_matrix * centered_position;
gl_Position = vec4(center.x + final_position.x, center.y + final_position.y, center.z, center.w);
}
` + "\x00"
var boxFragmentShaderSource string = `
#version 330
out vec4 fragment_color;
void main() {
fragment_color = vec4(0.3,0.3,0.3,1);
}
` + "\x00"
type BoundingBox struct {
program uint32 // program compiled from shaders
// font holds our orthographic matrix
font *Font
// attributes
centeredPosition uint32 // vertex position
// the final screen position post-scaling
finalPositionUniform int32
finalPosition mgl32.Vec2
// transform to orthographic projection
orthographicMatrixUniform int32
vao uint32
vbo uint32
ebo uint32
windowWidth float32
windowHeight float32
vboData []float32
vboIndexCount int
eboData []int32
eboIndexCount int
// X1, X2: the lower left and upper right points of a box that bounds the text
X1 Point
X2 Point
}
func loadBoundingBox(f *Font, X1 Point, X2 Point) (b *BoundingBox, err error) {
b = new(BoundingBox)
b.font = f
// create shader program and define attributes and uniforms
b.program, err = NewProgram(boxVertexShaderSource, boxFragmentShaderSource)
if err != nil {
return b, err
}
// ebo, vbo data
b.vboIndexCount = 4 * 2 // 4 indexes per bounding box (containing 2 position)
b.eboIndexCount = 6 // each rune requires 6 triangle indices for a quad
b.vboData = make([]float32, b.vboIndexCount, b.vboIndexCount)
b.eboData = make([]int32, b.eboIndexCount, b.eboIndexCount)
b.makeBufferData(X1, X2)
if f.IsDebug {
fmt.Printf("bounding %v %v\n", X1, X2)
fmt.Printf("bounding vbo data\n%v\n", b.vboData)
fmt.Printf("bounding ebo data\n%v\n", b.eboData)
}
// attributes
b.centeredPosition = uint32(gl.GetAttribLocation(b.program, gl.Str("centered_position\x00")))
// uniforms
b.finalPositionUniform = gl.GetUniformLocation(b.program, gl.Str("final_position\x00"))
b.orthographicMatrixUniform = gl.GetUniformLocation(b.program, gl.Str("orthographic_matrix\x00"))
// size of glfloat
glfloatSize := int32(4)
gl.GenVertexArrays(1, &b.vao)
gl.GenBuffers(1, &b.vbo)
gl.GenBuffers(1, &b.ebo)
// vao
gl.BindVertexArray(b.vao)
// vbo
// specify the buffer for which the VertexAttribPointer calls apply
gl.BindBuffer(gl.ARRAY_BUFFER, b.vbo)
gl.EnableVertexAttribArray(b.centeredPosition)
gl.VertexAttribPointer(
b.centeredPosition,
2,
gl.FLOAT,
false,
0,
gl.PtrOffset(0),
)
gl.BufferData(gl.ARRAY_BUFFER, int(glfloatSize)*b.vboIndexCount, gl.Ptr(b.vboData), gl.DYNAMIC_DRAW)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, b.ebo)
gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, int(glfloatSize)*b.eboIndexCount, gl.Ptr(b.eboData), gl.DYNAMIC_DRAW)
gl.BindVertexArray(0)
// not necesssary, but i just want to better understand using vertex arrays
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, 0)
return b, nil
}
func (b *BoundingBox) Release() {
gl.DeleteBuffers(1, &b.vbo)
gl.DeleteBuffers(1, &b.ebo)
gl.DeleteBuffers(1, &b.vao)
}
func (b *BoundingBox) Draw() {
gl.UseProgram(b.program)
// uniforms
gl.Uniform2fv(b.finalPositionUniform, 1, &b.finalPosition[0])
gl.UniformMatrix4fv(b.orthographicMatrixUniform, 1, false, &b.font.OrthographicMatrix[0])
// draw
gl.BindVertexArray(b.vao)
gl.DrawElements(gl.TRIANGLES, int32(b.eboIndexCount), gl.UNSIGNED_INT, nil)
gl.BindVertexArray(0)
}
func (b *BoundingBox) makeBufferData(X1 Point, X2 Point) {
// counter-clockwise quad
// index (0,0)
b.vboData[0] = X1.X // position
b.vboData[1] = X1.Y
// index (1,0)
b.vboData[2] = X2.X
b.vboData[3] = X1.Y
// index (1,1)
b.vboData[4] = X2.X
b.vboData[5] = X2.Y
// index (0,1)
b.vboData[6] = X1.X
b.vboData[7] = X2.Y
// ebo data
b.eboData[0] = 0
b.eboData[1] = 1
b.eboData[2] = 2
b.eboData[3] = 0
b.eboData[4] = 2
b.eboData[5] = 3
return
}