c++ - 将 Freetype 字形渲染到 OpenGL (3.3+) 纹理会导致重复纹理和伪影

标签 c++ opengl textures glsl freetype2

我只是想将从 Freetype 加载的字形(字母 Ě)作为位图图片显示到在整个窗口上拉伸(stretch)的 OpenGL 纹理上。结果在这里:

OpenGL + Freetype

为了得到这个结果,我必须将一个非常大的 FT_Set_Pixel_Sizes 设置为 450,否则生成的图像看起来会更糟。

我正在使用 GLSLShader loader class由 M.M. Mobeen、GLEW、SDL2 和 GLM。

shaders/shader.vert

#version 330 core
layout(location=0) in vec4 vVertex; //object space vertex
out vec2 vUV;   // texture coordinates for texture lookup in the fragment shader

void main()
{
    gl_Position = vec4(vVertex.xy,0,1);
    vUV = vVertex.zw; // texture coordinate
}

shaders/shader.frag

#version 330 core
layout (location=0) out vec4 vFragColor;
smooth in vec2 vUV;
uniform sampler2D textureMap;

void main()
{                                              
    vFragColor = texture(textureMap, vUV);
}

main.cpp

#include <glew.h>
#include <glm/glm.hpp>

#include "SDL2/SDL.h"
#include "SDL2/SDL_opengl.h"

#include <ft2build.h>
#include FT_FREETYPE_H    

#include "GLSLShader.h" // https://github.com/bagobor/opengl33_dev_cookbook_2013/blob/master/Chapter3/src/GLSLShader.h

//shader reference
GLSLShader shader;

//vertex array and vertex buffer object IDs
GLuint vaoID;
GLuint vboVerticesID;
GLuint vboIndicesID;

//texture ID
GLuint textureID;

//quad vertices and indices
glm::vec4 vertices[4];
GLushort indices[6];

int main( int argc, const char* argv[] )
{
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) return EXIT_FAILURE;

    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
    SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );

    SDL_Window* window = SDL_CreateWindow( "OpenGL + Freetype",
                                           SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                           1024, 768,
                                           SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );

    SDL_GLContext glcontext = SDL_GL_CreateContext( window );

    if( glcontext == nullptr ) return EXIT_FAILURE;

    glewExperimental = GL_TRUE;

    if( glewInit() != GLEW_OK ) return EXIT_FAILURE;

    SDL_GL_SetSwapInterval( 1 );

    shader.LoadFromFile( GL_VERTEX_SHADER, "shaders/shader.vert" );
    shader.LoadFromFile( GL_FRAGMENT_SHADER, "shaders/shader.frag" );

    //compile and link shader
    shader.CreateAndLinkProgram();
    shader.Use();
        shader.AddAttribute( "vVertex" );
        shader.AddUniform( "textureMap" );
        glUniform1i( shader( "textureMap" ), 0 );
    shader.UnUse();

    //setup quad geometry
    vertices[0] = glm::vec4( -1.0, -1.0, 0, 1 );
    vertices[1] = glm::vec4( 1.0, 1.0, 1, 0 );
    vertices[2] = glm::vec4( 1.0, -1.0, 1, 1 );
    vertices[3] = glm::vec4( -1.0, 1.0, 0, 0 );

    //fill quad indices array
    GLushort* id = &indices[0];
    *id++ = 0;
    *id++ = 1;
    *id++ = 2;
    *id++ = 0;
    *id++ = 1;
    *id++ = 3;

    glGenVertexArrays( 1, &vaoID );
    glGenBuffers( 1, &vboVerticesID );
    glGenBuffers( 1, &vboIndicesID );

    glBindVertexArray( vaoID );

    glBindBuffer( GL_ARRAY_BUFFER, vboVerticesID );
    glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), &vertices[0], GL_DYNAMIC_DRAW );

    glEnableVertexAttribArray( shader["vVertex"] );
    glVertexAttribPointer( shader["vVertex"], sizeof( shader["vVertex"] ), GL_FLOAT, GL_FALSE, 0, 0 );

    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vboIndicesID );
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), &indices[0], GL_STATIC_DRAW );

    glGenTextures( 1, &textureID );
    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, textureID );

    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
    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_LINEAR );

    FT_Library  library;
    FT_Face     face;

    bool error = FT_Init_FreeType( &library );

    if( error ) return EXIT_FAILURE;

    error = FT_New_Face( library,
                         "dejavu.ttf",
                         0,
                         &face );

    if( error ) return EXIT_FAILURE;

    error = FT_Set_Pixel_Sizes( face, 0, 16 );

    if( error ) return EXIT_FAILURE;

    FT_Set_Pixel_Sizes( face, 0, 450 );

    FT_UInt glyph_index = FT_Get_Char_Index( face, 282 ); // letter Ě

    error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );

    if( error ) return EXIT_FAILURE;

    error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL );

    if( error ) return EXIT_FAILURE;

    glTexImage2D( GL_TEXTURE_2D,
                  0,
                  GL_RGB,
                  face->glyph->bitmap.width,
                  face->glyph->bitmap.rows,
                  0,
                  GL_RGB,
                  GL_UNSIGNED_BYTE,
                  face->glyph->bitmap.buffer
                );

    bool running = true;
    while( running )
    {
        SDL_Event e;

        if( SDL_PollEvent( &e ) )
        {
            switch( e.type )
            {
                case SDL_QUIT:
                    running = false;
                    break;
                default:
                    break;
            }
        }

        glClearColor( 1, 1, 1, 1 );
        glClear( GL_COLOR_BUFFER_BIT );

        shader.Use(); // bind shader
            glDrawElements( GL_TRIANGLES, sizeof( indices ), GL_UNSIGNED_SHORT, 0 );
        shader.UnUse(); // unbind shader

        SDL_GL_SwapWindow( window );
    }

    return 0;
}

最佳答案

FT_RENDER_MODE_NORMAL results in a single-channel bitmap, not RGB:

FT_RENDER_MODE_NORMAL This is the default render mode; it corresponds to 8-bit anti-aliased bitmaps.

尝试在 glTexImage2D() 调用中使用 GL_RED 作为 format 而不是 GL_RGB:

glTexImage2D( GL_TEXTURE_2D,
              0,
              GL_RGB,
              face->glyph->bitmap.width,
              face->glyph->bitmap.rows,
              0,
              GL_RED,
              GL_UNSIGNED_BYTE,
              face->glyph->bitmap.buffer
            );

关于c++ - 将 Freetype 字形渲染到 OpenGL (3.3+) 纹理会导致重复纹理和伪影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25724555/

相关文章:

image - 将矩形图像数据打包到正方形纹理中

ios - 解除绑定(bind) Open GL ES 纹理的正确方法?

c++ - 二叉树不会编译: Error 'WinMain@16'

c++ - 创建一个简单的脚本 'language' - 类似 VARIANT 的值类型

c++ - mfc c++ 将带有 postmessage 的自定义用户消息从工作线程发送到主 ui 线程

c++ - OpenGL 顶点数组球体杂散顶点

opengl - 通过 HDMI 保持视频的 Alpha 透明度

c++ - 基础 openGL |黑屏

rotation - libgdx:使用 spritebatch 绘制纹理时旋转纹理

c++ - 这些代码有什么不同吗?