RenderTexture support?

Started by jungletoe, 15 August 2013, 23:03:24

jungletoe

Will render textures be supported with TGUI? They dont work at the moment when you substitute RenderWindows with tgui::Windows. See here:

#include <fstream>
#include <iostream>
#include <string>
#include <TGUI\TGUI.hpp>

int main ( int argc, char *argv[] )
{
// Create a new render-window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 384);
va[2].texCoords = sf::Vector2f(224, 384);
va[3].texCoords = sf::Vector2f(224, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();
}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);

// End the current frame and display its contents on screen
window.display();
}

return 0;
}

texus

I was already typing my reply as a mail, but I'll answer here instead.

I don't even see how it is technically possible that it works with sf::RenderWindow but not with tgui::Window.
tgui::Window just inherits from sf::RenderWindow.

The code works fine on my linux laptop. I am using TGUI v0.5.2 and SFML 2.1.

As a quick workaround, you could try using sf::RenderWindow and tgui::Form instead of tgui::Window.

jungletoe

Quote from: texus on 15 August 2013, 23:15:11
I don't even see how it is technically possible that it works with sf::RenderWindow but not with tgui::Window.
tgui::Window just inherits from sf::RenderWindow.

That's what's confusing me. I have the Intel graphics cards that were giving Laurent some troubles earlier, but it's all fixed in 2.1 (all examples work fine for me, just TGUI gives me problems).

I'll run some more tests and see what I can find ;)

jungletoe

Ok, just to confirm, this code doesn't give you any troubles (I altered it)? It just shows up as a black screen for me.


#include <fstream>
#include <iostream>
#include <string>
#include <TGUI\TGUI.hpp>

#include <fstream>
#include <iostream>
#include <string>
#include <TGUI\TGUI.hpp>

int main ( int argc, char *argv[] )
{
// Create a new render-window
tgui::Window window(sf::VideoMode(800, 600), "SFML window");

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 384);
va[2].texCoords = sf::Vector2f(224, 384);
va[3].texCoords = sf::Vector2f(224, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();
}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);

// End the current frame and display its contents on screen
window.display();
}

return 0;
}

texus


texus

I now tested it on both linux and windows 7 on a laptop with an intel HD 3000 graphics card. I can see the image.
The only thing I changed in the above code is the image filename.

I'm going to sleep now, so if you find anything else then I'll look into it tomorrow.

jungletoe

Hmm... that's very odd, mine is simply a black screen.

I'm using the workaround method. How would I draw the form?

texus

QuoteHow would I draw the form?
It has a draw method (instead of the drawGUI method from tgui::Window).
You can find the usage of tgui::Form at the bottom of the introduction tutorial (this reminds me that I should still move these tutorials to tgui.eu).

jungletoe

#8
Umm... I think tgui::Form.draw() has some issues...



Here is what it's supposed to look like:



The first image looks like it corrupted my tileset.png, which is loaded separately into an sf::Texture (I think it's pointing to an invalid piece of memory?). I'll try to whip up a complete and minimal example.


EDIT:
It also crashes later once I try to set a string for sf::Text, and the debugger points towards sf::Font::getGlyph().

jungletoe

#9
Here's the minimal example:

#include <fstream>
#include <iostream>
#include <string>
#include <TGUI\TGUI.hpp>

int main ( int argc, char *argv[] )
{
// Create a new render-window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
tgui::Form form(&window);

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 384);
va[2].texCoords = sf::Vector2f(224, 384);
va[3].texCoords = sf::Vector2f(224, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// Add GUI elements
tgui::Button* button = form.add<tgui::Button>();
button->load("rsc/GUI/Button");
button->setPosition(100, 100);
button->setText("Hello World");
button->callbackID = 1;
button->show();

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();

form.handleEvent(Event);
}

tgui::Callback callback;
while(form.getCallback(callback))
{
if((callback.callbackID == 1))
std::cout << "pressed\n";
}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);
form.draw();

