SFML
SFML copied to clipboard
sf::RenderTarget::pushGLStates()/sf::RenderTarget::popGLStates() does not track last active texture.
Subject of the issue
When pushing/popping OpenGL state to run custom OpenGL code; SFML will fail to recall the correct active texture and therefore fail to pop the correct GL_TEXTURE
matrix mode. I provided my minimally complete reproduction of the error (barring any spelling mistakes). Essentially, my custom OpenGL code makes use of active texture units other than 0. So, after the first frame of rendering, SFML will begin reporting GL_STACK_UNDERFLOW
and GL_STACK_OVERFLOW
errors when pushing/popping glMatrixMode(GL_TEXTURE)
as the active texture is no longer being correctly tracked.
Your environment
- Microsoft Windows 10
- SFML v2.5.1 (from VCPKG)
- VS2019 v16.5.5
- Default compiler flags from CMake v3.20
Steps to reproduce
#include <gl/glew.h>
#include <SFML/Graphics.hpp>
int main()
{
sf::ContextSettings settings;
settings.depthBits = 24;
settings.stencilBits = 8;
sf::RenderWindow window{sf::VideoMode(1280, 720}, "test", 7, settings};
window.setActive(true);
glewInit();
sf::RenderTexture rtt1;
rtt1.create(window.getSize().x / 2, 720, settings);
sf::RenderTexture rtt2;
rtt2.create(window.getSize().x / 2, 720, settings);
sf::CircleShape circle;
circle.setPosition(300, 300);
circle.setRadius(100.0f);
circle.setFillColor(sf::Color::Blue);
// Configure sprites to render side-by-side horizontally.
sf::Sprite sprite1{rtt1.getTexture()};
sf::Sprite sprite2{rtt2.getTexture()};
sprite2.setPosition(window.getSize().x / 2.0f, 0.0f);
sf::Event e;
while(window.isOpen() == true)
{
while(window.pollEvent(e) == true)
{
switch(e.type)
{
case sf::Event::Closed:
window.close();
break;
default:
break;
}
rtt2.setActive(true);
rtt2.clear();
rtt2.pushGLStates();
rtt2.draw(circle);
rtt2.popGLStates();
rtt2.display();
// Custom OpenGL code narrowed down to the fact that glActiveTexture is being called with a non-zero texture unit.
rtt1.setActive(true);
constexpr auto myActiveTexture{4};
glActiveTexture(GL_TEXTURE0 + myActiveTexture);
rtt1.display();
rtt1.setActive(false);
window.setActive(true);
window.clear();
window.pushGLStates();
window.draw(sprite1);
window.draw(sprite2);
window.popGLStates();
window.display();
}
return 0;
}
Expected behavior
I would expect that SFML will push the correct active texture unit (which it does) and then restore this same texture unit as active (which it does not).
Actual behavior
After pushing the active texture with glMatrixMode(GL_TEXTURE); glPushMatrix();
SFML will reset the state to glActiveTexture(GL_TEXTURE0)
and then fail to restore the previous state with glPopMatrix();
According to @binary1248 it would make sense to also handle glClientActiveTexture and glActiveTexture.
Would you be interested in providing a fix for this?
@eXpl0it3r If anyone not working on this issue, can I try this? 😊
@Snowapril I don't think anyone is actively working on it, so your help would definitely be appreciated! 🙂
Sorry for late. I'm trying to solve this issue from today but stucked.. 😢
I thought that glPushAttrib(GL_ALL_ATTRIB_BITS)
push the glActiveTexture
and glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
push the glClientActiveTexture
, thus glActiveTexture(GL_TEXTURE0 + myActiveTexture);
in above reproduce code must be handled correctly. But it was not..
Could I get some hint about it?