SDL_TTF рисует мусор

Я задал вопрос на днях о рендеринге шрифтов TTF с использованием SDL, и меня указали на SDL_TTFL. Я пытался использовать библиотеку SDL_TTF, но все, что я получаю, это мусор на экране

Я включил мои шейдеры, которые очень просты для этой программы, а также фрагмент, который я использую, чтобы загрузить текст на поверхность и привязать его к текстуре. Я вообще не пытаюсь делать что-то сумасшедшее. Есть что-то, что я делаю неправильно, ты видишь? Я не совсем уверен, как отлаживать шейдеры и т. Д.

Фрагмент шейдера (frag.glsl):

#version 330
in vec2 texCoord;
in vec4 fragColor;

out vec3 finalColor;

uniform sampler2D myTextureSampler;
void main() {
finalColor = texture( myTextureSampler, texCoord ).rgb;
}

Вершинный шейдер (vert.glsl)

#version 330

in vec3 vert;
in vec4 color;
in vec2 texcoord;

out vec4 fragColor;
out vec2 texCoord;

void main() {
fragColor = color;
gl_Position = vec4(vert, 1);
texCoord = texcoord;
}

Загрузка шрифта (loadFont.cpp)

//Initialise TTF
if( TTF_Init() == -1 )
throw std::runtime_error("SDL_TTF failed to initialise.");

//Load the texture
font = TTF_OpenFont( filePath.c_str(), 12 );
if(!font)
throw std::runtime_error("Couldn't load: "+ filePath);

TTF_SetFontStyle(font, TTF_STYLE_NORMAL);

surface = TTF_RenderUTF8_Blended(font, "Hello", this->textColor);
Uint8 colors = surface->format->BytesPerPixel;
int texture_format;
if (colors == 4) {   // alpha
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGBA;
else
texture_format = GL_BGRA;
} else {             // no alpha
if (surface->format->Rmask == 0x000000ff)
texture_format = GL_RGB;
else
texture_format = GL_BGR;
}
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

glTexImage2D(GL_TEXTURE_2D, 0, colors, surface->w, surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, surface->pixels);
SDL_FreeSurface(surface);

Настройка атрибута вершины

GLfloat vertices[] = {
//X    Y      Z     R     G     B     A     U    V
-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 1.f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 1.f,
-1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 0.f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 1.f,
1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 1.f, 0.f,
-1.0f, -0.4f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.f, 0.f

};glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);

glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(program->attrib("vert"));
glVertexAttribPointer(program->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), NULL);

glEnableVertexAttribArray(program->attrib("color"));
glVertexAttribPointer(program->attrib("color"), 4, GL_FLOAT, GL_TRUE,  9*sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat)));

glEnableVertexAttribArray(program->attrib("texcoord"));
glVertexAttribPointer(program->attrib("texcoord"), 2, GL_FLOAT, GL_TRUE,  9*sizeof(GLfloat), (const GLvoid*)(7 * sizeof(GLfloat)));

Я приложил код, который я использую для атрибутов вершины, согласно комментарию ниже.

РЕДАКТИРОВАТЬ:
В ответе, который был удален с тех пор, был задан вопрос, возвращал ли SDL_TTF 3 или 4 канала. Это возвращает изображение BGRA. Я попытался изменить свой фрагментный шейдер на

Фрагмент шейдера

#version 330
in vec2 texCoord;
in vec4 fragColor;

out vec4 finalColor;

uniform sampler2D myTextureSampler;
void main() {
finalColor = texture( myTextureSampler, texCoord ).rgba;
}

Обратите внимание на vec4, используя rgba, а не rgb. Это просто приводит к черному прямоугольнику.
Я также попытался сгенерировать поверхность с помощью SDL_LoadBMP (), которая дает точно такие же результаты.

5

Решение

Ваш звонок в

glTexImage2D (GL_TEXTURE_2D, 0, цвета, поверхность-> ш, поверхность-> ч, 0,
текстура_формат, GL_UNSIGNED_BYTE, поверхность-> пиксели);

Это проблема.

Третий параметр неверен:

http://www.opengl.org/sdk/docs/man/xhtml/glTexImage2D.xml

internalFormat

                Specifies the number of color components in the texture.
Must be one of base internal formats given in Table 1,
one of the sized internal formats given in Table 2, or one
of the compressed internal formats given in Table 3, below.

Я подозреваю, что вы хотите, чтобы ваш был GL_RGBA (или в каком формате вы хотите, чтобы opengl сохранял вашу текстуру)

РЕДАКТИРОВАТЬ:

Я только что видел это сейчас, но вы используете только 3 канала в вашем фрагментном шейдере. Функция Blended требует, чтобы вы использовали 4 канала, иначе альфа-канал будет испорчен.

Я думаю, что ваша «основная» проблема лежит где-то еще, так как это должно просто сделать цвет постоянным по всей поверхности. (Не «мусор», который вы видите)

Я быстро написал эту программу, которая в основном делает то, что вы делаете. Я думаю, что это поможет вам больше, чем мой репозиторий, поскольку это прямо к делу.

#include <GL/glew.h>

#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_ttf.h>

#include <string>
#include <iostream>

using namespace std;

SDL_Window *window = NULL;
SDL_GLContext context = NULL;
TTF_Font* font = NULL;
SDL_Surface* surface = NULL;

//OpenGL Objects
GLuint vao;
GLuint vbo;
GLuint texture;

//Shader Objects
GLuint program;
GLuint vs;
GLuint fs;

//Sampler Object
GLuint uniformSampler;

//Callback Function
APIENTRY GLvoid debugMessageCallbackFunction( GLenum source, GLenum type, GLuint id, GLenum severity,
GLsizei length, const GLchar* message, GLvoid* userParam)
{
cerr << endl << "\t" << message << endl;
}

//The shaders are identical to yours
const string fragmentShaderString =
"#version 130\n" // My laptop can't do OpenGL 3.3 so 3.0 will have to do
"in vec2 texCoord;\n""in vec4 fragColor;\n""\n""out vec4 finalColor;\n""\n""uniform sampler2D myTextureSampler;\n""void main() {\n""  finalColor = texture( myTextureSampler, texCoord ) * fragColor;\n""}";

const string vertexShaderString =
"#version 130\n""\n""in vec3 vert;\n""in vec4 color;\n""in vec2 texcoord;\n""\n""out vec4 fragColor;\n""out vec2 texCoord;\n"
"void main() {\n""  fragColor = color;\n""  gl_Position = vec4(vert, 1);\n""  texCoord = texcoord;\n""}\n";

//Your vertices, but I changed alpha to 1.0f
const GLfloat vertices[] =
{
//X    Y      Z     R     G     B     A     U    V
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 1.f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 1.f,
-1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 0.f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 1.f,
1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.f, 0.f,
-1.0f, -0.4f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.f, 0.f
};

int main(int argc, char* args[])
{
//Create Window and Context
window = SDL_CreateWindow("SDL Text with OpenGL", 0, 0, 640, 480, SDL_WINDOW_OPENGL);

//Set Core Context
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

context = SDL_GL_CreateContext(window);

//Simple OpenGL State Settings
glViewport( 0.f, 0.f, 640.f, 480.f);
glClearColor( 0.f, 0.f, 0.f, 1.f);

//Init Glew
//Set glewExperimental for Core Context
glewExperimental=true;
glewInit();

//Set Blending
//Required so that the alpha channels show up from the surface
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//Simple callback function for GL errors
glDebugMessageCallbackARB(debugMessageCallbackFunction, NULL);

//Create Shaders
vs = glCreateShader(GL_VERTEX_SHADER);
fs = glCreateShader(GL_FRAGMENT_SHADER);

//Source Pointers
const GLchar* vsSource= &vertexShaderString[0];
const GLchar* fsSource = &fragmentShaderString[0];

//Set Source
glShaderSource(vs, 1, &vsSource, NULL);
glShaderSource(fs, 1, &fsSource, NULL);

//Compile Shaders
glCompileShader(fs);
glCompileShader(vs);

//Create Shader Program
program = glCreateProgram();

//Attach Shaders to Program
glAttachShader(program, vs);
glAttachShader(program, fs);

//No need for shaders anymore
glDeleteShader(vs);
glDeleteShader(fs);

//Set Attribute Locations
glBindAttribLocation(program, 0, "vert");
glBindAttribLocation(program, 1, "color");
glBindAttribLocation(program, 2, "texcoord");

//Link Program
glLinkProgram(program);

//Setup VAO and VBO
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 9 * 6, vertices, GL_STATIC_DRAW);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), NULL);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),(GLvoid*)(3*sizeof(GLfloat)));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat),(GLvoid*)(7*sizeof(GLfloat)));