// End the current frame and display its contents on screen
window.display();
}

return 0;
}


The screen shows up black-- only the button is rendered. Without form.draw(), there are no problems.

With form.draw()


Without form.draw() (this is what it's supposed to look like)


I'm running Windows 7 with the Intel Chipset Family drivers (all updated).

texus

#10
But you are definately not running the latest tgui and sfml versions.

You are passing a pointer to the Form constructor, I changed it to a reference on 21 August.

You should try again with TGUI v0.5.2 and SFML 2.1.

jungletoe

Quote from: texus on 16 August 2013, 09:35:37
But you are definately not running the latest tgui and sfml versions.

You are passing a pointer to the Form constructor, I changed it to a reference on 21 August.

You should try again with TGUI v0.5.2 and SFML 2.1.

I updated them yesterday before I made the post.



That was the download that was on the TGUI homepage. Was it the wrong version?

texus

The download on my site is the right version, but if "tgui::Form form(&window);" compiles then you are still using the header files and library of an older version.

jungletoe

#13
Derp, I was using the wrong version in my test/minimal example program. However, I was using the correct library in my actual program.

When switching up the versions, the problem went from simply not rendering the background, to full-fledged distortion again.


Without initializing the form:
int main ( int argc, char *argv[] )
{
// Create a new render-window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
//tgui::Form form(window);

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 459);
va[2].texCoords = sf::Vector2f(624, 459);
va[3].texCoords = sf::Vector2f(624, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// Add GUI elements
//tgui::Button* button = form.add<tgui::Button>();
//button->load("rsc/GUI/Button");
//button->setPosition(100, 100);
//button->setText("Hello World");
//button->callbackID = 1;
//button->show();

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();

//form.handleEvent(Event);
}

//tgui::Callback callback;
//while(form.getCallback(callback))
//{
//if((callback.callbackID == 1))
//std::cout << "pressed\n";
//}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);
//form.draw();

// End the current frame and display its contents on screen
window.display();
}

return 0;
}






Initializing the form:
int main ( int argc, char *argv[] )
{
// Create a new render-window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
tgui::Form form(window);

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 459);
va[2].texCoords = sf::Vector2f(624, 459);
va[3].texCoords = sf::Vector2f(624, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// Add GUI elements
tgui::Button* button = form.add<tgui::Button>();
button->load("rsc/GUI/Button");
button->setPosition(100, 100);
button->setText("Hello World");
button->callbackID = 1;
button->show();

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();

//form.handleEvent(Event);
}

tgui::Callback callback;
while(form.getCallback(callback))
{
if((callback.callbackID == 1))
std::cout << "pressed\n";
}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);
//form.draw();

// End the current frame and display its contents on screen
window.display();
}

return 0;
}






Drawing the form
int main ( int argc, char *argv[] )
{
// Create a new render-window
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window");
tgui::Form form(window);

// Create a new render-texture
sf::RenderTexture texture;
if (!texture.create(800, 600))
return -1;

// Create a textured vertex array
sf::VertexArray va;
va.resize(4);
va.setPrimitiveType(sf::Quads);

va[0].position = sf::Vector2f(0, 0);
va[1].position = sf::Vector2f(0, 600);
va[2].position = sf::Vector2f(800, 600);
va[3].position = sf::Vector2f(800, 0);

va[0].texCoords = sf::Vector2f(0, 0);
va[1].texCoords = sf::Vector2f(0, 459);
va[2].texCoords = sf::Vector2f(624, 459);
va[3].texCoords = sf::Vector2f(624, 0);

sf::Texture vatex;
vatex.loadFromFile("rsc/sprites.png");

// Add GUI elements
tgui::Button* button = form.add<tgui::Button>();
button->load("rsc/GUI/Button");
button->setPosition(100, 100);
button->setText("Hello World");
button->callbackID = 1;
button->show();

// The main loop
while (window.isOpen())
{
// Event handling
sf::Event Event;
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();

//form.handleEvent(Event);
}

tgui::Callback callback;
while(form.getCallback(callback))
{
if((callback.callbackID == 1))
std::cout << "pressed\n";
}

// Clear the whole texture with red color
texture.clear(sf::Color::Red);

// Draw stuff to the texture
texture.draw(va, &vatex);

// We're done drawing to the texture
texture.display();

// Now we start rendering to the window, clear it first
window.clear();

// Draw the texture
sf::Sprite sprite(texture.getTexture());
window.draw(sprite);
form.draw();

// End the current frame and display its contents on screen
window.display();
}

