我试图在我的游戏引擎中创建一个函数来使用 stb_truetype 绘制文本,问题是在渲染它时,由于某种原因,文本后面有黑框,即使十六进制颜色是白色的,它也会因为某种原因是红色的,我已经尝试了一切,但无法修复颜色十六进制或黑框消失 这是我的引擎目前的功能:
#include "../include/engine.h"
#include "../include/glad/glad.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "../include/GLFW/glfw3.h"
#define STB_TRUETYPE_IMPLEMENTATION
#include "../include/stb_truetype.h"
// External window
GLFWwindow* window;
// Global font variable for cleanup
Font globalFont;
// 2D drawing state
bool is2DDrawingEnabled = false;
// Create a window
GLFWwindow* CreateWindow(const char* title, int width, int height) {
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return NULL;
}
// Set OpenGL version to 2.1
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
window = glfwCreateWindow(width, height, title, NULL, NULL);
if (!window) {
fprintf(stderr, "Failed to create GLFW window\n");
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); // Make sure glad supports OpenGL 2.1
glViewport(0, 0, width, height);
return window;
}
// Set background color using hex color codes like "#RRGGBB"
void SetBackColor(const char* hexColor) {
if (hexColor[0] == '#') {
unsigned int hexValue = (unsigned int)strtol(hexColor + 1, NULL, 16);
float r = ((hexValue >> 16) & 0xFF) / 255.0f;
float g = ((hexValue >> 8) & 0xFF) / 255.0f;
float b = (hexValue & 0xFF) / 255.0f;
glClearColor(r, g, b, 1.0f);
} else {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
}
// Load font function with error handling
Font LoadFont(const char* filename, int fontSize) {
Font font = { 0 };
// Load the font file
FILE* fontFile = fopen(filename, "rb");
if (!fontFile) {
fprintf(stderr, "Failed to open font file: %s\n", filename);
return font;
}
// Read font file into memory
fseek(fontFile, 0, SEEK_END);
long fileSize = ftell(fontFile);
fseek(fontFile, 0, SEEK_SET);
unsigned char* ttfBuffer = (unsigned char*)malloc(fileSize);
if (fread(ttfBuffer, 1, fileSize, fontFile) != fileSize) {
fprintf(stderr, "Failed to read font file: %s\n", filename);
fclose(fontFile);
free(ttfBuffer);
return font;
}
fclose(fontFile);
// Create bitmap for font
font.bitmap = (unsigned char*)malloc(512 * 512);
stbtt_bakedchar* bakedChars = (stbtt_bakedchar*)malloc(sizeof(stbtt_bakedchar) * 96);
if (stbtt_BakeFontBitmap(ttfBuffer, 0, (float)fontSize, font.bitmap, 512, 512, 32, 96, bakedChars) <= 0) {
fprintf(stderr, "Failed to bake font bitmap for: %s\n", filename);
free(ttfBuffer);
free(font.bitmap);
free(bakedChars);
return font;
}
// Generate texture
glGenTextures(1, &font.textureID);
glBindTexture(GL_TEXTURE_2D, font.textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 512, 512, 0, GL_RED, GL_UNSIGNED_BYTE, font.bitmap);
// Set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Store baked chars in font structure
font.glyphs = bakedChars; // Store the glyphs directly in the Font struct
// Free temporary buffers
free(ttfBuffer);
font.baseSize = fontSize;
// Store global font
globalFont = font;
return font;
}
// Function to start 2D drawing
void Start2DDrawing() {
if (!is2DDrawingEnabled) {
glEnable(GL_TEXTURE_2D); // Enable 2D texturing
glEnable(GL_BLEND); // Enable blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Set blend function
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, 800.0f, 600.0f, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
is2DDrawingEnabled = true;
}
}
void End2DDrawing() {
if (is2DDrawingEnabled) {
glDisable(GL_TEXTURE_2D);
is2DDrawingEnabled = false;
}
}
// Function to draw text
void DrawText(Font font, const char* text, int posX, int posY, const char* hexColor) {
glBindTexture(GL_TEXTURE_2D, font.textureID);
// Set color based on hex value
if (hexColor[0] == '#') {
unsigned int hexValue = (unsigned int)strtol(hexColor + 1, NULL, 16);
float r = ((hexValue >> 16) & 0xFF) / 255.0f;
float g = ((hexValue >> 8) & 0xFF) / 255.0f;
float b = (hexValue & 0xFF) / 255.0f;
glColor4f(r, g, b, 1.0f); // Set color from hex
} else {
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Default to white if not a valid hex
}
float x = (float)posX;
float y = (float)posY;
for (const char *c = text; *c; c++) {
if (*c < 32 || *c > 126) continue; // Skip unsupported characters
stbtt_aligned_quad q;
stbtt_GetBakedQuad(font.glyphs, 512, 512, *c - 32, &x, &y, &q, 1);
// Draw the quad for the character
glBegin(GL_QUADS);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glEnd();
}
}
bool WindowShouldEnd(GLFWwindow* window) {
return glfwWindowShouldClose(window);
}
void HandleEvents(GLFWwindow* window) {
glfwPollEvents();
glfwSwapBuffers(window);
}
void ClearScreen() {
glClear(GL_COLOR_BUFFER_BIT);
}
void error_callback(int error, const char* description) {
fprintf(stderr, "Error: %s\n", description);
}
// Cleanup
void Cleanup() {
// Clean up the global font
glDeleteTextures(1, &globalFont.textureID);
free(globalFont.bitmap);
free(globalFont.glyphs); // Free baked glyphs
glfwDestroyWindow(window);
glfwTerminate();
}
engine.h 中的字体内容:
// Color structure
typedef struct {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} Color;
// Font structure to hold font data
typedef struct Glyph {
stbtt_bakedchar bakedChar; // Represents the baked character data from stb_truetype
float advanceX; // The amount to advance the cursor after rendering this glyph
float offsetX; // The offset for rendering this glyph
} Glyph;
typedef struct Font {
GLuint textureID; // Texture ID for the font atlas
unsigned char *bitmap; // Bitmap data for the font atlas
int baseSize; // Base font size (used for scaling)
stbtt_bakedchar* glyphs; // Pointer to an array of baked characters for the font
} Font;
这是主要的应用程序代码,我猜它没有任何问题:
#include "../include/engine.h"
int main() {
window = CreateWindow("Test Window", 800, 600); // Initialize the window
if (!window) return -1; // Exit if window creation failed
globalFont = LoadFont("assets/AfacadFlux.ttf", 48); // Load the font
if (globalFont.textureID == 0) return -1; // Exit if font loading failed
while (!WindowShouldEnd(window)) {
ClearScreen();
SetBackColor("#222222");
Start2DDrawing();
Color white = {255, 255, 255, 255}; // White color
DrawText(globalFont, "Hello, World!", 100, 100, "#FFFFFF"); // Draw text
End2DDrawing();
HandleEvents(window);
}
Cleanup(); // Clean up resources
return 0;
}
这是我面临的问题的预览: 预览
我尝试做的事情:
添加一个函数来在我的引擎中渲染文本
我的期望:
带有工作颜色十六进制的透明文本
请阅读glTexImage2D文档。
void glTexImage2D( GLenum target,
GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid * data);
第三个参数是
internalFormat
,它定义“纹理中颜色分量的数量。必须是 1、2、3 或 4,或以下符号常量之一......”。 GL_READ
不在列表中。但仍然假设您将一个放入其中。
下一个发现是一个
format
参数。这就是 OpenGL
处理你的像素数据的方式。应该是GL_ALPHA
,GL_LUMINANCE
,GL_LUMINANCE_ALPHA
。即与 Alpha 通道或亮度相关的任何内容。这是因为您希望通过 OpenGL
固定管道提供颜色。对你来说,caice,它肯定是一个 GL_ALPHA
,因为你稍后使用 alpha 混合。你知道它会的 glEnable(GL_BLEND); // Enable blending glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Set blend function
在向屏幕显示文本之前不要忘记启用 Alpha 混合。