OpenGL设置纹理透明色

3

我的问题是->如何在OpenGL中使颜色255,200,255透明?(透明意味着删除像素颜色255,200,255或任何有效方法...)

我的纹理加载函数来自这个教程-> http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=33

请注意,我不必使用Alpha通道,我有一组预制图像,具有自定义颜色(255,200,255),必须透明/删除像素...

我的程序中的一些.tga加载函数:

Texture AllTextures[1000];
typedef struct                                  
{
    GLubyte * imageData;                                    // Image Data (Up To 32 Bits)
    GLuint  bpp;                                            // Image Color Depth In Bits Per Pixel
    GLuint  width;                                          // Image Width
    GLuint  height;                                         // Image Height
    GLuint  texID;                                          // Texture ID Used To Select A Texture
    GLuint  type;                                           // Image Type (GL_RGB, GL_RGBA)
} Texture;  
bool LoadUncompressedTGA(Texture * texture, char * filename, FILE * fTGA)   // Load an uncompressed TGA (note, much of this code is based on NeHe's 
    {                                                                           // TGA Loading code nehe.gamedev.net)
        if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)                 // Read TGA header
        {                                       
            MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);     // Display error
            if(fTGA != NULL)                                                    // if file is still open
            {
                fclose(fTGA);                                                   // Close it
            }
            return false;                                                       // Return failular
        }   

        texture->width  = tga.header[1] * 256 + tga.header[0];                  // Determine The TGA Width  (highbyte*256+lowbyte)
        texture->height = tga.header[3] * 256 + tga.header[2];                  // Determine The TGA Height (highbyte*256+lowbyte)
        texture->bpp    = tga.header[4];                                        // Determine the bits per pixel
        tga.Width       = texture->width;                                       // Copy width into local structure                      
        tga.Height      = texture->height;                                      // Copy height into local structure
        tga.Bpp         = texture->bpp;                                         // Copy BPP into local structure

        if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32)))    // Make sure all information is valid
        {
            MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK);    // Display Error
            if(fTGA != NULL)                                                    // Check if file is still open
            {
                fclose(fTGA);                                                   // If so, close it
            }
            return false;                                                       // Return failed
        }

        if(texture->bpp == 24)                                                  //If the BPP of the image is 24...
        {
            texture->type   = GL_RGBA;                                          // Set Image type to GL_RGB
        }
        else                                                                    // Else if its 32 BPP
        {
            texture->type   = GL_RGBA;                                          // Set image type to GL_RGBA
        }

        tga.bytesPerPixel   = (tga.Bpp / 8);                                    // Compute the number of BYTES per pixel
        tga.imageSize       = (tga.bytesPerPixel * tga.Width * tga.Height);     // Compute the total amout ofmemory needed to store data
        texture->imageData  = (GLubyte *)malloc(tga.imageSize);                 // Allocate that much memory

        if(texture->imageData == NULL)                                          // If no space was allocated
        {
            MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK);    // Display Error
            fclose(fTGA);                                                       // Close the file
            return false;                                                       // Return failed
        }

        if(fread(texture->imageData, 1, tga.imageSize, fTGA) != tga.imageSize)  // Attempt to read image data
        {
            MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);      // Display Error
            if(texture->imageData != NULL)                                      // If imagedata has data in it
            {
                free(texture->imageData);                                       // Delete data from memory
            }
            fclose(fTGA);                                                       // Close file
            return false;                                                       // Return failed
        }

        // Byte Swapping Optimized By Steve Thomas
        for(GLuint cswap = 0; cswap < (int)tga.imageSize; cswap += tga.bytesPerPixel)
        {
            texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=texture->imageData[cswap] ^= texture->imageData[cswap+2];
        }

        fclose(fTGA);                                                           // Close file
        return true;                                                            // Return success
    }
    void LoadMyTextureTGA(int id,char* texturename)
    {
         //texturename ex: "Data/Uncompressed.tga"
        if(LoadTGA(&AllTextures[id], texturename))
        {
            //success      

                glGenTextures(1, &AllTextures[id].texID);               // Create The Texture ( CHANGE )
                glBindTexture(GL_TEXTURE_2D, AllTextures[id].texID);
                glTexImage2D(GL_TEXTURE_2D, 0, 3, AllTextures[id].width, AllTextures[id].height, 0, GL_RGB, GL_UNSIGNED_BYTE, AllTextures[id].imageData);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);


                if (AllTextures[id].imageData)                      // If Texture Image Exists ( CHANGE )
                {
                    free(AllTextures[id].imageData);                    // Free The Texture Image Memory ( CHANGE )
                }        
        }
        else
        {
           MessageBoxA(0,"Textures Loading Fail! Game will close now","Game Problem",0);
           exit(1);
        }

    }
3个回答

3
如果纹理的 bpp 值为 24 而不是 32(这意味着没有内置的 alpha 通道),则必须生成一个 32 位的 OpenGL 纹理,并将每个 texel 的 alpha 值设置为 255,当 tga 像素为 255,200,255 时。

那我该怎么做呢?我该如何启用Alpha透明度? - Tenev
在glTexImage2D()中用GL_RGBA代替GL_RGB。这样,即使在PNG中没有指定alpha通道,您也将始终拥有一个alpha通道。但现在的OpenGL会期望xh4个纹理元素,因此需要分配另一个缓冲区,就像(GLubyte )malloc(tga.imageSize);但是,需要分配xh*4个字节。然后对于每个纹理元素,将R、G和B分量从texture->imageData复制到新缓冲区中。如果这些RGB与所需值匹配,则将A设置为255。 - Calvin1602
请明确一点:如果texture->imageData是RGBARGBARGBARGBA...(即texture->bpp == 32),请不要更改您的代码;如果texture->imageData是RGBRGBRGBRGB...(即texture->bpp == 24),则您需要将其转换为RGBARGBARGBARGBA,并自行计算A值。 - Calvin1602

1

好的,如果您正在使用纹理,那么我假设您已经有了一个片段着色器。这其实很容易。

首先,在主程序中打开 alpha 混合:

glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

然后,在片段着色器中添加以下代码:

vec3 chromaKeyColor = texture(myTextureSampler,UV.xy).xyz;
float alpha;
if ((chromaKeyColor.x <= 0.01) && (chromaKeyColor.y <= 0.01) && (chromaKeyColor.z <= 0.01)){
    alpha = 0.;
}
else
{
    alpha = 1.0;
}
color = vec4(texture(myTextureSampler,VertexOut.texCoord.xy).xyz,alpha);

上述代码将黑色设置为色度键。 (在0.01的阈值范围内)您可以通过查找其RGB值来选择另一种颜色。 如果它不是色度键颜色,则将Alpha设置为完全(1.0)。

0

OpenGL和色键可能有点棘手。使用1位Alpha可能更容易,但我见过SDL用于像您描述的颜色键控。这个线程可能会对您有所帮助。


我不会使用“棘手”这个词,我会说OpenGL直接不支持颜色键控,你需要采用手动方式,使用着色器或在上传glTexImage2D之前将alpha = 0.0设置为透明像素。 - Dr. Snoopy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接