//Init TTF
TTF_Init();

//Open Font
font = TTF_OpenFont("DroidSansFallbackFull.ttf", 30);

SDL_Color color = {255, 255, 255, 255};

//Create Surface
surface = TTF_RenderUTF8_Blended(font, "This is TEXT!", color);

//Your format checker
GLenum format = (surface->format->BytesPerPixel==3)?GL_RGB:GL_RGBA;

//Create OpenGL Texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D( GL_TEXTURE_2D, 0, format, surface->w, surface->h, 0,
format, GL_UNSIGNED_BYTE, surface->pixels);

//Set Some basic parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

//Set up Sampler
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

uniformSampler = glGetUniformLocation(program, "myTextureSampler");
//It defaults to using GL_TEXTURE0, so it's not necessary to set it
//in this program it's generally a good idea.

//--------------------------------------------------------------------------------------
// DRAW STAGE
//--------------------------------------------------------------------------------------

glUseProgram(program);

//glBindVertexArray(vao); - still in use

glClear(GL_COLOR_BUFFER_BIT);

glDrawArrays(GL_TRIANGLES, 0, 6);

SDL_GL_SwapWindow(window);

//Sleep for 2s before closing
SDL_Delay(2000);
}

Я не делал никаких проверок ошибок и не закрывал ни один из ресурсов, так как он просто предназначен для ссылки и не предназначен для использования.

Обычно я не использую glew, но написание кода для ручного получения функций для такой маленькой программы казалось бессмысленным.

Компилируется с

g++ source.cpp -g -lSDL2 -lSDL2_ttf -lGL -GLEW -o demo

на Linux. Возможно, вам придется внести некоторые изменения в Windows (файлы заголовков могут немного измениться, а библиотеки тоже изменятся), и я думаю, что на Mac это будет работать без изменений.

РЕДАКТИРОВАТЬ 2:

Чтобы скомпилировать его в Windows с помощью mingw, вам нужно добавить APIENTRY в функцию обратного вызова, и у main должны быть аргументы. Изменен код для отражения этого.

Протестировал его и он работает как на Windows, так и на Linux. (При условии, что ваша реализация имеет доступ к расширению GL_ARB_debug_callback, если не просто закомментировать это)

3

Другие решения

Работает хорошо, нужно только редактировать const GLfloat vertices[] массив, чтобы иметь возможность последовательно изменять цвет текста. Для однотонного текста, все компоненты RGB в массиве должны быть равны 1.0f и визуализировать текстуру в color, Для многоцветного текста, сначала визуализируйте текстуру белым SDL_Color color = { 255, 255, 255, 255 };, затем отредактируйте массив, как показано здесь ниже.

float width = (float)surface->w;
float height = (float)surface->h;

// alpha to 1.0f
const GLfloat vertices[] = {
// X         Y          Z     R     G     B     A     U     V
-1.0, -height / width, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, height / width, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
1.0f, -height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,  height / width, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, height / width, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f
};

Разноцветный текст отображается в SDG в качестве текстуры в OpenGL

0

По вопросам рекламы [email protected]