4

私がやろうとしているのは、テクスチャを単一チャネル データ配列からハードウェアにロードし、そのアルファ チャネルを使用してオブジェクトにテキストを描画することです。私はopengl 4を使用しています。

4 チャンネルの RGBA テクスチャを使用してこれを実行しようとすると、問題なく動作しますが、何らかの理由で 1 つのチャンネルだけを読み込もうとすると、画像が文字化けしてしまい、その理由がわかりません。次のコードを使用して、一連のグリフのテクスチャ ビットマップ データを 1 つのテクスチャに結合することにより、テクスチャを作成します。

int texture_height = max_height * new_font->num_glyphs;
int texture_width = max_width;

new_texture->datasize = texture_width * texture_height;
unsigned char* full_texture = new unsigned char[new_texture->datasize];

// prefill texture as transparent
for (unsigned int j = 0; j < new_texture->datasize; j++)
    full_texture[j] = 0;

for (unsigned int i = 0; i < glyph_textures.size(); i++) {
    // set height offset for glyph
    new_font->glyphs[i].height_offset = max_height * i;
    for (unsigned int j = 0; j < new_font->glyphs[i].height; j++) {
        int full_disp = (new_font->glyphs[i].height_offset + j) * texture_width;
        int bit_disp = j * new_font->glyphs[i].width;
        for (unsigned int k = 0; k < new_font->glyphs[i].width; k++) {
            full_texture[(full_disp + k)] =
                    glyph_textures[i][bit_disp + k];
        }
    }
}

次に、テクスチャ データの呼び出しをロードします。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));

私のフラグメント シェーダーは次のコードを実行します。

#version 330

uniform sampler2D texture;

in vec2 texcoord;
in vec4 pass_colour;

out vec4 out_colour;

void main()
{
float temp = texture2D(texture, texcoord).r;
out_colour = vec4(pass_colour[0], pass_colour[1], pass_colour[2], temp);
}

テクスチャから生成されたとわかる画像が得られますが、ひどく歪んでいて、その理由がわかりません。ところで、GL_ALPHA が Opengl 4 から削除されたため、GL_RED を使用しています。本当に混乱しているのは、グリフから 4 RGBA テクスチャを生成し、そのアルファ チャネルを使用すると、これが正常に機能する理由です??

4

2 に答える 2

15
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));

これは技術的には合法ですが、決して良い考えではありません。

まず、3 番目のパラメーターが何であるかを理解する必要がありますglTexImage2D。これがテクスチャの実際の画像形式です。1 つのチャンネルでテクスチャを作成しているわけではありません。4 つのチャネルを持つテクスチャを作成しています。

次に、最後の 3 つのパラメーターの機能を理解する必要があります。これらはピクセル転送パラメータです。OpenGL に渡すピクセル データがどのように見えるかを記述します。

このコマンドは、「4 チャンネルのテクスチャを作成し、赤のチャンネルだけにデータをアップロードします。このデータは、符号なしバイトの配列として保存されます」と言っています。テクスチャの一部のチャネルのみにデータをアップロードすることは、技術的には合法ですが、良い考えはほとんどありません。シングル チャネル テクスチャを作成している場合は、シングル チャネル テクスチャを使用する必要があります。そして、それは適切な画像フォーマットを意味します。

次に、事態はさらに混乱します。

new_texture->datasize = texture_width * texture_height*4;

「*4」の使用は、4 チャンネルのピクセル データを作成していることを強く示唆しています。ただし、1 チャネルのデータしかアップロードしていません。残りの計算はこれに同意します。データパスを入力したことがないようですfull_texture[texture_width * texture_height]。そのため、必要以上のメモリを割り当てている可能性があります。

最後に 1 つ:常にサイズ設定された内部フォーマットを使用してください。ただ使用しないでくださいGL_RGBAGL_RGBA8またはGL_RGBA4何でも使用します。ドライバーに選択させないでください。それがあなたに良いものを与えることを願っています。

したがって、正しいアップロードは次のようになります。

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, full_texture);

参考までに:reinterpret_castは不要です。C++ でも、ポインターは暗黙的に に変換できますvoid*

于 2012-03-24T03:43:08.253 に答える
4

glTexImage2d()の「内部フォーマット」と「フォーマット」パラメータを交換したと思います。つまり、テクスチャ オブジェクトに RGBA が必要であるが、その逆ではなく、ファイル データに RED しかないことを伝えました。

呼び出しを次のように置き換えてみてください。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture->x, texture->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));
于 2012-03-24T03:36:02.330 に答える