Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sf::RenderTexture displays upside down #35

Closed
kevvo1288 opened this issue Jun 26, 2017 · 15 comments
Closed

sf::RenderTexture displays upside down #35

kevvo1288 opened this issue Jun 26, 2017 · 15 comments
Labels

Comments

@kevvo1288
Copy link

I'm not sure if this is the same issue as #11 but RenderTextures seem to be flipped upside down. I've attached a minimal program to produce the issue. The sprite shows right-side up if I render it using RenderWindow::draw() but if I use ImGui::Image() it is upside down. Rendering the raw sf::RenderTexture using ImGui::Image() also results in an upside down image.
If I do the same test using an image loaded from a file into a sf::Texture instead of the sf::RenderTexture, everything renders just fine.

#include "imgui.h"
#include "imgui-SFML.h"

#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
	sf::RenderWindow window(sf::VideoMode(640, 480), "");
	window.setFramerateLimit(60);
	ImGui::SFML::Init(window);

	bool show = true;
	
	sf::RenderTexture renderTexture;
	if (!renderTexture.create(32, 32))
	{
		std::cout << "error renderTexture\n";
		return 1;
	}
	sf::Sprite sprite(renderTexture.getTexture());
	sf::RectangleShape rect(sf::Vector2f(16, 16));
	rect.setFillColor(sf::Color::White);
	rect.setPosition(0, 0);
	renderTexture.clear(sf::Color::Green);
	renderTexture.draw(rect);
	renderTexture.display();

	sf::Clock deltaClock;
	while (window.isOpen()) {
		sf::Event event;
		while (window.pollEvent(event)) {
			ImGui::SFML::ProcessEvent(event);

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

		ImGui::SFML::Update(window, deltaClock.restart());
		
		ImGui::Begin("Sprite Test");
		//ImGui will render this upside down
		ImGui::Image(sprite);
		ImGui::End();

		ImGui::Begin("RenderTexture Test");
		//ImGui will render this upside down
		ImGui::Image(renderTexture.getTexture());
		ImGui::End();
		
		window.clear(sf::Color::Black);
		//SFML renders ok
		window.draw(sprite);
		//But IMGUI seems to render these upside down
		ImGui::SFML::Render(window);
		window.display();
	}

	ImGui::SFML::Shutdown();
}
@eliasdaler
Copy link
Contributor

Okay, I'll see what I can do soon. Are you using the latest version of SFML, btw?

@kevvo1288
Copy link
Author

Yes, sorry I should have said:
SFML 2.4.2 VC++ 14 (VS 2015) 32 bit
Windows 7

@eliasdaler
Copy link
Contributor

eliasdaler commented Aug 31, 2017

Sorry, I forgot about the issue. So, the problem is really here and it exists because RenderTexture stores the texture upside down. The sprite renders correctly, because textures store flag about whether it has pixels flipped or not.

sf::Texture::Bind handles this case, but for some reason if I use texture pointers instead of native handles in imgui-SFML code, things get really glitched. I'll take a closer look at the issue in a few days and report what I will found.

UPD: No fix found :(

@JonnyPtn
Copy link
Contributor

For what it's worth, I've worked around this temporarily by just copying all the Image(sf::Texture...) overloads, replacing with Image(sf::RenderTexture...) and flipping the UV's. Seems to give the expected result although I'm sure there are smarter ways to work around this....

@eliasdaler
Copy link
Contributor

Yes, I think that's the right way to do it for now. The problem is that if the user passes renderTexture.getTexture() instead of renderTexture, it'll just be sf::Texture and we'll have no way to say if it came from sf::RenderTexture or not (inside ImGui::SFML::Render).

I think I'll overload Image with sf::RenderTexture for now. That's the best I can do about it, I think. Will investigate further later.

@fda-odoo
Copy link

Didn't see the code, but usually a flipped texture is 90% of the time due to a forgotten ".display()" call...

@eliasdaler
Copy link
Contributor

No, here the problem is that RenderTexture stores flipped texture. I think I need to add overload for it which will flip it, just like JohnyPtn said. :)

@JonnyPtn
Copy link
Contributor

Uh huh, this is part of the 10% :P

example solution:

void Image(const sf::RenderTexture& texture, const sf::Vector2f& size, const sf::FloatRect& textureRect,
               const sf::Color& tintColor, const sf::Color& borderColor)
{
    sf::Vector2f textureSize = static_cast<sf::Vector2f>(texture.getSize());
    ImVec2 uv0(textureRect.left / textureSize.x, (textureRect.top + textureRect.height) / textureSize.y);
    ImVec2 uv1((textureRect.left + textureRect.width) / textureSize.x, textureRect.top / textureSize.y);
    ImGui::Image((void*)texture.getTexture().getNativeHandle(), size, uv0, uv1, tintColor, borderColor);
}

@barthoukes
Copy link

Also found this flipping issue already reported in 2010 and no solution yet for me or any other designer. I really need to render the menu-card to renderTextures, then add them to the sf::View to create a swipe experience... else sfml is really too slow, especially in Chinese. My menu card is suddenly upside down :-( Because of lower performance compare to SDL, this verticle shit and not able to update parts of the screen I have to stick with SDL, although SFML seems to have a very clear interface for C++... too bad. :-( I hope they will improve in the future and also change to utf-8 because utf-32 becomes a nightmarre.

@eliasdaler
Copy link
Contributor

@barthoukes does the solution from @JonnyPtn work for you for ImGui-SFML?

@JonnyPtn
Copy link
Contributor

I'm not really sure where to start with that comment... but here goes:

  • This is just an SFML binding for imgui
  • You can pretty much copy and paste the code in my previous comment to get your problem solved

And regards to your SFML comments:

  • I don't see how being in Chinese affects the speed of SFML
  • Do you have any tests to back up your "SDL is faster" claim? It's hard to compare, but common knowledge is that SFML is slightly faster. I'd love to see some benchmarks
  • What's "this verticle shit" and which parts of the screen can't you update?
  • sf::String can convert to utf8 for you, that's exactly what it's designed for.

Most of your comment Is SFML related, so best not to discuss it here anyway, join us in the SFML Discord (or IRC) channel if you want to discuss them

@DaveInDev
Copy link

DaveInDev commented May 16, 2020

Hi @eliasdaler ,

I bumped into the same flipped texture problem...
I could not figure out where to insert @JonnyPtn solution, because his ImGui::Image call did not worked for me... but I added this to imgui-SFML.cpp :

void Image(const sf::RenderTexture& texture, 
	const sf::Color& tintColor, const sf::Color& borderColor) {
	ImTextureID textureID =
		convertGLTextureHandleToImTextureID(texture.getTexture().getNativeHandle());
	ImGui::Image(textureID, static_cast<sf::Vector2f>(texture.getSize()), 
		ImVec2(0, 1), ImVec2(1, 0), tintColor, borderColor);
}

and this in imgui-SFML.h

IMGUI_SFML_API void Image(const sf::RenderTexture& texture, const sf::Color& tintColor = sf::Color::White, const sf::Color& borderColor = sf::Color::Transparent);
and it worked. So if it can help someone... or if you want to update your code...

Anyway, thx for your code @eliasdaler , it's great !

@baanchas
Copy link

thanks @JonnyPtn, your solution solved the problem, now everything works correctly.

@eliasdaler
Copy link
Contributor

eliasdaler commented Feb 22, 2021

Please check out this branch:
https://github.com/eliasdaler/imgui-sfml/tree/render-texture-fixes
UPD: branch deleted, fix is here: ee41e16

So, here's the thing. I can add sf::RenderTexture overload which works properly, however it won't work for sf::Sprite which has a texture from sf::RenderTexture assigned, so if I take the code from @kevvo1288 and add these lines:

ImGui::TextUnformatted("RenderTexture");
ImGui::Image(renderTexture);
ImGui::SameLine();
ImGui::ImageButton(renderTexture);

ImGui::TextUnformatted("Texture");
ImGui::Image(*sprite.getTexture());
ImGui::SameLine();
ImGui::ImageButton(*sprite.getTexture());

ImGui::TextUnformatted("Sprite");
ImGui::Image(sprite);
ImGui::SameLine();
ImGui::ImageButton(sprite);

I get the following result:
image

This is the best I can do, because to know if the texture comes from sf::RenderTexture or not, we need access to sf::Texture::m_pixelsFlipped which is private.

@eliasdaler
Copy link
Contributor

Merged the fix into the master: ee41e16
I've also added a workaround if you really need to use sf::RenderTexture with sf::Sprite (you basically have to copy it to a new sf::Texture... not perfect, but it works. See README for details)

The oldest bug is now closed. Sorry for the huge procrastination on my part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants