opengl 渲染文本神奇地消失

dba5bblo  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(105)

我目前正在准备一切写我自己的游戏在c使用GLFW。我以前从来没有用C写过游戏,只在C#中使用Unity。我对GLSL完全陌生。我发现了如何渲染文本,一切工作基本上都很好,但现在我有一个问题(我认为)投影矩阵。我使用GLFWmonitor来获取屏幕分辨率,并在此分辨率下运行窗口:

GLFWmonitor *monitor = glfwGetPrimaryMonitor();
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
std::cout << "Monitor resolution: " << mode->width << "x" << mode->height << std::endl;
CBWindow window(mode->width, mode->height, "City Builder");

字符集
从我得到的cout:

Monitor resolution: 1440x900


然后我从文本渲染器开始,使用glfwGetWindowSize来获取窗口大小,并将投影矩阵设置为这个大小,但出现了一些问题。就好像我可以呈现文本的空间只在我的窗口的一小部分中可用:

的数据
出于调试原因,我开始打印从glfwGetWindowSize得到的宽度和高度,我看到这不是100%,但它应该可以工作:

Window size: 1440x793


我不知道为什么我得到这个不正确的数字,我不知道为什么我不能在整个屏幕上渲染。
下面是负责渲染文本的函数:

void TextRenderer::renderText(GLFWwindow *window, const std::string& text, GLfloat x, GLfloat y, GLfloat scale, const glm::vec3& color) {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    this->shader.use();
    int w, h;
    glfwGetWindowSize(window, &w, &h);
    std::cout << "Window size: " << w << "x" << h << std::endl;
    glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(w), 0.0f, static_cast<GLfloat>(h));
    this->shader.setUniform("textColor", color);
    this->shader.setUniform("projection", projection);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(this->VAO);

    // iterate through all characters
    std::string::const_iterator c;
    for (c = text.begin(); c != text.end(); c++) {
        Character ch = this->font.getCharacters().at(*c);

        GLfloat xpos = x + ch.Bearing.x * scale;
        GLfloat ypos = y - (ch.Size.y - ch.Bearing.y) * scale;

        GLfloat w = ch.Size.x * scale;
        GLfloat h = ch.Size.y * scale;

        // update VBO for each character
        GLfloat vertices[6][4] = {
                { xpos,     ypos + h,   0.0, 0.0 },
                { xpos,     ypos,       0.0, 1.0 },
                { xpos + w, ypos,       1.0, 1.0 },

                { xpos,     ypos + h,   0.0, 0.0 },
                { xpos + w, ypos,       1.0, 1.0 },
                { xpos + w, ypos + h,   1.0, 0.0 }
        };

        // render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D, ch.TextureID);

        // update content of VBO memory
        glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        // render quad
        glDrawArrays(GL_TRIANGLES, 0, 6);
        x += (ch.Advance >> 6) * scale;
    }

    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
    this->shader.unuse();
    glDisable(GL_BLEND);
}


片段着色器:

#version 330 core

in vec2 TexCoords;
out vec4 color;

uniform sampler2D text;
uniform vec3 textColor;

void main()
{
    vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
    color = vec4(textColor, 1.0) * sampled;
}


和顶点着色器:

#version 330 core

layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;

uniform mat4 projection;

void main()
{
    gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
    TexCoords = vertex.zw;
}


我们在renderText方法中使用的着色器函数只使用glUseProgram和设置uniform的函数。
下面是我如何使用这些函数:

#include <iostream>
#include <glm/ext/matrix_clip_space.hpp>
#include "Display/Window.h"
#include "Renderer/Shader.h"
#include "vendor/stb/stb_truetype.h"
#include "Renderer/UI/Text/Font.h"
#include "Renderer/UI/Text/TextRenderer.h"

int main() {
    if(!glfwInit()){
        printf("Failed to initialize OpenGL\n");
        exit(1);
    }

    GLFWmonitor *monitor = glfwGetPrimaryMonitor();
    const GLFWvidmode *mode = glfwGetVideoMode(monitor);
    std::cout << "Monitor resolution: " << mode->width << "x" << mode->height << std::endl;
    CBWindow window(mode->width, mode->height, "City Builder");

    Shader shader("../assets/shaders/Text/vert.glsl", "../assets/shaders/Text/frag.glsl");
    Font font("../assets/fonts/Arial.ttf", 48);
    TextRenderer textRenderer(shader, font);

    double lastTime = glfwGetTime();
    int nbFrames = 0;
    std::string fps_text;

    while(!glfwWindowShouldClose(window.GetWindow())){

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

        double currentTime = glfwGetTime();
        nbFrames++;
        if ( currentTime - lastTime >= 1.0 ){ 
            fps_text = "FPS: " + std::to_string(nbFrames);
            nbFrames = 0;
            lastTime += 1.0;
        }

        textRenderer.renderText(window.GetWindow(),fps_text, 1400, 0, 1, glm::vec3(1.0f, 0.0f, 0.0f));
        textRenderer.renderText(window.GetWindow(),fps_text, 0, 790, 1, glm::vec3(1.0f, 0.0f, 0.0f));

        glfwSwapBuffers(window.GetWindow());
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}


谢谢你的时间

wztqucjr

wztqucjr1#

是否有可能丢失的107个像素被窗口标题栏使用?这是有意义的,因为你不能在标题栏上呈现文本。但这只是一个假设。
显示器大小与窗口大小不同。
如果我的假设是正确的,你应该尝试将窗口设置为全屏模式。我希望这对你有帮助:)

相关问题