[英]Opengl: Use single channel texture as alpha channel to display text
我想要做的是從單個通道數據陣列將紋理加載到硬件中,並使用它的alpha通道將文本繪制到對象上。 我正在使用opengl 4。
如果我嘗試使用4通道RGBA紋理這樣做,它可以很好地工作,但無論出於何種原因,當我嘗試加載單個通道時,我只會得到一個亂碼圖像,我無法找出原因。 我通過將一系列字形的紋理位圖數據與以下代碼組合成單個紋理來創建紋理:
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_RED因為從Opengl 4中刪除了GL_ALPHA。真正令我困惑的是為什么當我從字形生成4 RGBA紋理然后使用它的alpha通道時它能正常工作?
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));
這在技術上是合法的,但絕不是一個好主意。
首先,您需要了解glTexImage2D
的第三個參數是什么。 這是紋理的實際圖像格式 。 您不是使用一個通道創建紋理; 你正在創建一個有四個通道的紋理。
接下來,您需要了解最后三個參數的作用。 這些是像素傳輸參數 ; 他們描述了你給OpenGL的像素數據是什么樣的。
該命令是說,“創建一個4信道的質地,那么一些數據上傳到只是紅色通道。該數據被存儲為無符號字節數組”。 將數據上傳到紋理的某些通道在技術上是合法的,但幾乎從來不是一個好主意。 如果要創建單通道紋理,則應使用單通道紋理 。 這意味着適當的圖像格式。
接下來,事情變得更加混亂:
new_texture->datasize = texture_width * texture_height*4;
您使用“* 4”強烈建議您創建四通道像素數據。 但您只需上傳單通道數據。 其余的計算都同意這一點; 你似乎沒有填寫任何數據傳遞full_texture[texture_width * texture_height]
。 所以你可能會分配比你需要的更多的內存。
最后一件事: 始終使用大小的內部格式。 永遠不要只使用GL_RGBA
; 使用GL_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*
。
我想你交換了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));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.