Skip to content

Commit 1c773e9

Browse files
committed
Tutorial 06 - Dibujar Texto 2D
Mostrar texto 2D usando la librería STB para cargar una fuente TrueType.
1 parent 057663e commit 1c773e9

10 files changed

+390
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ find_package(GLM REQUIRED)
1212
include_directories(${GLFW3_INCLUDE_DIRS})
1313
include_directories(${GLEW_INCLUDE_DIRS})
1414
include_directories(${GLM_INCLUDE_DIRS})
15+
1516
include_directories(Common)
1617

1718
set(GRAPHIC_LIBS ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARIES} ${GLFW3_LIBRARY})
@@ -22,3 +23,4 @@ add_subdirectory(Tutorial-02)
2223
add_subdirectory(Tutorial-03)
2324
add_subdirectory(Tutorial-04)
2425
add_subdirectory(Tutorial-05)
26+
add_subdirectory(Tutorial-06)

Common/OpenGLText.hpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#ifndef OPENGLTEXT_H
2+
#define OPENGLTEXT_H
3+
4+
#include <cstdio>
5+
#include <string>
6+
#include <vector>
7+
8+
#include <GL\GL.h>
9+
#include <GL\glew.h>
10+
#include <glm\glm.hpp>
11+
#include <glm\gtc\matrix_transform.hpp>
12+
13+
#include "OpenGLShader.hpp"
14+
15+
#define STB_TRUETYPE_IMPLEMENTATION
16+
#define STB_RECT_PACK_IMPLEMENTATION
17+
#define STB_IMAGE_WRITE_IMPLEMENTATION
18+
19+
#include "stb\stb_rect_pack.h"
20+
#include "stb\stb_truetype.h"
21+
#include "stb\stb_image_write.h"
22+
23+
#define BITMAP_W 1024
24+
#define BITMAP_H 1024
25+
26+
class OpenGLText {
27+
28+
private:
29+
GLuint font_tex, vao, buffer, ortho_loc, text_loc, color_loc;
30+
stbtt_packedchar chardata[256];
31+
OpenGLShader shader;
32+
float width, height;
33+
float r, g, b;
34+
35+
void init() {
36+
37+
GLuint program = shader.compile("shaders/text.vertex_shader", "shaders/text.fragment_shader");
38+
39+
ortho_loc = glGetUniformLocation(program, "projection");
40+
text_loc = glGetUniformLocation(program, "font");
41+
color_loc = glGetUniformLocation(program, "font_color");
42+
43+
glGenVertexArrays(1, &vao);
44+
glBindVertexArray(vao);
45+
46+
glGenBuffers(1, &buffer);
47+
glBindBuffer(GL_ARRAY_BUFFER, buffer);
48+
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(GLfloat), NULL, GL_DYNAMIC_DRAW);
49+
50+
glBindVertexArray(0);
51+
}
52+
53+
public:
54+
void loadFont(const std::string& font, float font_size)
55+
{
56+
FILE *file;
57+
if(fopen_s(&file, font.c_str(), "rb")){
58+
std::cout << "No encuentra el archivo: " << font << std::endl;
59+
return;
60+
}
61+
62+
fseek(file, 0, SEEK_END);
63+
long size = ftell(file);
64+
fseek(file, 0, SEEK_SET);
65+
66+
unsigned char* ttf_buffer = new unsigned char[size];
67+
unsigned char* temp_bitmap = new unsigned char[BITMAP_W * BITMAP_H];
68+
69+
fread(ttf_buffer, 1, size, file);
70+
71+
stbtt_pack_context pc;
72+
73+
stbtt_PackBegin(&pc, temp_bitmap, BITMAP_W, BITMAP_H, 0, 1, NULL);
74+
stbtt_PackSetOversampling(&pc, 2, 2);
75+
stbtt_PackFontRange(&pc, ttf_buffer, 0, font_size, 0, 256, chardata);
76+
stbtt_PackEnd(&pc);
77+
78+
//stbi_write_png("font.png", BITMAP_W, BITMAP_H, 1, temp_bitmap, 0);
79+
80+
glGenTextures(1, &font_tex);
81+
glBindTexture(GL_TEXTURE_2D, font_tex);
82+
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_W, BITMAP_H, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
83+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
84+
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
85+
86+
delete[] ttf_buffer;
87+
delete[] temp_bitmap;
88+
89+
fclose(file);
90+
file = NULL;
91+
92+
init();
93+
}
94+
95+
void draw(float x, float y, const std::wstring& text) {
96+
shader.use();
97+
glBindVertexArray(vao);
98+
99+
glUniform3f(color_loc, r, g, b);
100+
101+
glm::mat4 ortho_proj = glm::ortho(0.0f, width, height, 0.0f);
102+
glUniformMatrix4fv(ortho_loc, 1, GL_FALSE, &ortho_proj[0][0]);
103+
104+
glActiveTexture(GL_TEXTURE0);
105+
glBindTexture(GL_TEXTURE_2D, font_tex);
106+
glUniform1i(text_loc, 0);
107+
108+
glEnable(GL_BLEND);
109+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
110+
111+
std::wstring::const_iterator c;
112+
for (c = text.begin(); c != text.end(); c++) {
113+
stbtt_aligned_quad q;
114+
stbtt_GetPackedQuad(chardata, BITMAP_W, BITMAP_H, *c, &x, &y, &q, 1);
115+
116+
const GLfloat vertex[] = {
117+
q.s0, q.t0, q.x0, q.y0,
118+
q.s1, q.t0, q.x1, q.y0,
119+
q.s1, q.t1, q.x1, q.y1,
120+
121+
q.s0, q.t0, q.x0, q.y0,
122+
q.s1, q.t1, q.x1, q.y1,
123+
q.s0, q.t1, q.x0, q.y1
124+
};
125+
126+
glBindBuffer(GL_ARRAY_BUFFER, buffer);
127+
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertex), vertex);
128+
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
129+
glBindBuffer(GL_ARRAY_BUFFER, 0);
130+
glEnableVertexAttribArray(0);
131+
132+
glDrawArrays(GL_TRIANGLES, 0, 6);
133+
}
134+
135+
glDisable(GL_BLEND);
136+
glBindVertexArray(0);
137+
shader.unUse();
138+
}
139+
140+
void setSize(int width, int height) {
141+
this->width = static_cast<float>(width);
142+
this->height = static_cast<float>(height);
143+
}
144+
145+
void setColor(float r, float g, float b) {
146+
this->r = r;
147+
this->g = g;
148+
this->b = b;
149+
}
150+
};
151+
152+
#endif

Readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Tutoriales OpenGL Moderno
2+
Computación gráfica utilizando OpenGL 3.3 o superior.

Tutorial-06/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
file(COPY simple.vertex_shader simple.fragment_shader DESTINATION shaders)
2+
file(COPY text.vertex_shader text.fragment_shader DESTINATION shaders)
3+
file(COPY roboto.ttf DESTINATION font)
4+
5+
include_directories(../includes)
6+
7+
add_executable( Tutorial-06 texto-opengl.cpp
8+
shaders/simple.vertex_shader
9+
shaders/simple.fragment_shader
10+
shaders/text.vertex_shader
11+
shaders/text.fragment_shader
12+
../common/openglwindow.hpp
13+
../common/openglshader.hpp
14+
../common/opengltext.hpp )
15+
16+
target_link_libraries( Tutorial-06 ${GRAPHIC_LIBS} )

Tutorial-06/Roboto.ttf

134 KB
Binary file not shown.

Tutorial-06/Texto-OpenGL.cpp

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#include "OpenGLWindow.hpp"
2+
#include "OpenGLShader.hpp"
3+
#include "OpenGLText.hpp"
4+
#include <glm/gtc/matrix_transform.hpp>
5+
#include <sstream>
6+
7+
class Tutorial_03 : public OpenGLWindow {
8+
9+
public:
10+
Tutorial_03() : vao{}, buffer{}, index_buffer{}, MatrixID{} { }
11+
12+
private:
13+
void onstart() override {
14+
15+
glEnable(GL_DEPTH_TEST);
16+
17+
// crear, compilar y enlasar el Vertex y Fragment Shader
18+
GLuint program = shader_simple.compile("shaders/simple.vertex_shader", "shaders/simple.fragment_shader");
19+
20+
// Obtener el ID del uniform llamado "MVP"
21+
MatrixID = glGetUniformLocation(program, "MVP");
22+
23+
// crear y enlazar un vao
24+
glGenVertexArrays(1, &vao);
25+
glBindVertexArray(vao);
26+
27+
// vetices para generar un cubo 3D
28+
static const float vertex[] =
29+
{
30+
1.0f, -1.0f, -1.0f, 1.0f,
31+
1.0f, -1.0f, 1.0f, 1.0f,
32+
-1.0f, -1.0f, 1.0f, 1.0f,
33+
-1.0f, -1.0f, -1.0f, 1.0f,
34+
1.0f, 1.0f, -1.0f, 1.0f,
35+
1.0f, 1.0f, 1.0f, 1.0f,
36+
-1.0f, 1.0f, 1.0f, 1.0f,
37+
-1.0f, 1.0f, -1.0f, 1.0f
38+
};
39+
40+
// componetes RGBA para los colores de cada vertice
41+
static const float color[] =
42+
{
43+
1.0f, 0.0f, 0.0f, 1.0f,
44+
0.0f, 1.0f, 0.0f, 1.0f,
45+
0.0f, 0.0f, 1.0f, 1.0f,
46+
1.0f, 0.0f, 0.0f, 1.0f,
47+
0.0f, 1.0f, 0.0f, 1.0f,
48+
1.0f, 0.0f, 0.0f, 1.0f,
49+
0.0f, 1.0f, 0.0f, 1.0f,
50+
0.0f, 0.0f, 1.0f, 1.0f
51+
};
52+
53+
// indices usados para unir los vertices que componen el cubo
54+
static const GLushort indices[] =
55+
{
56+
0, 1, 2,
57+
7, 6, 5,
58+
4, 5, 1,
59+
5, 6, 2,
60+
6, 7, 3,
61+
0, 3, 7,
62+
3, 0, 2,
63+
4, 7, 5,
64+
0, 4, 1,
65+
1, 5, 2,
66+
2, 6, 3,
67+
4, 0, 7
68+
};
69+
70+
// generar, almacenar el buffer de indices
71+
glGenBuffers(1, &index_buffer);
72+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
73+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
74+
75+
// generar dos ids para los buffer
76+
glGenBuffers(2, buffer);
77+
78+
// enlazar el buffer de vertices
79+
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
80+
// almacenar datos en el buffer de vertices
81+
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
82+
83+
// describir los datos y activar vPosition (location = 0)
84+
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
85+
glEnableVertexAttribArray(0);
86+
87+
// enlazar el buffer de color
88+
glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
89+
// almacenar datos en el buffer de color
90+
glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);
91+
92+
// describir los datos y activar vColor (location = 1)
93+
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL);
94+
glEnableVertexAttribArray(1);
95+
96+
// Inicializar Fuente TrueType
97+
text.loadFont("font/roboto.ttf", 48);
98+
text.setSize(1280, 768);
99+
}
100+
101+
void onrender(double time) override {
102+
glClearColor(0.25f, 0.55f, 0.55f, 1.0f);
103+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
104+
105+
// Usar el shader
106+
shader_simple.use();
107+
glBindVertexArray(vao);
108+
109+
// Matriz de modelo, se aplica una rotacion sobre el eje Y
110+
glm::mat4 Model;
111+
Model = glm::rotate(Model, (float)time, glm::vec3(0.0f, 1.0f, 0.0f));
112+
113+
// Matriz de proyeccion y visualizacion
114+
glm::mat4 Projection = glm::perspective(45.0f, aspect_ratio, 0.1f, 100.0f);
115+
glm::mat4 View = glm::lookAt(glm::vec3(4, 3, -3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0));
116+
117+
// Crear la matriz total MVP
118+
glm::mat4 MVP = Projection * View * Model;
119+
120+
// Enviar las tranformaciones al shader
121+
// MatrixID es el ID del uniform MVP obtenida por glGetUniformLocation(program, "MVP");
122+
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
123+
124+
// Dibujar cubo usando los indices almacenados en el buffer,
125+
// 1 triangulo = 3 indices, 1 cara = 2 triangulos, 1 cubo = 6 caras.
126+
// 3 * 2 * 6 = 36 indices a dibujar
127+
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
128+
129+
glBindVertexArray(0);
130+
shader_simple.unUse();
131+
132+
// Dibujar Texto 2D
133+
draw_text(time);
134+
}
135+
136+
void draw_text(double time) {
137+
std::wostringstream str;
138+
str.precision(2);
139+
str.setf(std::ios::fixed);
140+
str << "Time: " << time << " ms.";
141+
142+
// Establecer color y dibujar texto en la ubicacion indicada.
143+
text.setColor(0.15f, 0.3f, 0.7f);
144+
text.draw(10, 60, L"Tutor de Programación - Render Text 2D");
145+
146+
// Establecer color y dibujar texto en la ubicacion indicada.
147+
text.setColor(0.3f, 0.3f, 0.3f);
148+
text.draw(10, 120, str.str());
149+
}
150+
151+
// Liberar memoria usada por los buffers
152+
void onstop() override {
153+
glDeleteBuffers(2, buffer);
154+
glDeleteBuffers(1, &index_buffer);
155+
glDeleteVertexArrays(1, &vao);
156+
}
157+
158+
OpenGLText text;
159+
OpenGLShader shader_simple;
160+
GLuint vao, index_buffer;
161+
GLuint buffer[2];
162+
GLuint MatrixID;
163+
};
164+
165+
int main() {
166+
Tutorial_03 win_app;
167+
if (win_app.init("OpenGL Moderno - Render Text 2D", 1280, 720)) {
168+
win_app.info();
169+
win_app.run();
170+
}
171+
return 0;
172+
}

Tutorial-06/simple.fragment_shader

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#version 330 core
2+
3+
in vec4 color;
4+
out vec4 fColor;
5+
6+
void main()
7+
{
8+
fColor = color;
9+
}

Tutorial-06/simple.vertex_shader

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#version 330 core
2+
3+
layout (location = 0) in vec4 vPosition;
4+
layout (location = 1) in vec4 vColor;
5+
6+
uniform mat4 MVP;
7+
8+
out vec4 color;
9+
10+
void main()
11+
{
12+
gl_Position = MVP * vPosition;
13+
color = vColor;
14+
}

0 commit comments

Comments
 (0)