c++sdlsdl-2truetypesdl-ttf

SDL2 TTF Text Not Rendering As Expected


I've been working on a program that utilizes SDL2, and I've been trying to get text on the screen using an SDL_Surface converted to a SDL_Texture then rendering with SDL_RenderCopy(). It shows only a black screen (as expected) however the red "Hello World!" text does not appear. This is also C++, to clarify.

This is my code:

#include <iostream>
#include <SDL.h>
#include <SDL_ttf.h>

int main()
{
    bool quit = false;

    SDL_Event event;

    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();

    SDL_Window *window = SDL_CreateWindow("GUI Text Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);

    if(window == NULL)
    {
        std::cout << "window is null" << SDL_GetError();
    }

    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

    if(renderer == NULL)
    {
        std::cout << "renderer is null" << SDL_GetError();
    }

    SDL_Color red = {255, 0, 0, 255};

    TTF_Font *roboto = TTF_OpenFont("fonts/Roboto-Regular.ttf", 24);

    if(roboto == NULL)
    {
        std::cout << "font is null " << SDL_GetError();
    }

    SDL_Surface *textSurface = TTF_RenderText_Solid(roboto, "Hello World!", red);

    if(textSurface == NULL)
    {
        std::cout << "surface is null " << SDL_GetError();
    }

    SDL_Texture *textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

    if(textTexture == NULL)
    {
        std::cout << "texture is null " << SDL_GetError();
    }

    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    rect.w = 300;
    rect.h = 300;

    while (!quit)
    {
        while (SDL_PollEvent(&event) > 0)
        {
            switch (event.type)
            {
                case SDL_QUIT:
                    quit = true;
                    break;
            }
        }

        SDL_RenderCopy(renderer, textTexture, nullptr, &rect);

        SDL_UpdateWindowSurface(window);
    }

    SDL_Quit();
    TTF_Quit();

    return 0;
}

(The fonts folder is in the same working directory as the g++-compiled executable)

I was expecting the red "Hello World!" text to appear but alas, it did not.

EDIT: Thanks to genpfault, I was able to get the text somewhat rendered, but there's weird static behind the text—probably the rect.

My new code:

#include <iostream>
#include <SDL.h>
#include <SDL_ttf.h>

int main()
{
    bool quit = false;

    SDL_Event event;

    SDL_Init(SDL_INIT_EVERYTHING);
    TTF_Init();

    SDL_Window *window = SDL_CreateWindow("GUI Text Editor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_SHOWN);

    if(window == NULL)
    {
        std::cout << "window is null" << SDL_GetError();
    }

    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

    if(renderer == NULL)
    {
        std::cout << "renderer is null" << SDL_GetError();
    }

    SDL_Color red = {255, 0, 0, 255};

    TTF_Font *roboto = TTF_OpenFont("fonts/Roboto-Regular.ttf", 24);

    if(roboto == NULL)
    {
        std::cout << "font is null " << SDL_GetError();
    }

    SDL_Surface *textSurface = TTF_RenderText_Solid(roboto, "Hello World!", red);

    if(textSurface == NULL)
    {
        std::cout << "surface is null " << SDL_GetError();
    }

    SDL_Texture *textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);

    if(textTexture == NULL)
    {
        std::cout << "texture is null " << SDL_GetError();
    }

    SDL_Rect rect;
    rect.x = 0;
    rect.y = 0;
    rect.w = 300;
    rect.h = 300;

    while (!quit)
    {
        while (SDL_PollEvent(&event) > 0)
        {
            switch (event.type)
            {
                case SDL_QUIT:
                    quit = true;
                    break;
            }
        }

        SDL_RenderPresent(renderer);

        SDL_RenderCopy(renderer, textTexture, nullptr, &rect);

        SDL_UpdateWindowSurface(window);
    }

    SDL_Quit();
    TTF_Quit();

    return 0;
}

The static:

enter image description here


Solution

  • I'm not quite sure how you ended up using both SDL_CreateRenderer and SDL_UpdateWindowSurface at the same time, but here is the short answer to your problem: replace SDL_UpdateWindowSurface(window); with SDL_RenderPresent(renderer);, and call SDL_RenderClear where appropriate (presumably just before SDL_RenderCopy).

    If you are following Lazy Foo's tutorial like you said in the comments, I guess you haven't gotten to the TTF section yet, because it does basically what I say above. I can only assume you skipped to searching "how to render text in SDL2" and tried to adapt what you found without understanding what it does. Note that the second answer in that post gives you a complete working example.

    I suggest closely following the tutorial or dropping it to try something else instead. For example, delving into the SDL wiki to understand exactly what each function does, and searching the web for whatever isn't obvious, like the difference between SDL_RenderPresent vs SDL_UpdateWindowSurface.