Почему не работают функции новой OpenGL (с GLUT), хотя старые работают?
Скачал код с одного сайта (см. ниже), подключил все библиотеки, но VS выдает ошибки:
Идентификатор "glBindVertexArray" не определен
Идентификатор "glActiveTexture" не определен
Идентификатор "GL_TEXTURE0" не определен
и др.
Причем функции старого OpenGL не выдают ошибок. Я так понял, что проблема в том, что мой код использует стандартный OpenGL от винды (GL 1.1), но как это исправить я не понял.
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <GL/glut.h>
#include <glm.hpp>
#include <freetype/freetype.h>
class Text
{
private:
struct Alphabet_Characters
{
float left_bearing = 0.0f;
float bottom_bearing = 0.0f;
float height_plus_padding = 0.0f;
float width_plus_padding = 0.0f;
float glyph_advance_x = 0.0f;
char character;
glm::vec2 texcoord_top_left;
glm::vec2 texcoord_top_right;
glm::vec2 texcoord_bottom_left;
glm::vec2 texcoord_bottom_right;
};
struct Message_Characters
{
glm::vec4 bottom_left_tr1; // Triangle 1
glm::vec4 bottom_right_tr1;
glm::vec4 top_left_tr1;
glm::vec4 top_left_tr2; // Triangle 2
glm::vec4 top_right_tr2;
glm::vec4 bottom_right_tr2;
};
struct Message_Parent
{
unsigned VAO_message, VBO_message, VAO_alphabet, VBO_alphabet;
unsigned alphabet_texture;
bool draw_alphabet = true;
bool dynamic_static = false;
size_t allocated_memory_bytes = 0;
int font_size = 10;
int tallest_font_height = 0;
int relative_distance = 0;
int alphabet_texture_width = 0;
int alphabet_texture_height = 0;
float alphabet_start_x = -0.80f; // These are set here in OpenGL [-1, 1] coordinate range.
float alphabet_start_y = -0.45f;
float text_start_x = 0.0f;
float text_start_y = 0.0f;
std::string message_string;
std::vector<Alphabet_Characters> alphabet_vec;
Message_Characters alphabet_quad;
std::vector<Message_Characters> characters_quads;
std::vector<float> start_x_current;
std::string font_path;
};
// --------------------------------
std::string alphabet_string;
FT_Library& free_type;
FT_GlyphSlot glyph; // "glyph" (FT_GlyphSlot) is simply being used as shorthand for "face" (FT_Face) ->glyph... set in: set_font_parameters()
float scale_pixels_x_to_OpenGL = 0.0f; // OpenGL [-1, 1] (i.e. 2) divided by the number of screen pixels.
float scale_pixels_y_to_OpenGL = 0.0f;
int character_row_limit = 15; // Alphabet character row limit.
int alphabet_padding = 7; // Padding is optional (it spaces out the alphabet characters, without affecting each message's character spacing)
// Note: if character background is slightly opaque e.g. 0.1 = vec4(1, 1, 1, texture(text_Texture, texture_coordinates).r) + 0.1, then spaces, i.e. simply " " show as a: alphabet_padding * alphabet_padding square.
public:
FT_Face face; // Resources are freed in main() via FT_Done_Face(...)
std::vector<Message_Parent> messages;
Text(FT_Library& free_type, int window_width, int window_height, std::string alphabet_string) : free_type(free_type)
{
this->alphabet_string = alphabet_string;
scale_pixels_x_to_OpenGL = 2.0f / window_width; // Scale vertex data to render on-screen the same size as the font's set pixel-size...
scale_pixels_y_to_OpenGL = 2.0f / window_height; // This makes the text display at the same correct pixel size, regardless of the window size.
}
void create_text_message(std::string message, int text_start_x, int text_start_y, std::string font_path, int font_size, bool dynamic_static)
{
int alphabet_detected = -1;
for (int i = 0; i < messages.size(); ++i)
{
if (messages[i].font_size == font_size && messages[i].font_path == font_path)
{
alphabet_detected = i;
break;
}
}
Message_Parent new_message; // Changed by reference during most of the below function calls.
new_message.font_size = font_size;
new_message.font_path = font_path;
if (alphabet_detected == -1) // Create new alphabet.
{
std::cout << "\n\n New alphabet created (characters are listed below) --- Font path: " << font_path << " --- Font size: " << font_size;
set_font_parameters(new_message);
create_blank_texture(new_message);
calculate_alphabet_image_size(new_message);
format_alphabet_texture_image(new_message);
create_alphabet_image_quad(new_message);
set_buffer_data_alphabet(new_message);
}
else // Copy the existing alphabet.
{
new_message.draw_alphabet = false;
new_message.alphabet_vec = messages[alphabet_detected].alphabet_vec;
new_message.alphabet_texture = messages[alphabet_detected].alphabet_texture;
new_message.alphabet_texture_width = messages[alphabet_detected].alphabet_texture_width;
new_message.alphabet_texture_height = messages[alphabet_detected].alphabet_texture_height;
new_message.tallest_font_height = messages[alphabet_detected].tallest_font_height;
new_message.relative_distance = messages[alphabet_detected].relative_distance;
std::cout << "\n\n Existing alphabet detected (no new alphabet is required) --- Font path: " << font_path << " --- Font size: " << font_size << "\n";
}
new_message.message_string = message;
process_text_compare(new_message, text_start_x, text_start_y); // process_text_index(...) is called within this function call.
new_message.dynamic_static = dynamic_static; // True = dynamic.
initialise_buffer_data_message(new_message); // Initialise the message's buffer data.
update_buffer_data_message(new_message, 0); // Update the message's buffer data.
messages.push_back(new_message); // Add the new message to the list of messages.
}
void draw_alphabets()
{
for (unsigned i = 0; i < messages.size(); ++i)
{
if (messages[i].draw_alphabet)
{
glBindVertexArray(messages[i].VAO_alphabet);
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, messages[i].alphabet_texture);
glDisable(GL_DEPTH_TEST);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(0);
// std::cout << "\n Drawing alphabet... messages index: " << i;
}
}
}
void draw_messages()
{
for (unsigned i = 0; i < messages.size(); ++i)
{
glBindVertexArray(messages[i].VAO_message);
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, messages[i].alphabet_texture);
glDisable(GL_DEPTH_TEST); // Cast (unsigned) used below, silences the compiler warning (unsigned 32 bit is still over 4 billion)
glDrawArrays(GL_TRIANGLES, 0, (unsigned)messages[i].characters_quads.size() * 6);
glEnable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(0);
}
}
void draw_messages(unsigned message_index)
{
if (message_index > messages.size() - 1)
{
std::cout << "\n Warning: draw_messages(...) --- 'message_index' is greater than 'messages.size() - 1'\n";
int keep_console_open;
std::cin >> keep_console_open;
}
else
{
glBindVertexArray(messages[message_index].VAO_message);
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, messages[message_index].alphabet_texture);
glDisable(GL_DEPTH_TEST); // Cast (unsigned) used below, silences the compiler warning (unsigned 32 bit is still over 4 billion)
glDrawArrays(GL_TRIANGLES, 0, (unsigned)messages[message_index].characters_quads.size() * 6);
glEnable(GL_DEPTH_TEST);
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(0);
}
}
void process_text_index(Message_Parent& new_message, unsigned index, float advanced_current)
{
// Y-Values (by default the characters are bottom aligned) ("new_message.text_start_x & text_start_y" are set in: process_text_compare(...))
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
float bottom_bearing = new_message.alphabet_vec[index].bottom_bearing;
float y_pos_aligned = new_message.text_start_y - bottom_bearing;
float height = new_message.alphabet_vec[index].height_plus_padding;
float texcoord_top_left_y = new_message.alphabet_vec[index].texcoord_top_left.y;
float texcoord_bottom_right_y = new_message.alphabet_vec[index].texcoord_bottom_right.y;
float texcoord_top_right_y = new_message.alphabet_vec[index].texcoord_top_right.y;
float texcoord_bottom_left_y = new_message.alphabet_vec[index].texcoord_bottom_left.y;
// X-Values
// -----------
float start_x_current = new_message.text_start_x + advanced_current;
float left_bearing = new_message.alphabet_vec[index].left_bearing;
float width = new_message.alphabet_vec[index].width_plus_padding;
float texcoord_bottom_left_x = new_message.alphabet_vec[index].texcoord_bottom_left.x;
float texcoord_bottom_right_x = new_message.alphabet_vec[index].texcoord_bottom_right.x;
float texcoord_top_left_x = new_message.alphabet_vec[index].texcoord_top_left.x;
float texcoord_top_right_x = new_message.alphabet_vec[index].texcoord_top_right.x;
Message_Characters quad{};
// Triangle 1
// -------------
quad.bottom_left_tr1.x = start_x_current + left_bearing;
// Used for replacing characters from some index position, to the end of the full message length
// ---------------------------------------------------------------------------------------------------------------------------
new_message.start_x_current.push_back(start_x_current); // Record the character's start position... but excluding: left_bearing
quad.bottom_left_tr1.y = y_pos_aligned;
quad.bottom_left_tr1.z = texcoord_bottom_left_x;
quad.bottom_left_tr1.w = texcoord_top_left_y; // Y-axis texture coordinates are reversed.
quad.bottom_right_tr1.x = start_x_current + left_bearing + width;
quad.bottom_right_tr1.y = y_pos_aligned;
quad.bottom_right_tr1.z = texcoord_bottom_right_x;
quad.bottom_right_tr1.w = texcoord_top_right_y;
quad.top_left_tr1.x = start_x_current + left_bearing;
quad.top_left_tr1.y = y_pos_aligned + height;
quad.top_left_tr1.z = texcoord_top_left_x;
quad.top_left_tr1.w = texcoord_bottom_left_y;
// Triangle 2
// -------------
quad.top_left_tr2.x = start_x_current + left_bearing;
quad.top_left_tr2.y = y_pos_aligned + height;
quad.top_left_tr2.z = texcoord_top_left_x;
quad.top_left_tr2.w = texcoord_bottom_left_y;
quad.top_right_tr2.x = start_x_current + left_bearing + width;
quad.top_right_tr2.y = y_pos_aligned + height;
quad.top_right_tr2.z = texcoord_top_right_x;
quad.top_right_tr2.w = texcoord_bottom_right_y;
quad.bottom_right_tr2.x = start_x_current + left_bearing + width;
quad.bottom_right_tr2.y = y_pos_aligned;
quad.bottom_right_tr2.z = texcoord_bottom_right_x;
quad.bottom_right_tr2.w = texcoord_top_right_y;
// --------------------------------------------------------------
// std::cout << "\n CHARACTER: " << new_message.message_string.c_str()[index] << " --- start_x_current: " << start_x_current << " --- y_pos_aligned: " << y_pos_aligned << " --- width: " << width << " --- height: " << height;
// std::cout << "\n texcoord_top_left_x: " << texcoord_top_left_x;
// std::cout << "\n texcoord_top_right_x: " << texcoord_top_right_x << "\n";
new_message.characters_quads.push_back(quad);
}
void update_buffer_data_message(Message_Parent& new_message, int characters_offset)
{
glBindVertexArray(new_message.VAO_message);
glBindBuffer(GL_ARRAY_BUFFER, new_message.VBO_message);
GLintptr data_offset_bytes = (GLintptr)characters_offset * 6 * 4 * sizeof(float);
GLsizeiptr replace_size_bytes = (new_message.characters_quads.size() * 6 * 4 * sizeof(float)) - data_offset_bytes;
if (data_offset_bytes + replace_size_bytes > (unsigned)new_message.allocated_memory_bytes)
{
std::cout << "\n Warning: update_buffer_data_message(...) --- 'data_offset_bytes' " << data_offset_bytes << " + 'replace_size_bytes' " << replace_size_bytes << " was too large for 'allocated_memory_bytes' "
<< new_message.allocated_memory_bytes << " --- so 'replace_size_bytes' has been reduced to: ";
replace_size_bytes -= (data_offset_bytes + replace_size_bytes) - new_message.allocated_memory_bytes;
std::cout << replace_size_bytes;
}
if (data_offset_bytes + replace_size_bytes < (unsigned)new_message.allocated_memory_bytes)
{
std::cout << "\n Warning: update_buffer_data_message(...) --- 'data_offset_bytes' " << data_offset_bytes << " + 'replace_size_bytes' " << replace_size_bytes << " is less than 'allocated_memory_bytes' "
<< new_message.allocated_memory_bytes << " --- so 'characters_offset' " << characters_offset << " has been reduced to: ";
characters_offset -= (int)((new_message.allocated_memory_bytes - (data_offset_bytes + replace_size_bytes)) / 6 / 4 / sizeof(float));
std::cout << characters_offset;
}
int keep_console_open;
if (characters_offset == -1)
std::cin >> keep_console_open;
glBufferSubData(GL_ARRAY_BUFFER, data_offset_bytes, replace_size_bytes, &new_message.characters_quads[characters_offset]);
glBindVertexArray(0);
}
private:
void set_font_parameters(Message_Parent new_message)
{
FT_Error error_code{};
int keep_console_open;
error_code = FT_New_Face(free_type, new_message.font_path.c_str(), 0, &face);
if (error_code)
{
std::cout << "\n\n Error code: " << error_code << " --- " << "Could not open font: " << new_message.font_path.c_str();
std::cin >> keep_console_open;
}
error_code = FT_Set_Pixel_Sizes(face, 0, new_message.font_size);
if (error_code)
{
std::cout << "\n\n Error code: " << error_code << " --- " << "Could not set font pixel size : " << new_message.font_size;
std::cin >> keep_console_open;
}
glyph = face->glyph; // Shorthand for "face->glyph"
}
void create_blank_texture(Message_Parent& new_message)
{
glGenTextures(1, &new_message.alphabet_texture);
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, new_message.alphabet_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // GL_NEAREST... GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glActiveTexture(GL_TEXTURE0);
}
void calculate_alphabet_image_size(Message_Parent& new_message)
{
FT_Error error_code{};
int curr_row_width = 0;
int max_row_width = 0;
int number_of_rows = 1;
int character_count = 0;
new_message.tallest_font_height = 0;
for (unsigned i = 0; i < alphabet_string.size(); i++)
{
error_code = FT_Load_Char(face, alphabet_string[i], FT_LOAD_RENDER);
if (error_code)
{
std::cout << "\n\n Error code: " << error_code << " --- " << "Could not load character: " << alphabet_string[i];
int keep_console_open;
std::cin >> keep_console_open;
}
if ((signed)glyph->bitmap.rows > new_message.tallest_font_height)
new_message.tallest_font_height = glyph->bitmap.rows;
curr_row_width += glyph->bitmap.width + alphabet_padding * 2;
++character_count;
if (character_count == character_row_limit)
{
character_count = 0;
++number_of_rows;
if (curr_row_width > max_row_width)
max_row_width = curr_row_width;
curr_row_width = 0;
}
new_message.alphabet_texture_width = (curr_row_width > max_row_width) ? curr_row_width : max_row_width;
// std::cout << "\n\n alphabet_texture_width: " << alphabet_texture_width;
}
new_message.alphabet_texture_height = number_of_rows * (new_message.tallest_font_height + alphabet_padding * 2);
std::cout << "\n\n alphabet_texture_width: " << new_message.alphabet_texture_width
<< " --- alphabet_texture_height: " << new_message.alphabet_texture_height << "\n";
}
void format_alphabet_texture_image(Message_Parent& new_message)
{
glActiveTexture(GL_TEXTURE31);
glBindTexture(GL_TEXTURE_2D, new_message.alphabet_texture);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Initialise empty data: https://stackoverflow.com/questions/7195130/how-to-efficiently-initialize-texture-with-zeroes
std::vector<GLubyte> empty_data(new_message.alphabet_texture_width * new_message.alphabet_texture_height, 0); // GL_RED = 8 bits = 1 byte.
// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
// "Each element is a single red component. OpenGL converts it to floating point and assembles it to RGBA, by attaching 0 for green and blue, and 1 for alpha. Each component is clamped to the range [0, 1]"
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, new_message.alphabet_texture_width, new_message.alphabet_texture_height, 0, GL_RED, GL_UNSIGNED_BYTE, &empty_data[0]);
int character_count = 0;
int increment_x = alphabet_padding;
int increment_y = alphabet_padding;
new_message.relative_distance = new_message.tallest_font_height; // Set relative distance to initial value.
for (unsigned i = 0; i < alphabet_string.size(); ++i)
{
FT_Load_Char(face, alphabet_string[i], FT_LOAD_RENDER); // "glyph" as used below... is shorthand for "face->glyph"
int tex_coord_left = increment_x - alphabet_padding;
glTexSubImage2D(GL_TEXTURE_2D, 0, increment_x, increment_y, glyph->bitmap.width, glyph->bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, glyph->bitmap.buffer); // Apply 1 character at a time to the texture.
int tex_coord_right = increment_x + glyph->bitmap.width + alphabet_padding;
int tex_coord_bottom = increment_y - alphabet_padding;
int tex_coord_top = increment_y + glyph->bitmap.rows + alphabet_padding;
increment_x += glyph->bitmap.width + (alphabet_padding * 2);
// By default the characters are bottom aligned (Note: bitmap_top = the "Remaining Distance" above that bottom alignment, after having been moved downwards by "bottom_bearing" to produce character-origin alignment)
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
if (new_message.relative_distance > new_message.tallest_font_height - glyph->bitmap_top)
new_message.relative_distance = new_message.tallest_font_height - glyph->bitmap_top; // Record the smallest... Tallest Font - "Remaining Distance" (incidentally, the tallest font is also checked against itself by doing this)
// FT_GlyphSlotRec: https://freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_glyphslotrec (Also available: https://freetype.org/freetype2/docs/reference/ft2-base_interface.html#ft_glyph_metrics)
// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Alphabet_Characters alphabet_character{};
alphabet_character.glyph_advance_x = (glyph->advance.x / 64) * scale_pixels_x_to_OpenGL;
// The values below are in pixels... FT_Bitmap: https://freetype.org/freetype2/docs/reference/ft2-basic_types.html#ft_bitmap
// --------------------------------------------------------------------------------------------------------------------------------------------------------------------
alphabet_character.left_bearing = glyph->bitmap_left * scale_pixels_x_to_OpenGL;
alphabet_character.width_plus_padding = (tex_coord_right - tex_coord_left) * scale_pixels_x_to_OpenGL;
alphabet_character.bottom_bearing = ((int)glyph->bitmap.rows - (int)glyph->bitmap_top) * scale_pixels_y_to_OpenGL;
alphabet_character.height_plus_padding = (tex_coord_top - tex_coord_bottom) * scale_pixels_y_to_OpenGL;
alphabet_character.character = alphabet_string[i];
std::cout << "\n CHARACTER: " << alphabet_string[i] << "\n glyph->advance.x: " << glyph->advance.x << "\n glyph->advance.x / 64: " << glyph->advance.x / 64
<< "\n glyph->bitmap_left: " << glyph->bitmap_left << "\n glyph->bitmap.width: " << glyph->bitmap.width << "\n glyph->bitmap.rows: " << glyph->bitmap.rows
<< "\n bottom bearing (height - top): " << (int)glyph->bitmap.rows - (int)glyph->bitmap_top << "\n top bearing (bitmap_top): " << glyph->bitmap_top << "\n";
// Texture Coordinates Section (divide texture coordinate position values by texture size to get range [0, 1])
// ------------------------------------------------------------------------------------------------------------------------------------------
alphabet_character.texcoord_top_left.x = (float)tex_coord_left / (float)new_message.alphabet_texture_width;
alphabet_character.texcoord_top_left.y = (float)(tex_coord_top) / (float)new_message.alphabet_texture_height;
alphabet_character.texcoord_top_right.x = (float)(tex_coord_right) / (float)new_message.alphabet_texture_width;
alphabet_character.texcoord_top_right.y = (float)(tex_coord_top) / (float)new_message.alphabet_texture_height;
alphabet_character.texcoord_bottom_left.x = (float)(tex_coord_left) / (float)new_message.alphabet_texture_width;
alphabet_character.texcoord_bottom_left.y = (float)(tex_coord_bottom) / (float)new_message.alphabet_texture_height;
alphabet_character.texcoord_bottom_right.x = (float)(tex_coord_right) / (float)new_message.alphabet_texture_width;
alphabet_character.texcoord_bottom_right.y = (float)(tex_coord_bottom) / (float)new_message.alphabet_texture_height;
new_message.alphabet_vec.push_back(alphabet_character); // Used in: process_text_compare()
++character_count;
if (character_count == character_row_limit)
{
character_count = 0;
increment_y += new_message.tallest_font_height + (alphabet_padding * 2);
increment_x = alphabet_padding;
}
}
glActiveTexture(GL_TEXTURE0);
}
void create_alphabet_image_quad(Message_Parent& new_message)
{
float x = new_message.alphabet_start_x;
float y = new_message.alphabet_start_y;
float width = new_message.alphabet_texture_width * scale_pixels_x_to_OpenGL;
float height = new_message.alphabet_texture_height * scale_pixels_y_to_OpenGL;
float margin = 50 * scale_pixels_x_to_OpenGL; // Display each alphabet to the right of the previous one.
if (messages.size() > 0)
{
x = messages[messages.size() - 1].alphabet_start_x + (messages[messages.size() - 1].alphabet_texture_width * scale_pixels_x_to_OpenGL) + margin;
new_message.alphabet_start_x = x;
}
// Triangle 1
// -------------
new_message.alphabet_quad.bottom_left_tr1.x = x;
new_message.alphabet_quad.bottom_left_tr1.y = y;
new_message.alphabet_quad.bottom_left_tr1.z = 0.0f;
new_message.alphabet_quad.bottom_left_tr1.w = 1.0f;
new_message.alphabet_quad.bottom_right_tr1.x = x + width;
new_message.alphabet_quad.bottom_right_tr1.y = y;
new_message.alphabet_quad.bottom_right_tr1.z = 1.0f;
new_message.alphabet_quad.bottom_right_tr1.w = 1.0f;
new_message.alphabet_quad.top_left_tr1.x = x;
new_message.alphabet_quad.top_left_tr1.y = y + height;
new_message.alphabet_quad.top_left_tr1.z = 0.0f;
new_message.alphabet_quad.top_left_tr1.w = 0.0f;
// Triangle 2
// -------------
new_message.alphabet_quad.top_left_tr2.x = x;
new_message.alphabet_quad.top_left_tr2.y = y + height;
new_message.alphabet_quad.top_left_tr2.z = 0.0f;
new_message.alphabet_quad.top_left_tr2.w = 0.0f;
new_message.alphabet_quad.top_right_tr2.x = x + width;
new_message.alphabet_quad.top_right_tr2.y = y + height;
new_message.alphabet_quad.top_right_tr2.z = 1.0f;
new_message.alphabet_quad.top_right_tr2.w = 0.0f;
new_message.alphabet_quad.bottom_right_tr2.x = x + width;
new_message.alphabet_quad.bottom_right_tr2.y = y;
new_message.alphabet_quad.bottom_right_tr2.z = 1.0f;
new_message.alphabet_quad.bottom_right_tr2.w = 1.0f;
}
void set_buffer_data_alphabet(Message_Parent& new_message)
{
glGenVertexArrays(1, &new_message.VAO_alphabet);
glGenBuffers(1, &new_message.VBO_alphabet);
glBindVertexArray(new_message.VAO_alphabet);
glBindBuffer(GL_ARRAY_BUFFER, new_message.VBO_alphabet);
glBufferData(GL_ARRAY_BUFFER, 6 * 4 * sizeof(float), &new_message.alphabet_quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
void process_text_compare(Message_Parent& new_message, int text_start_x, int text_start_y)
{
float advance_to_next_character = 0.0f;
// "relative_distance" and "tallest_character" are fixed values, calculated per message (used here to align the text's highest pixel to the display window's top row of pixels)
float tallest_character = new_message.tallest_font_height * scale_pixels_y_to_OpenGL;
float relative_distance = new_message.relative_distance * scale_pixels_y_to_OpenGL;
for (unsigned i = 0; i < new_message.message_string.size(); ++i)
{
for (unsigned i2 = 0; i2 < new_message.alphabet_vec.size(); ++i2)
{
if (new_message.message_string.c_str()[i] == new_message.alphabet_vec[i2].character)
{
if (advance_to_next_character == 0) // Start X, Y positions need setting here, but only for the 1st character, i.e. when: advance_to_next_character = 0
{
// Enable these two lines for 2D window-positioned text
// -----------------------------------------------------------------------
new_message.text_start_x = -1.0f - new_message.alphabet_vec[i2].left_bearing + (text_start_x - alphabet_padding) * scale_pixels_x_to_OpenGL;
new_message.text_start_y = 1.0f + relative_distance - tallest_character - (text_start_y + alphabet_padding) * scale_pixels_y_to_OpenGL;
// Enable these two lines instead for 3D animated text
// --------------------------------------------------------------------
// new_message.text_start_x = -1.35f;
// new_message.text_start_y = 0.0f;
}
process_text_index(new_message, i2, advance_to_next_character);
advance_to_next_character += new_message.alphabet_vec[i2].glyph_advance_x;
break; // Stop checking the alphabet if the character is found.
}
}
}
}
void initialise_buffer_data_message(Message_Parent& new_message)
{
glGenVertexArrays(1, &new_message.VAO_message);
glGenBuffers(1, &new_message.VBO_message);
glBindVertexArray(new_message.VAO_message);
glBindBuffer(GL_ARRAY_BUFFER, new_message.VBO_message);
new_message.allocated_memory_bytes = new_message.characters_quads.size() * 6 * 4 * sizeof(float);
if (new_message.dynamic_static)
glBufferData(GL_ARRAY_BUFFER, new_message.allocated_memory_bytes, NULL, GL_DYNAMIC_DRAW);
else
glBufferData(GL_ARRAY_BUFFER, new_message.allocated_memory_bytes, NULL, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
};
Ответы (1 шт):
Автор решения: Никита Самоуков
→ Ссылка
Если идентификатор не определен значит его нету.
Чтоб опенжл нормальный подрубить, нужно подрубить какой-нибудь глад. Ну и указатели чтоб появились нужно его врубить, иначе вызывать эти функции нельзя.
#include <glad/gl.h>
gladLoadGL