transparente pngs mit opengl/sdl



  • hallo,

    ich möchte ein transparentes png-bild in meiner sdl/opengl
    anwendung laden und anzeigen lassen.

    ich kann bei meiner anwendung zwischen opengl und sdl wählen -
    bei sdl werden die transparenten pngs perfekt angezeigt, bei opengl
    nicht.

    so lade ich das sdl-surface:

    SDL_Surface *bitmap;
    	bitmap = IMG_Load("test-p2.png");
        if (bitmap == NULL)
        {
            cout << "Could not load texture!" << endl;
    		SDL_Delay(5000);
            exit(0);
        }
    
        GLuint text_png = LoadTexture(bitmap,0);
    

    meine load_texture:

    GLuint BLevel::LoadTexture(SDL_Surface *surface,int trans)
     {
    	SDL_Surface* textureSurface;
    	SDL_Surface* convertedTexture;
    
    	textureSurface = surface;
    
    	// 2^n format
    	int oldX = textureSurface->w;
    	int oldY = textureSurface->h;
    	int paddedX = getNextPOT(textureSurface->w);
    	int paddedY = getNextPOT(textureSurface->h);
    
    	SDL_Rect targetRect;
    	targetRect.x = 0;
    	targetRect.y = 0;
    	targetRect.w = (paddedX - oldX) / 2;
    	targetRect.h = (paddedY - oldY) / 2;
    
    	//if(trans==1)
    		//SDL_SetColorKey(textureSurface, SDL_SRCCOLORKEY, getpixel(textureSurface,0,0));
    
    	convertedTexture = 
    		SDL_CreateRGBSurface(SDL_SWSURFACE,
    			paddedX, paddedY, 32,
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    			0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
    #else
    			0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
    #endif
    	SDL_BlitSurface(textureSurface, 0, convertedTexture, &targetRect);
    
    	GLuint texture;
    	glGenTextures(1, &texture);
    	glBindTexture(GL_TEXTURE_2D, texture);
    	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, GL_RGBA8,
    			convertedTexture->w, convertedTexture->h, 0, GL_RGBA,
    			GL_UNSIGNED_BYTE, convertedTexture->pixels);
    	SDL_FreeSurface(textureSurface);
    	SDL_FreeSurface(convertedTexture);
    
    	return texture;
    }
    

    und so rendere ich sie in meiner main-loop:

    glBindTexture(GL_TEXTURE_2D, text_png);
    
    		glEnable(GL_BLEND);
    		//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    		glBegin(GL_QUADS);
                    ...
            glEnd();
    
    		glDisable(GL_BLEND);
    

    das sollte doch eig. schon genügen oder? jedenfalls zeigt er das png-bild
    ohne jegliche transparent an...

    das ist das bild:
    http://www.babelduo.de/test-p2.png

    im photoshop/gimp sieht man auch die transparenz!

    was mache ich falsch?

    danke euch schonmal



  • dies ist einer der Gründe, warum ich nicht mit SDL arbeite. Ich kann dir so leider nicht sagen, wie es geht, aber ich kann dir eine alternative anbieten zu SDL, mit der du diese komplikationen nicht hast.

    GLFW
    kann ich da nur empfehlen, es kann mir den openGL kontext erzeugen, und Bilder mit tranzparenz laden, Diese beiden Aktionen sind da auch jeweils nur ein Befehl, also simpel genug. Einziger Nachteil, man müsste die Bilder nach TGA umkonvertieren, aber das ist ja dank gimp sehr leicht.

    weitere Infos
    http://glfw.sourceforge.net/



  • Also bei mir klappt das alles so, wie es soll, und zwar mit:

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    Hast du bei dir ja auskommentiert ...



  • ja, damit würd auch mit GLFW nicht klappen, aber trotzdem find ich GLFW irgendwie genial. bei SDL bekommt man ja unter Linux noch nicht einmal einen vernünftigen hardware Surface hin, ohne komplikationen bei und aus dem Grund hat es da bei mir die Sympathie verloren.



  • hmm danke euch - scheint recht ordentlich zu sein
    hab mich etwas auf der page umgesehen...

    allerdings habe ich nun keine lust mein gesamtes projekt
    umzustellen 🙂 außerdem liegt es doch eher an opengl als an sdl oder?

    @TomasRiker

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    

    hilft bei mir nur um eine farbe in einer textur
    transparent zu machen... ich möchte ja halbtransparente überläufe
    etc. aus png-bildern nutzen...

    oder machst du das?

    wenn ja wär es cool wenn du ein par code-schnipsel posten könntest...
    vom laden der texturen und rendern

    danke schonmal



  • ich fuehr folgende Codeschnipsel aus (und es funktioniert):

    if (SDL_Init(0) < 0)
    
    		throw EngineError("unable to initialize SDL");
    
    void Renderer::setup(int width, int height) const
    
    {
    
    	if (!(SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO))
    
    	{
    
    		if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
    
    			throw EngineError("unable to initialize the video subsystem");
    
    	}
    
    	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
    
    	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    
    	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    
    	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    
    	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    
    	if (SDL_SetVideoMode(640, 480, 0, SDL_OPENGL) == NULL)
    
    		throw EngineError("unable to initialize OpenGL");
    
    	glClearColor(CLEAR_COLOR[0], CLEAR_COLOR[1], CLEAR_COLOR[2], 0);
    
    	glClearDepth(1.0);
    
    //	glEnable(GL_DEPTH_TEST);
    
    	glShadeModel(GL_SMOOTH);
    
    	glEnable(GL_BLEND);
    
    	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    	resize(width, height);
    
    }
    
    void Renderer::resize(int width, int height) const
    
    {
    
    	glViewport(0, 0, width, height);
    
    	glMatrixMode(GL_PROJECTION);
    
    	glLoadIdentity();
    
    	glOrtho(0, width, 0, height, 0, 1);
    
    	glMatrixMode(GL_MODELVIEW);
    
    	glLoadIdentity();
    
    }
    
    SpritePtr SpriteManager::loadSprite(const char* file, int size) const
    
    {
    
    	if ((size & (size - 1)) != 0)
    
    	{
    
    		throw EngineError("Texture sizes need to be powers of 2");
    
    	}
    
    	SDL_Surface* s = IMG_Load(file);
    
    	if (!s)
    
    		throw EngineError(std::string("unable to load texture from ") + file, IMG_GetError());
    
    	// NOTE: for some reason the comiler won't accept GL_BGR(A)
    
    	// so right now the textures are wrongly colored.
    
    	int mode;
    
    	if (s->format->BytesPerPixel == 3)
    
    		mode = GL_RGB;
    
    	else if (s->format->BytesPerPixel == 4)
    
    		mode = GL_RGBA;
    
    	else
    
    	{
    
    		SDL_FreeSurface(s);
    
    		throw EngineError("Textures need to have 24 or 32 bpp");
    
    	}
    
    	// I have no idea why i do this, but transparency doesn't work if I don't ?-)
    
    	if ( (s->flags & SDL_SRCALPHA) == SDL_SRCALPHA )
    
    		SDL_SetAlpha(s, 0, SDL_ALPHA_TRANSPARENT);
    
    	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    
    	SpritePtr sprite(new Sprite());
    
    	// assume the image contains several sprites of SPRITE_SIZExSPRITE_SIZE
    
    	// copy each such sprite in a new surface and create a texture out of it
    
    	SDL_Rect srcRect = {0, 0, size, size};
    
    	SDL_Surface* spriteSurface = SDL_CreateRGBSurface(
    
    		SDL_SWSURFACE, size, size, s->format->BitsPerPixel,
    
    		// make sure to use RGBA, as (at least under Windows) I can't get GL_ABGR to work :(
    
    		#if SDL_BYTEORDER == SDL_LIL_ENDIAN
    
    			       0x000000FF,
    
    			       0x0000FF00,
    
    			       0x00FF0000,
    
    			       0xFF000000
    
    		#else
    
    			       0xFF000000,
    
    			       0x00FF0000,
    
    			       0x0000FF00,
    
    			       0x000000FF
    
    		#endif
    
           );
    
    	int n = s->w / size;
    
    	for (int i = 0; i < n; ++i)
    
    	{
    
    		srcRect.x = i * size;
    
    		SDL_FillRect(spriteSurface, 0, 0);
    
    		SDL_BlitSurface(s, &srcRect, spriteSurface, 0);
    
    		unsigned int textureid;
    
    		glGenTextures(1, &textureid);
    
    		glBindTexture(GL_TEXTURE_2D, textureid);
    
    		glTexImage2D(GL_TEXTURE_2D, 0, mode,
    
    			spriteSurface->w, spriteSurface->h, 0, GL_RGBA,
    
    			GL_UNSIGNED_BYTE, spriteSurface->pixels);
    
    		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    
    		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    
    		boost::shared_ptr<Sprite::Frame> f(new Sprite::Frame());
    
    		f->texture = textureid;
    
    		f->displayTime = FRAME_DURATION;
    
    		sprite->frames.push_back(f);
    
    	}
    
    	SDL_FreeSurface(spriteSurface);
    
    	SDL_FreeSurface(s);
    
    	return sprite;
    
    }
    
    void Sprite::draw(const Vector2D& pos, const Vector2D& size, State* state, float angle) const
    
    {
    
    	// change to next frame
    
    	unsigned int now = Clock::get().getAbsoluteTicks();
    
    	if (state->lastFrameChange == 0)
    
    		state->lastFrameChange = now;
    
    	while (now - state->lastFrameChange > frames[state->currentFrame]->displayTime)
    
    	{
    
    		state->lastFrameChange += frames[state->currentFrame]->displayTime;
    
    		++(state->currentFrame);
    
    		state->currentFrame %= frames.size();
    
    		state->lastFrameChange = now;
    
    	}
    
    	glEnable(GL_TEXTURE_2D);
    
    	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    
    	glBindTexture(GL_TEXTURE_2D, frames[state->currentFrame]->texture);
    
    	glPushMatrix();
    
    	glTranslatef(pos.x, pos.y, 0);
    
    	glRotatef(angle, 0, 0, 1);
    
    	// for some reason all the textures are always
    
    	// tilted by 90 degree ?-)
    
    	glRotatef(90, 0, 0, 1);
    
    	glTranslatef(-size.x/2, -size.y/2, 0);
    
    	glBegin(GL_QUADS);
    
    	glTexCoord2f(0, 0);
    
    	glVertex2f(0, 0);
    
    	glTexCoord2f(1, 0);
    
    	glVertex2f(size.x, 0);
    
    	glTexCoord2f(1, 1);
    
    	glVertex2f(size.x, size.y);
    
    	glTexCoord2f(0, 1);
    
    	glVertex2f(0, size.y);
    
    	glEnd();
    
    	glPopMatrix();
    
    	glDisable (GL_TEXTURE_2D);
    
    }
    


  • @Blue-Tiger

    ok?! habs übernommen und hat auf anhieb geklappt... guck nun mal
    was du anders hattest als ich bin mal gespannt 🙂

    danke dir! perfekt



  • [werbung]genau solche Beispiele sind ja bei GLFW haufenweise dabei[/werbung]



  • 😃

    wieso einfach wenns auch kompliziert geht 😉


Anmelden zum Antworten