Prepare OpenGL text rendering state only once
Date: Sun Jan 7 17:55:38 2024 +0100
This commit is contained in:
parent
3b78739efd
commit
85195590aa
1 changed files with 57 additions and 23 deletions
80
main.cpp
80
main.cpp
|
|
@ -118,6 +118,7 @@ uint32_t hex_program;
|
||||||
uint32_t texture_array;
|
uint32_t texture_array;
|
||||||
glm::mat4 transforms[ARRAY_LIMIT];
|
glm::mat4 transforms[ARRAY_LIMIT];
|
||||||
int32_t letter_map[ARRAY_LIMIT];
|
int32_t letter_map[ARRAY_LIMIT];
|
||||||
|
int32_t text_frame_idx;
|
||||||
|
|
||||||
|
|
||||||
// error processing
|
// error processing
|
||||||
|
|
@ -240,27 +241,47 @@ uint32_t make_gl_program(const char *pathname_vertex, const char *pathname_fragm
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_text(const char *text, float x, float y, float scale, glm::vec3 color)
|
void render_queued_text(glm::vec3 color)
|
||||||
|
{
|
||||||
|
//glActiveTexture(GL_TEXTURE0);
|
||||||
|
//glBindTexture(GL_TEXTURE_2D_ARRAY, texture_array);
|
||||||
|
//glBindVertexArray(textvao);
|
||||||
|
//glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
||||||
|
|
||||||
|
glUniform3f(glGetUniformLocation(text_program, "text_color"), color.x, color.y, color.z);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(text_program, "transforms"), text_frame_idx, GL_FALSE, &transforms[0][0][0]);
|
||||||
|
glUniform1iv(glGetUniformLocation(text_program, "letter_map"), text_frame_idx, &letter_map[0]);
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, text_frame_idx);
|
||||||
|
|
||||||
|
//glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
//glBindVertexArray(0);
|
||||||
|
//glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
text_frame_idx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_text(const char *text, float x, float y, float scale, glm::vec3 color, bool render_immediately)
|
||||||
{
|
{
|
||||||
// TODO: Group draw calls together instead of doing 1 draw call/character. Use an atlas with GL_TEXTURE_ARRAY
|
// TODO: Group draw calls together instead of doing 1 draw call/character. Use an atlas with GL_TEXTURE_ARRAY
|
||||||
// Take tips from https://www.youtube.com/watch?v=S0PyZKX4lyI
|
// Take tips from https://www.youtube.com/watch?v=S0PyZKX4lyI
|
||||||
scale *= 48.0f/256;
|
scale *= 48.0f/256;
|
||||||
|
|
||||||
// activate corresponding render state
|
// activate corresponding render state
|
||||||
glUseProgram(text_program);
|
|
||||||
glUniform3f(glGetUniformLocation(text_program, "text_color"), color.x, color.y, color.z);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_array);
|
|
||||||
glBindVertexArray(textvao);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
|
||||||
|
|
||||||
int idx = 0;
|
//glUseProgram(text_program);
|
||||||
|
//glActiveTexture(GL_TEXTURE0);
|
||||||
|
//glBindTexture(GL_TEXTURE_2D_ARRAY, texture_array);
|
||||||
|
//glBindVertexArray(textvao);
|
||||||
|
//glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
||||||
|
|
||||||
// iterate through 128 ASCI characters
|
// iterate through 128 ASCI characters
|
||||||
for (const char *p = text; *p != '\0'; ++p)
|
for (const char *p = text; *p != '\0'; ++p)
|
||||||
{
|
{
|
||||||
// Avoid drawing more than 400 chars at a time
|
// Avoid drawing more than ARRAY_LIMIT chars at a time
|
||||||
if (idx == ARRAY_LIMIT - 1)
|
if (text_frame_idx == ARRAY_LIMIT)
|
||||||
break;
|
{
|
||||||
|
render_queued_text(color);
|
||||||
|
}
|
||||||
|
|
||||||
char c = *p;
|
char c = *p;
|
||||||
charglyph_t charglyph = glyphmap[(size_t)c];
|
charglyph_t charglyph = glyphmap[(size_t)c];
|
||||||
|
|
@ -274,20 +295,21 @@ void render_text(const char *text, float x, float y, float scale, glm::vec3 colo
|
||||||
float xpos = x + charglyph.bearing.x * scale;
|
float xpos = x + charglyph.bearing.x * scale;
|
||||||
float ypos = y - (256 - charglyph.bearing.y) * scale;
|
float ypos = y - (256 - charglyph.bearing.y) * scale;
|
||||||
|
|
||||||
transforms[idx] = glm::translate(glm::mat4(1.0f), glm::vec3(xpos, ypos, 0)) * glm::scale(glm::mat4(1.0f), glm::vec3(256 * scale, 256 * scale, 0));
|
transforms[text_frame_idx] = glm::translate(glm::mat4(1.0f), glm::vec3(xpos, ypos, 0)) * glm::scale(glm::mat4(1.0f), glm::vec3(256 * scale, 256 * scale, 0));
|
||||||
letter_map[idx] = charglyph.tex;
|
letter_map[text_frame_idx] = charglyph.tex;
|
||||||
|
|
||||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||||
x += (charglyph.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
x += (charglyph.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
||||||
++idx;
|
++text_frame_idx;
|
||||||
|
}
|
||||||
|
if (render_immediately)
|
||||||
|
{
|
||||||
|
render_queued_text(color);
|
||||||
}
|
}
|
||||||
glUniformMatrix4fv(glGetUniformLocation(text_program, "transforms"), idx, GL_FALSE, &transforms[0][0][0]);
|
|
||||||
glUniform1iv(glGetUniformLocation(text_program, "letter_map"), idx, &letter_map[0]);
|
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, idx);
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindVertexArray(0);
|
// glBindVertexArray(0);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
// glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inside_hex(hex_t *hex, glm::vec2 point)
|
bool inside_hex(hex_t *hex, glm::vec2 point)
|
||||||
|
|
@ -654,8 +676,15 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv)
|
||||||
static char debug_text_buf[256];
|
static char debug_text_buf[256];
|
||||||
{
|
{
|
||||||
TIME_BLOCK(text_render);
|
TIME_BLOCK(text_render);
|
||||||
|
// Prepare GL state for text rendering
|
||||||
|
glUseProgram(text_program);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_array);
|
||||||
|
glBindVertexArray(textvao);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
||||||
|
|
||||||
stbsp_snprintf(debug_text_buf, 256, "Cursor position %.0f %.0f screen %.2f %.2f world", cursor_x, cursor_y, cursor_world.x, cursor_world.y);
|
stbsp_snprintf(debug_text_buf, 256, "Cursor position %.0f %.0f screen %.2f %.2f world", cursor_x, cursor_y, cursor_world.x, cursor_world.y);
|
||||||
render_text(debug_text_buf, 25, 25, .5f, glm::vec3(1.0f, 1.0f, 1.0f));
|
render_text(debug_text_buf, 25, 25, .5f, glm::vec3(1.0f, 1.0f, 1.0f), true);
|
||||||
|
|
||||||
for (int i = 0; show_hex_numbers && i < grid.rows * grid.columns; ++i)
|
for (int i = 0; show_hex_numbers && i < grid.rows * grid.columns; ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -671,14 +700,19 @@ int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv)
|
||||||
continue;
|
continue;
|
||||||
char number_string[11];
|
char number_string[11];
|
||||||
stbsp_snprintf(number_string, 11, "%d", i);
|
stbsp_snprintf(number_string, 11, "%d", i);
|
||||||
render_text(number_string, v.x, v.y, .2f + (0.3f / the_camera.size.x), glm::vec3(0.0f, 0.0f, 0.0f));
|
render_text(number_string, v.x, v.y, .2f + (0.3f / the_camera.size.x), glm::vec3(0.0f, 0.0f, 0.0f), false);
|
||||||
}
|
}
|
||||||
|
render_queued_text(glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
if (hovered_hex != -1)
|
if (hovered_hex != -1)
|
||||||
{
|
{
|
||||||
char buf[30];
|
char buf[30];
|
||||||
stbsp_snprintf(buf, 30, "Cursor INSIDE hex %d", hovered_hex);
|
stbsp_snprintf(buf, 30, "Cursor INSIDE hex %d", hovered_hex);
|
||||||
render_text(buf, 25.0f, window_height - 25.0f, .5f, glm::vec3(1.0f, 1.0f, 1.0f));
|
render_text(buf, 25.0f, window_height - 25.0f, .5f, glm::vec3(1.0f, 1.0f, 1.0f), true);
|
||||||
}
|
}
|
||||||
|
// Restore GL state
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue