SFML community forums

Help => Graphics => Topic started by: bobingabout on March 10, 2014, 11:08:14 am

Title: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 11:08:14 am
As the attached images show, when I draw into the RenderTexture, I don't apear to actually have anything drawn into the Texture. Am I doing something wrong?

I basically followed this tutorial.
Code: [Select]
// create a 500x500 render-texture
sf::RenderTexture renderTexture;
if (!renderTexture.create(500, 500))
{
    // error...
}

// drawing uses the same functions
renderTexture.clear();
renderTexture.draw(sprite); // or any other drawable
renderTexture.display();

// get the target texture (where the stuff has been drawn)
sf::Texture& texture = renderTexture.getTexture();

// draw it to the window
sf::Sprite sprite(texture);
window.draw(sprite);

.create, .clear, .draw, .display to create the texture, .getTexture to create a sf::Texture to use on a sprite, simple enough.

so I did this, Don't worry if it looks complicated, this is mostly just copy paste from another area that I know works, that creates a std::vector of sprites, and draws each and every one of them every frame. I thought this would be a better way of managing things.

Code: [Select]
void CTextObject::createtext()
{
if(font != NULL && text.size() > 0)
{
sf::IntRect rect;
destpos.x = cursor.x;
destpos.y = 0;

uint32 maxwidth = stringwidth();
uint32 maxheight = stringheight();
uint32 width = 0;
uint32 len = text.length();
uint32 i;

sf::Sprite charsprite;
charsprite.setTexture(*font);
charsprite.setColor(sf::Color(255,255,255)); // shouldn't really need this

texttexture.create(maxwidth, maxheight);
texttexture.clear();//(sf::Color(0,0,0,0)); // transparant clear // revert to black so I can see it

for(i = 0; text[i] != '\r' && text[i] != '\n' && i < len ; i++)
{
if(unispace) width += font->size().x;
else width += font->width(text[i]);
}
if(width > 0)
{
if(right) destpos.x = (float)(maxwidth - width);
if(centered) destpos.x = (float)(maxwidth - width)/2;
if(left) destpos.x = 0;
}
for(i = 0; i < len; i++)
{
if(text[i] == '\r' || text[i] == '\n')
{
destpos.x = 0;
width = 0;
if(text[i] == '\n')
{
destpos.y += font->size().y;
}
for(uint32 j = i + 1; text[j] != '\r' && text[j] != '\n' && j < len; j++)
{
if(unispace) width += font->size().x;
else width += font->width(text[j]);
}
if(width > 0)
{
if(right) destpos.x = (float)(maxwidth - width);
if(centered) destpos.x = (float)(maxwidth - width)/2;
if(left) destpos.x = 0;
}
}
else
{
rect = font->getcharrect(text[i]);
charsprite.setTextureRect(rect);
charsprite.setPosition((float)(destpos.x), (float)(destpos.y));
texttexture.draw(charsprite);

if(unispace) destpos.x += font->size().x;
else destpos.x += font->width(text[i]);
}
}
destpos.y += cursor.y;
texttexture.display();
textsprite.setTexture(texttexture.getTexture());
textsprite.setPosition(pos);
}
}

I have placed breakpoints on the clear, draw and display lines to make sure my code actually runs through each step, and it does apear to be running correction, but as you can see by the attachments, it doesn't work.


am I doing something wrong?
Title: Re: sf::RenderTexture problems.
Post by: eXpl0it3r on March 10, 2014, 11:19:18 am
Please create a minimal and complete example, that is start a fresh project, add a render texture, draw some text to it, draw to the screen.
If that works, then there's something going wrong in your code. Thus you'll have to go through your code.

Having to go through a few pieces of code doesn't help much, especially when things like window.display() are missing most likely due to premature copying.

The whole createtext function doesn't really matter for the problem of render texture, thus it's of no use to us, if you post the full function. Try to isolate the issue first. ;)
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 11:27:52 am
I have actually been puzzling over this for a few days, it's not like I failed, and instantly came here to ask for help.

The "How it should look" is a screenshot from an output of another peice of code, as described, creating a vector array of sprites, and drawing all of them each loop.

The biggest thing that kept bugging me was... "Am I drawing it inside the RenderTexture?"



While I'm here, before I look at it again, another question:

Say I want to resize my RenderTexture, how would I go about doing that? just use create(size.x, size.y) again?

Because when I do that, I don't even get the black square.
Title: Re: sf::RenderTexture problems.
Post by: eXpl0it3r on March 10, 2014, 12:04:57 pm
The "How it should look" is a screenshot from an output of another peice of code, as described, creating a vector array of sprites, and drawing all of them each loop.
Well you then might want to clearify what you're actually trying to do. Drawing some sprites and posting some possible output doesn't help us understand what the goal of it is.

The biggest thing that kept bugging me was... "Am I drawing it inside the RenderTexture?"
If you're unsure how to properly use a render texture, then try it in an isolated situation, with no other code than just the render texture. That way you can familiarize yourself and test that it actually works.

Say I want to resize my RenderTexture, how would I go about doing that? just use create(size.x, size.y) again?
Yes, you simply create a larger render texture.

Because when I do that, I don't even get the black square.
Well you must be doing something wrong somewhere, but it's impossible to tell from our side. ;)
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 12:22:50 pm
Because when I do that, I don't even get the black square.
Well you must be doing something wrong somewhere, but it's impossible to tell from our side. ;)
Basically... it runs through this loop again to recreate everything.

First run through: Black square.
Second run through: Nothing at all.

in any case, I'll look into it again, as said. I'm currently at work, so doing this around other things.
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 04:13:56 pm
Okay, I made a little test program when I managed to find the time for it. This is the entire code of the program:
Code: [Select]
#include <SFML/Graphics.hpp>


int main()
{
freopen ( "Error.log", "wt" , stderr );

sf::RenderWindow window;
window.create(sf::VideoMode(800, 533), "SFML Window", sf::Style::None);
window.setFramerateLimit(60);
window.setVerticalSyncEnabled(true);

sf::Texture traintexture;
traintexture.loadFromFile("train.png");
sf::Sprite trainsprite;
trainsprite.setTexture(traintexture);
trainsprite.setPosition(0,0);

sf::RenderTexture traintex2;
traintex2.create(800,533);
traintex2.clear();
traintex2.draw(trainsprite);
traintex2.display();
sf::Sprite trainsprite2;
trainsprite2.setTexture(traintex2.getTexture());
trainsprite2.setPosition(0,0);

sf::Event Event;

while (window.isOpen())
{
while (window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
window.close();
if (Event.type == sf::Event::KeyPressed && Event.key.code == sf::Keyboard::Escape)
window.close();
}
window.clear(sf::Color(255,255,255));

// window.draw(trainsprite);
window.draw(trainsprite2);

window.display(); // draw the screen, probably the last thing in the main loop
}
return EXIT_SUCCESS;
}

And the results are the attached files.
Note:
Image1.jpg was produced from trainsprite, which is the file loaded into a texture, linked to a sprite, then drawn.
Image2.png was produced from trainsprite2, which draws trainsprite into a rendertexture, links it to a sprite, then draws that.

Both cropped for upload size reasons.

What's going wrong?
Title: Re: sf::RenderTexture problems.
Post by: eXpl0it3r on March 10, 2014, 04:53:28 pm
What is your graphics card? Is your driver uptodate?

Not related to the issue, but:
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 05:44:38 pm
What is your graphics card? Is your driver uptodate?
Mobile Intel (R) 945 Express Chipset Family
And the driver is unlikely to be up to date, I've never updated it.
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 07:17:35 pm
The framerate should never be limited while VSync is active nor the other way around. It's always one or the other.

I always thought they did 2 different, independant things:
FrameRateLimit limits the frame rate to draw a maximum number of frames a second, have it too high, and it will draw faster than your graphics card is safely capable of displaying properly.

VSync is far more impotant, and simply prevents flicker, making sure that the graphics card will only render the screen image imediately after one has finished being drawn, preventing flicker, or what I call Half Image, where the bottom half of the screen is the frame after the top have of the screen. Frames might be drawn faster than the refresh rate, but those updated between the ones actually displayed will simply be discarded.
I've seen games without VSync, it looks aweful...


Being able to set both VSync and FrameRateLimit comes in handy when you want to draw with a slower animation speed than the refresh rate, but maintain a smooth flicker-free screen.
Title: Re: sf::RenderTexture problems.
Post by: eXpl0it3r on March 10, 2014, 07:53:42 pm
I always thought they did 2 different, independant things:
Well they do different things, but you still can't combine them. ;)

The FrameRateLimit measures the time it takes to calculate and render the frame and if there's enough time left, it will call sf::sleep() thus giving the processing time back to the CPU. Unfortunately the system sleep() call is not precise enough thus the FrameRateLimit will rarely have a fully consistent framerate (+- 10fps).

The VSync makes sure to only make a draw call once the screen refreshes, thus preventing the famous screen tearing and in the process limiting the framerate to the screen refresh rate (which is mostly 60). It will also wait if it's not the time to draw yet (not sure how exactly though).