return 0;
}





As you can see, when drawing the form, it completely glitches out and produces all of these weird artifacts (the button graphic is replaced by the render texture?). Hovering over the button distorts it further (but only if I have more images loaded within the program). When initializing the form, it wipes everything and doesn't even draw the RenderTexture.

I have no clue why this would happen after looking through TGUI's source. I'm sorry that you have to debug all of this ;_;





texus

#14
It works fine for me, so I'm not sure what I can do about it.

You could try using a sprite instead of a vertex array (to rule out the possibility that it is about the vertex array instead of the render texture).

Other than that, you should try to find where it goes wrong, but I won't be able to help you with that.
Try to remove (place in comments) the contents of all functions in Form and see if that changes anything.
If that doesn't then you should continue with removing the functions in Group.

Edit: Can you find someone else to test this as well? I'm still not sure if there is a problem with your pc or whether more people have problems with it. I'll try on my pc with ati card tomorrow as well.

jungletoe

My friend just tested it on Windows 8. Same result as me.


texus

Ok, could you send me everything needed to reproduce this?
The source code, executable, images u use, even the compiled sfml and tgui libraries.

I want to test this with the exact same resources.

jungletoe

Quote from: texus on 16 August 2013, 22:59:28
Ok, could you send me everything needed to reproduce this?
The source code, executable, images u use, even the compiled sfml and tgui libraries.

I want to test this with the exact same resources.

Sure.
https://fbe.am/mJZ

Just place the SFML and TGUI folders in C:\ and you'll be set. That ZIP contains everything.



texus

#18
Great, but how the heck do I download it?
I'd say by logging in, but it won't register me.

Could you perhaps put it on something like dropbox?

EDIT: Nermind, I found it. Half of the page wasn't displayed because of AddBlock Plus.

texus

Now we are getting somewhere.
The executable produces the same result as you had.

jungletoe

Awesome. Sounds like progress :)

texus

#21
We have been looking at the wrong place.

Creating the Form and even calling the draw function causes no problem.

It is the button that is causing the problems. The image is drawn when the button is drawn (when the form is drawn). This is why you only saw something when form.draw was uncommented. If you remove the button->setPosition(...) call you will also notice that the small image isn't drawn on the same spot anymore.

So basically your texture is used as image for the button. The question that remains is why.

Edit:
I"ll continue running tests tomorrow. I'll check if it does the same on an ati card, if there is a difference when I rebuild the libraries (dynamic vs static), if it is solved with the different design in v0.6, ...
So hopefully I will be able to find, and if possible fix, this issue tomorrow.

jungletoe


jungletoe

By the way, I should mention that in my client I ran for my game, it didn't just draw the whole RenderTexture for all of the buttons/elements (tgui::Picture doesnt work as well), it drew the sources. So if I spliced up a frame within a PNG image, the whole PNG would show, not just the parts I selected. You can see this happen in the first picture I posted with tileset.png

texus

I found the issue.

You were linking to the static sfml libraries, but to the dynamic tgui libraries. This isn't possible (because tgui uses the SFML_STATIC as well). I am very surprised that this is even possible, I would have expected tons of errors or warnings in this situation.

So if you link to tgui-s.lib instead of tgui.lib then the problem should go away.