渲染文本出现故障并显示后面的文本四边形和错误的颜色十六进制

问题描述 投票:0回答:1

我试图在我的游戏引擎中创建一个函数来使用 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;
}

这是我面临的问题的预览: 预览

我尝试做的事情:

添加一个函数来在我的引擎中渲染文本

我的期望:

带有工作颜色十六进制的透明文本

c opengl graphics game-engine
1个回答
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 混合。

© www.soinside.com 2019 - 2024. All rights reserved.