Hi,
I have encountered a problem with rendering textures on a laptop with integrated graphics (Lenovo Thinkpad T450s with Intel HD 5500). I'm using latest stable SFML (compiled myself). The problem is reproduced in the code below. In short:
1. Render a texture with standard opengl vertex arrays.
2. Render text with SFML, including pop/push of opengl context.
3. Render another opengl vertex array. This doesn't work on HD 5500, the texture isn't rendered. Sometimes you can see some flickering as if the missing texture is rendered and then instantly cleared again. If I don't render the text, the second texture renders ok. When trying on another computer everything works fine. See attached images for working/failed results on two different computers.
Having searched for a solution I get the impression that there are known compatibility problems with Intel graphics and SFML. This feels like something that might be very hard to fix. Still, there's always the possibility that my code is borked? Or maybe there is some workaround?
#include <iostream>
#include "SFML/Graphics.hpp"
#include "SFML/OpenGL.hpp"
struct Vertex{
public:
int vertexX, vertexY;
float textureX, textureY;
float colorR, colorG, colorB, colorA;
};
int main(){
sf::RenderWindow* window = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "SFML Window", sf::Style::Default);
sf::Image* textureAtlas = new sf::Image();
if(!textureAtlas->loadFromFile("data/img/tile.png")){
std::cout << "File not found: " << "data/img/tile.png" << std::endl;
}
sf::Font* currentFont = new sf::Font();
if(!currentFont->loadFromFile("data/fnt/Arial Unicode MS.ttf")){
std::cout << "File not found: " << "data/fnt/Arial Unicode MS.ttf" << std::endl;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, 800, 600);
glOrtho(0, 800, 600, 0, 0, 1);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
int textureAtlasWidth = textureAtlas->getSize().x;
int textureAtlasHeight = textureAtlas->getSize().y;
glScalef(1.0 / textureAtlasWidth, 1.0 / textureAtlasHeight, 1);
unsigned int textureAtlasGLHandle;
glGenTextures(1, &textureAtlasGLHandle);
glBindTexture(GL_TEXTURE_2D, textureAtlasGLHandle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureAtlasWidth, textureAtlasHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureAtlas->getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
Vertex vertex;
std::vector<Vertex> textureVertexArray;
while (window->isOpen()){
sf::Event event;
while (window->pollEvent(event)){
if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
window->close();
}
glClear(GL_COLOR_BUFFER_BIT);
// Draw first texture. This always works.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
vertex.colorR = 1;
vertex.colorG = 1;
vertex.colorB = 1;
vertex.colorA = 1;
vertex.vertexX = 0;
vertex.vertexY = 0;
vertex.textureX = 0;
vertex.textureY = 0;
textureVertexArray.push_back(vertex);
vertex.vertexX = 64;
vertex.vertexY = 0;
vertex.textureX = 64;
vertex.textureY = 0;
textureVertexArray.push_back(vertex);
vertex.vertexX = 64;
vertex.vertexY = 64;
vertex.textureX = 64;
vertex.textureY = 64;
textureVertexArray.push_back(vertex);
vertex.vertexX = 0;
vertex.vertexY = 64;
vertex.textureX = 0;
vertex.textureY = 64;
textureVertexArray.push_back(vertex);
if(textureVertexArray.size() > 0){
glVertexPointer(2, GL_INT, sizeof(Vertex), &textureVertexArray[0].vertexX);
glColorPointer(4, GL_FLOAT, sizeof(Vertex), &textureVertexArray[0].colorR);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &textureVertexArray[0].textureX);
glDrawArrays(GL_QUADS, 0, textureVertexArray.size());
textureVertexArray.clear();
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
// Draw text
window->pushGLStates();
sf::Text* sfText = new sf::Text("Hello glitch", *currentFont, 16);
sf::Color color(255, 255, 255, 255);
sfText->setColor(color);
sfText->move(32, 64);
window->draw(*sfText); // If this line is disabled the texture below will render.
delete sfText;
window->popGLStates();
// Draw second texture. This texture will not be drawn on Intel HD 5500.
// If the window->draw() function above is disabled, the texture renders ok.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
vertex.colorR = 1;
vertex.colorG = 1;
vertex.colorB = 1;
vertex.colorA = 1;
vertex.vertexX = 64;
vertex.vertexY = 0;
vertex.textureX = 0;
vertex.textureY = 0;
textureVertexArray.push_back(vertex);
vertex.vertexX = 128;
vertex.vertexY = 0;
vertex.textureX = 64;
vertex.textureY = 0;
textureVertexArray.push_back(vertex);
vertex.vertexX = 128;
vertex.vertexY = 64;
vertex.textureX = 64;
vertex.textureY = 64;
textureVertexArray.push_back(vertex);
vertex.vertexX = 64;
vertex.vertexY = 64;
vertex.textureX = 0;
vertex.textureY = 64;
textureVertexArray.push_back(vertex);
if(textureVertexArray.size() > 0){
glVertexPointer(2, GL_INT, sizeof(Vertex), &textureVertexArray[0].vertexX);
glColorPointer(4, GL_FLOAT, sizeof(Vertex), &textureVertexArray[0].colorR);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &textureVertexArray[0].textureX);
glDrawArrays(GL_QUADS, 0, textureVertexArray.size());
textureVertexArray.clear();
}
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
window->display();
}
delete textureAtlas;
delete window;
delete currentFont;
}