5

先日、SDLを使ったTTFフォントのレンダリングについて質問したところ、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 に注意し、rgb ではなく rgba を使用します。これは単に黒い長方形につながります。また、SDL_LoadBMP() を使用してサーフェスを生成しようとしましたが、まったく同じ結果が得られました。

4

2 に答える 2

3

への電話

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

問題です。

3 番目のパラメーターが間違っています。

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

内部フォーマット

                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 を追加する必要があり、メインには引数が必要です。これを反映するようにコードを変更しました。

テストしたところ、Windows と Linux の両方で動作します。(実装が GL_ARB_debug_callback 拡張機能にアクセスできる場合は、それをコメントアウトするだけではありません)

于 2013-11-04T14:15:32.033 に答える