SFML community forums

Help => Graphics => Topic started by: wintertime on November 10, 2013, 08:27:39 pm

Title: Alpha channel gets lost
Post by: wintertime on November 10, 2013, 08:27:39 pm
I was trying to do a forum search, but it only yields a Database error, so I try asking. ;)
I wanted to use a sf::RenderTexture, bind it and draw it to a window using OpenGL calls. The problem is I noticed the transparent parts of the Texture overwrite whats on the window when they should be invisible.
In the example code I wrote (I put it together from several classes in my code, added some globals to replace member variables, fixed it up and shortened it) the whole window should stay green, but it shows a red rectangle. It seems the alpha channel gets lost when using the texture or copying it?
#include "SFML/Window.hpp"
#include "SFML/OpenGL.hpp"
#include "SFML/Graphics.hpp"
#include <stdexcept>

int32_t windowx(1024);
int32_t windowy(768);
bool fullscreen(false);
sf::IntRect screenRect(0,0,windowx,windowy);

bool ProcessEvent(sf::Event& event) {
  if(event.type==sf::Event::Resized) {
    windowx=event.size.width;
    windowy=event.size.height;
    screenRect.width=windowx;
    screenRect.height=windowy;
    glViewport(0,0,event.size.width,event.size.height);
  }
  return event.type==sf::Event::KeyReleased;
}

void Draw(sf::Window& window) {
  glClearColor(0.0f,1.0f,0.0f,1.0f); // green
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(screenRect.left,screenRect.left+screenRect.width,screenRect.top+screenRect.height,screenRect.top,+1024.0,-1024.0);
  glMatrixMode(GL_MODELVIEW);

  sf::RenderTexture rtex;
  if(!rtex.create(32,32))
    throw std::runtime_error("error creating RenderTexture");
  rtex.clear(sf::Color(255,0,0,0)); // transparent red
  rtex.display();

  window.setActive();
  sf::Texture::bind(&(rtex.getTexture()));

  glEnable(GL_TEXTURE_2D);
  glColor4ub(255,255,255,255);
  const sf::IntRect& rect(screenRect);

  glBegin(GL_TRIANGLES);
  glTexCoord2f(0.f,0.f);
  glVertex2i(rect.left           ,rect.top);
  glTexCoord2f(0.f,1.f);
  glVertex2i(rect.left           ,rect.top+rect.height/2);
  glTexCoord2f(1.f,1.f);
  glVertex2i(rect.left+rect.width/2,rect.top+rect.height/2);
  glVertex2i(rect.left+rect.width/2,rect.top+rect.height/2);
  glTexCoord2f(1.f,0.f);
  glVertex2i(rect.left+rect.width/2,rect.top);
  glTexCoord2f(0.f,0.f);
  glVertex2i(rect.left           ,rect.top);
  glEnd();

  glColor4ub(0,0,0,0);
  sf::Texture::bind(nullptr);
  glDisable(GL_TEXTURE_2D);
}

int main(int argc,char* argv[]) {
  sf::Window window(sf::VideoMode(windowx,windowy),"Test",
                    fullscreen ? sf::Style::Fullscreen : sf::Style::Default,
                    sf::ContextSettings(0,0,0,2,1));
  window.setVerticalSyncEnabled(1);
  glViewport(0,0,windowx,windowy);

  sf::Event event;
  while(window.isOpen()) {
    Draw(window);
    window.display();

    while(window.pollEvent(event)) {
      if(ProcessEvent(event) || event.type==sf::Event::Closed)
        window.close();
    }
  }

  return 0;
}
 
Title: Re: Alpha channel gets lost
Post by: Nexus on November 10, 2013, 08:45:21 pm
Enable blending and choose the correct blending function.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

You may have to set additional states, don't assume SFML does it for you. Furthermore, keep OpenGL and SFML draw calls separate with the sf::Window functions, as shown in the OpenGL tutorial (http://www.sfml-dev.org/tutorials/2.1/window-opengl.php).

By the way, is there a specific reason why you use OpenGL, or is it just an experiment for learning purposes?
Title: Re: Alpha channel gets lost
Post by: wintertime on November 10, 2013, 09:19:54 pm
Ahh, thank you. Weird that its just forgetting such a simple thing as enabling blending.
Its gonna be a 3D game, thats why I use OpenGL everywhere. The only exception is converting some text strings to textures for the GUI when they are first used, then these textures get reused for many frames, but I deleted that part to shorten the example.
I read that tutorial already when searching for info, but what do you mean with more separating? I only use SFML Graphics module when a RenderTexture gets written to shortly and then reactivate the Window(its no RenderWindow because I only use OpenGL on it), so appeared no and should be no problem. I would assume the RenderTexture got its own context and it needs no resetGLStates call?
Title: Re: Alpha channel gets lost
Post by: Nexus on November 10, 2013, 09:30:19 pm
I meant the ...GLStates() functions, in case you mix OpenGL and SFML draw calls. Either you use them, or you keep track of all the OpenGL states on your own.