2012-03-24 72 views
2

我想要做的是從單通道數據數組中加載紋理到硬件中,並使用它的alpha通道將文本繪製到對象上。我使用的是opengl 4.Opengl:使用單通道紋理作爲alpha通道來顯示文本

如果我嘗試使用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,因爲GL_ALPHA從Opengl 4中刪除。 真正讓我困惑的是,爲什麼這個工作正常,當我從字形生成4 RGBA紋理,然後使用它的alpha通道?

+0

最後,我通過在調用glTexImage2D之前將數據轉換爲float來完成此工作。我相信我需要使用4字節倍數的數據格式。這就是爲什麼RGBA轉RGBA的原因(即使它是4x字節)以及爲什麼浮動數據也起作用。看來我無法使用GL_UNSIGNED_BYTE,除非它具有4通道數據的輸入和輸出。也許這是ATI驅動程序中的一個錯誤? – 2012-03-24 05:16:14

+1

好吧,我已經明白了這一點。我的代碼沒有錯,也沒有驅動程序中的錯誤。 GL_UNPACK_ALINGMENT需要設置爲1才能工作。它默認設置爲4。運行「glPixelStorei(GL_UNPACK_ALIGNMENT,1);」解決了我所有的問題。由於性能原因,我不確定它爲什麼設置爲4。我會調查。 – 2012-03-24 05:27:36

回答

3

我想你換了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)); 
+0

我的場景是紅色的,RGBA中的內部數據。如果我交換它們更糟。我也嘗試將內部文件數據設置爲紅色,它仍然顯示相同...我甚至嘗試了兩個通道,並且不起作用... – 2012-03-24 03:44:09

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

這在技術上是合法的,但是從來沒有一個好主意。

首先,您需要了解glTexImage2D的第三個參數是什麼。這是紋理的實際image format。你沒有創建一個通道的紋理;您正在用四個通道創建紋理。

接下來,您需要了解最後三個參數的作用。這些是pixel transfer parameters;他們描述了你給OpenGL的像素數據的外觀。

此命令說:「創建一個4通道紋理,然後上傳一些數據到只是的紅色通道,這個數據存儲爲一個無符號字節數組。上傳數據到一些紋理通道的在技術上是合法的,但幾乎從來都不是一個好主意。如果您要創建單通道紋理,則應使用單通道紋理。這意味着一個合適的圖像格式。

接下來,事情變得更加撲朔迷離:

new_texture->datasize = texture_width * texture_height*4; 

你使用「* 4」強烈建議您正在創建四通道的像素數據。但你只上傳單通道數據。其餘的計算同意這一點;你似乎沒有填寫任何數據通過full_texture[texture_width * texture_height]。所以你可能會分配比你需要的更多的內存。

最後一件事:總是使用大小的內部格式。切勿使用GL_RGBA;使用GL_RGBA8GL_RGBA4或其他。不要讓司機挑選,並希望它給你一個好的。

所以,正確上傳會是這樣:

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

FYI:在reinterpret_cast是不必要的;即使在C++中,指針也可以隱式轉換爲void*

+0

嗨,感謝您的信息。 4是我在加載4個通道和1個通道之間來回切換時的錯字。發帖時我搞砸了,我會編輯帖子。我已經應用了所有建議,不幸的是我仍然可以獲得相同的效果。 – 2012-03-24 03:56:41

+0

這非常奇怪,當我從4通道數據螺母創建4通道紋理時,如果我嘗試從4通道數據創建1通道紋理,它仍會混亂起來,我會得到適當的效果!這至少告訴我這個問題不是輸入數據,並且必須位於從一種數據到另一種數據的轉換中,或者在我的着色器代碼中。 – 2012-03-24 04:16:17

相關問題