Skip to main content
GameDev.net gamedev.net
🔒 Locked 🤖 Godot

How to create empty transparent texture?

Started by wagner_fsoares Mar 22, 2010 at 9:15 PM 12 replies 6.5k views
Original Post
wagner_fsoares
wagner_fsoares
Ok, I have this code:

GLuint LowLayer::CreateBlankTexture(Vector2 size)
{
    GLuint tempTexture;
    unsigned char* pixels = new unsigned char[(int)size.X * (int)size.Y * 4];
    for (int i = 0; i < (int)size.X * (int)size.Y * 4; i++)
        pixels = 0;
    glGenTextures(1, &tempTexture);
    glBindTexture(GL_TEXTURE_2D, tempTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, 4, (int)size.X, (int)size.Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    delete[] pixels;
    return tempTexture;
}
It creates an empty texture so I can draw onto it. I've a function that "optimizes" tile maps, it generates splitted 512x512 images through the built tile map. On my laptop it just works as expected, but on my desktop, what should be a transparent area is black, and it covers what was behind. Could it be a video card issue? I really don't think so, because images drawn directly on the screen are ok. Just for the record, the laptop has an Intel video card, the desktop has a NVidia video card.
swiftcoder
swiftcoder
Quote:
Original post by wagner_fsoares
On my laptop it just works as expected, but on my desktop, what should be a transparent area is black, and it covers what was behind.
Is blending enabled, and what blend mode do you have set? OpenGL doesn't handle transparency unless you explicitly enable blending, and set the blending mode to a reasonable value.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
wagner_fsoares
wagner_fsoares
Do you mean when creating the empty texture?
Because during drawing, I enable it and set the blendfunc to:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
MarkS
MarkS
Though unlikely, it is possible that the card (or driver) is having a problem calculating the resulting color value with the components all set to zero. Again, this shouldn't be an issue. However, try:
for(int i = 0;i < (int)size.X * (int)size.Y * 4;i += 4)
{
pixels = 0xFF;
pixels[i + 1] = 0xFF;
pixels[i + 2] = 0xFF;
pixels[i + 3] = 0x00;
}

and see if it still happens. If that works, you need to contact your card manufacturer.
No, I am not a professional programmer. I'm just a hobbyist having fun...
wagner_fsoares
wagner_fsoares
It didn't work.
This must be a video issue.
I tried on a PC with an ATI card and it works ok.

Here is the problematic game:
http://www.calangodev.com/arquivos/Plataformer.7z
(use the arrows to move and jump).
There are 2 tilemaps, one for the background (the sky) and one for the ground.
MarkS
MarkS
The background is black. I take it that is not what I should be seeing?

If I understand what you are trying to do, you are setting any foreground tiles that are empty to an empty texture, correct? If so, it would be better to set them to an unused tile ID, like -1, and then skip any tiles with that ID when drawing the tile map. Also, make absolutely sure that you are not setting the alpha values of the background textures.

I use an nVidia GTX 260. I wrote some code to test a fully transparent texture and it works in all cases. This leads me to believe that your problem is somewhere else in your code.
No, I am not a professional programmer. I'm just a hobbyist having fun...
wagner_fsoares
wagner_fsoares
That's exactly what I'm doing.
And I'm skipping null tiles too.
So the black area is just plain empty texture area.
It couldn't be just code, because the background is being shown on my laptop and on another desktop PC (with ATI video card).
You said you have a nVidia card too, just like my desktop PC (GeForce 8600), that makes me wonder if nVidia card have any problem with OpenGL.

I didn't get what you said about setting alpha values, I'm just creating an empty texture with tha method I told before, just drawing (or skipping) the tiles on the screen and then copying that into a texture.

I think I'll contact nVidia about this problem if I can't solve it.
Tell me, would it help if I paste my "optimized tile creation" method here?

Thanks for the replies!
Stani R
Stani R
Hard to say what's wrong from the little code you provided. At the very least, that method looks correct to me. But chances are very high that the problem is with your code, not with the card. OpenGL drivers for nVidia are very good, and I also have the same card as you and run many OpenGL programs on it without problems, including transparent textures in my own programs. You can try talking to nVidia of course but you are unlikely to get a satisfactory answer - it's not their job to debug your program. It might help if you post screenshots both from when it's working and from when it's not working, and also provide more code to show what you're doing.
MarkS
MarkS
I'm really curious why the transparent textures are needed. I'm making a tile engine that supports multiple layers with alpha blending and I never even thought to use empty textures.

The way to go about this is to render the background layer (which should not have any empty tiles) and then the foreground layers, skipping any empty tiles. It should just work, unless something in your code is messed up.
No, I am not a professional programmer. I'm just a hobbyist having fun...
wagner_fsoares
wagner_fsoares
The main problem is that my tiles are 32x32, and I'm drawing 2 tilemaps ((640 / 32) * (480 / 32)) * 2 tiles.
On my laptop I get 58 FPS, on my desktop I get more than 500, so I thought on optimizing it by generating bigger tiles from the generated map.
Here is how it is when it's working:


And here is the method that generates them:
void TileMap::Build(string textureName, Vector2 tileSize, Vector2 mapDimension){    Texture *texture = TextureManager::Instance()->Get(textureName);    if (texture != NULL)    {        m_tileSize = tileSize;        m_numTiles.X = texture->GetSize().X / tileSize.X;        m_numTiles.Y = texture->GetSize().Y / tileSize.Y;        m_texture = texture;        m_mapDimension = mapDimension;        if (m_collisionMap.empty())            m_collisionMap.resize(m_numTiles.X * m_numTiles.Y, 0);        int mapsizeX = Utils::LowestPowerof2(IGameVars()->GetGameResolution().X);        int mapsizeY = Utils::LowestPowerof2(IGameVars()->GetGameResolution().Y);        int maxsizeX = (mapsizeX / (int)m_tileSize.X) * (int)m_tileSize.X;        int maxsizeY = (mapsizeY / (int)m_tileSize.Y) * (int)m_tileSize.Y;        glViewport(0, 0, mapsizeX, mapsizeY);        glMatrixMode(GL_PROJECTION);        glLoadIdentity();        glOrtho(0, mapsizeX, mapsizeY, 0, 0, 1);        glMatrixMode(GL_MODELVIEW);        glLoadIdentity();        glClear(GL_COLOR_BUFFER_BIT);        Rect lastRect = Rect(            ((m_tileMap.size() - 1) % (int)m_mapDimension.X) * m_tileSize.X,            ((m_tileMap.size() - 1) / (int)m_mapDimension.X) * m_tileSize.Y,            m_tileSize.X, m_tileSize.Y        );        m_builtTextureTiles.X = ((lastRect.X + lastRect.Width) / maxsizeX) + 1;        m_builtTextureTiles.Y = ((lastRect.Y + lastRect.Height) / maxsizeY) + 1;        Vector2 numTilesperBuiltTiles = Vector2(maxsizeX / (int)m_tileSize.X, maxsizeY / (int)m_tileSize.Y);        int i = 0;        while (i < m_tileMap.size())        {            GLuint tempTexture = LowLayer::CreateBlankTexture(Vector2(maxsizeX, maxsizeY));            bool lineFeed = true;                        int x = i % (int)m_mapDimension.X;            int am = (int)m_mapDimension.X - x;            if (am >= numTilesperBuiltTiles.X)            {                am = numTilesperBuiltTiles.X;                lineFeed = false;            }            int y = i / (int)m_mapDimension.X;            int an = (int)m_mapDimension.Y - y;            if (an >= numTilesperBuiltTiles.Y)                an = numTilesperBuiltTiles.Y;            for (int j = 0; j < am * an; j++)            {                int tile = i + (j % am) + ((j / am) * (int)m_mapDimension.X);                if (m_tileMap[tile] != 0)                {                    Rect destinationRect = Rect(                        (j % am) * m_tileSize.X,                        (j / am) * m_tileSize.Y,                        m_tileSize.X, m_tileSize.Y                    );                    int tileDraw = m_tileMap[tile] - 1;                    LowLayer::DrawGLTexture(m_texture->GetData(), m_texture->GetSize(),                        Rect(                            (tileDraw % (int)m_numTiles.X) * m_tileSize.X,                            (tileDraw / (int)m_numTiles.X) * m_tileSize.Y,                            m_tileSize.X, m_tileSize.Y                        ),                        Vector2::Zero(),                        destinationRect, Vector2(1, 1), 0, Color::White(), Flip::None);                }            }            glFlush();            glBindTexture(GL_TEXTURE_2D, tempTexture);            glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, mapsizeX, mapsizeY, 0);            m_builtTexture.push_back(Texture(tempTexture, maxsizeX, maxsizeY));            glClear(GL_COLOR_BUFFER_BIT);            i += am;            if (lineFeed)                i += ((an - 1) * (int)m_mapDimension.X);        }    }#ifdef _DEBUG    else    {        cout << "TileMap::Build ERROR: The texture '" << textureName << "' does not exist in the TextureManager.\n";    }#endif}
wagner_fsoares
wagner_fsoares
As no solution has been found yet, I just changed OpenGL texture generation code to SDL code, I'm generating the optimized surface and then I generate an OpenGL texture from it.
It's a solution, but I'd be glad if it was using OpenGL, oh well.
Thanks anyway guys!
iliak
iliak
Quote:
Original post by wagner_fsoares
Ok, I have this code:

GLuint LowLayer::CreateBlankTexture(Vector2 size){    GLuint tempTexture;    unsigned char* pixels = new unsigned char[(int)size.X * (int)size.Y * 4];    for (int i = 0; i < (int)size.X * (int)size.Y * 4; i++)        pixels = 0;    glGenTextures(1, &tempTexture);    glBindTexture(GL_TEXTURE_2D, tempTexture);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);    glTexImage2D(GL_TEXTURE_2D, 0, 4, (int)size.X, (int)size.Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);    delete[] pixels;    return tempTexture;}


If you try :
glTexImage2D(GL_TEXTURE_2D, 0, 4, (int)size.X, (int)size.Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);


It would create an empty texture.
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
V-man
V-man
glTexImage2D(GL_TEXTURE_2D, 0, 4, (int)size.X, (int)size.Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, null);

leaves the pixels undefined so you might in fact get junk.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.