Thus, while VSync essentially brings more positive points to the table, the end user is able to force VSync off in the driver, thus the secondary option could be used.
Mixing both is bad, because then VSync will pause the drawing, while FrameRateLimit will call sleep and thus you'll run into problems where your framerate might randomly drop. Again, as stated in the tutorials, use one or the other. ;)

Mobile Intel (R) 945 Express Chipset Family
This is quite a bad graphics card (had one once myself), I'm not sure if it can be fixed...

And the driver is unlikely to be up to date, I've never updated it.
Well then look at your manufacturer's homepage... ;)
Title: Re: sf::RenderTexture problems.
Post by: Laurent on March 10, 2014, 08:44:40 pm
Quote
Unfortunately the system sleep() call is not precise enough thus the FrameRateLimit will rarely have a fully consistent framerate (+- 10fps).
... so it's not unusual to get frames that last slightly more than 1/60 seconds, and thus skip the next screen refresh. Since v-sync is activated, your program will then wait for the next refresh, 1/60th of seconds later. This results in a bad 30 FPS whereas your code could run much faster. This is exactly why activating both is really a bad idea.

V-sync alone will ensure proper rendering and decent framerate; if you need precise timing then you'd rather implement a more robust fixed timestep algorithm and not rely on setFramerateLimit.
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 08:59:44 pm
It took me a while to find the latest driver for my Graphics processor...
released on 2/28/2008... I did not know there were 28 months in a year... Anyway, it's 8 years old, and my netbook isn't that old, so chances are I already have the latest version.

I cannot currently check the version on that computer, but I can check it's "Twin", installed from the same disk.

it is not...

Anyway, I will update when I am able, and see if it helps, but untill then, some interesting info about the card/driver capabilities:

Direct X 9
OpenGL 1.4
Shader Model 2.0
And a "No" to OpenCL, and all the Intel specific crap.
Title: Re: sf::RenderTexture problems.
Post by: G. on March 10, 2014, 09:38:37 pm
2/28 is called february 28, some countries use mm/dd/yyyy
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 09:43:59 pm
2/28 is called february 28, some countries use mm/dd/yyyy

I know, it's a joke poking fun at people who can't grasp the concept, and importance of "Order of Significance", it should be dd/mm/yyyy or yyyy/mm/dd, and NEVER yyyy/dd/mm or mm/dd/yyyy. the reason being, you either start with the least significant, and list the numbers in increasing significance, or start with the most significant, and list the numbers in decreasing significance.

If you still can't grasp it, Lets just say that writing date as mm/dd/yyyy is the equivelent of writing time as mm:ss:hh, you just wouldn't do it.

And although I am in a country that writes dd/mm, or dd/mm/yyyy, I timestamp my files in yyyymmdd format. month before date is perfectly acceptable(and could be argued to be more correct than day before month), but day should never be placed between month and year.
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 10, 2014, 11:08:36 pm
I updated the driver.

it didn't help...
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 12, 2014, 11:25:36 am
I have 4 computers in my office here, so I tried my program (both the test program, and what I thought should work for my actual progam). They all have Intel graphics, 2 of them with similar cards to my own (A 915G, and a 865G) didn't work, but the newer ones (i3 based) did work, for both programs.

I'm thinking I should keep this code, and write another version using pixel manipulation on an image (not as clean, and processor heavy by comparison) for those older incompatable cards.


My question though is, is there a way to check with SFML if a card is capable of using a RenderTexture or not, or would I need to set that myself with my config file, and give the user the option?
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 12, 2014, 11:56:45 am
Okay... this is crazy, I managed to solve the problem:

Instead of saving a reference to the texture from RenderTexture.getTexture() and passing that to Sprite.setTexture(), or simply passing the returned value from getTexture() stright to setTexture(), as was in my example, I instead copied the texture from getTexture() as so, it worked!

// in class headder
sf::Texture texttexture;
sf::Sprite textsprite;

// in function
sf::RenderTexture rendertexture;
// after doing things on rendertexture
texttexture = rendertexture.getTexture();
textsprite.setTexture(texttexture);
 

so I'm not sure WHY it doesn't like you passing it the value from getTexture() on certain graphics cards directly, or a reference to it, but it works if you copy it!

Anyway, problem solved.
Title: Re: sf::RenderTexture problems.
Post by: bobingabout on March 14, 2014, 01:17:54 am
I suppose a problem with copying the texture from the RenderTexture.getTexture to a Texture... it's copying the texture, on slower cards, it's SLOW.

I hadn't noticed initially, because it was only doing the opteration on startup, but my procedure locks up the rendering by a whole second while it creates 12 sprites less than 100x100 in size.