SFML community forums
Help => Graphics => Topic started by: Richy19 on April 23, 2011, 07:48:54 pm
-
Just wondering if theres anything in SFML that allows you to downsize without loosing quality.
In VS/XNA i use the generate mipmaps option in the content importer:
(http://img194.imageshack.us/img194/3139/unledgx.png)
But i didnt know if SFML had anything like it
-
Just wondering if theres anything in SFML that allows you to downsize without loosing quality.
That doesn't make sense, downsizing always looses quality since you have less pixels. The only thing that you can choose is how to loose the quality (ie. which scale filter to apply). In SFML you can play with Image::SetSmooth to modify that. With smoothing on, you get bilinear filtering. With smoothing off, you get nearest pixel filtering.
In VS/XNA i use the generate mipmaps option in the content importer:
Generating mipmaps doesn't help, the important thing is (again) what filter you apply, either when you generate the mipmap levels, or when you perform texture lookup.
-
Downsizing doesn't use mipmaps. (Edit: Nah, it does...) You need to zoom the view to use them. Here is a small test I made, using SFML2:
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#define GL_GENERATE_MIPMAP 0x8191
#include <math.h>
#define USEMIPMAPS true
inline float fRand() { return rand() / float(RAND_MAX + 1); };
inline float fRand(float upperLimit) { return fRand() * upperLimit; };
inline unsigned int uRand(unsigned int upperLimit) { return unsigned int(fRand() * upperLimit); };
int main()
{
sf::ContextSettings cs;
cs.AntialiasingLevel = 8;
sf::RenderWindow App(sf::VideoMode(800, 800), "SFML window", sf::Style::Default, cs);
sf::Image image;
image.Create(1600, 1600);
image.SetSmooth(true);
if(USEMIPMAPS)
{
image.Bind();
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
for(int y=0; y<1600; y++)
{
for(int x=0; x<1600; x++)
{
int c = uRand(256);
image.SetPixel(x, y, sf::Color(c,c,c));
}
}
sf::Sprite sprite;
sprite.SetImage(image);
sprite.SetOrigin(image.GetWidth()/2, image.GetHeight()/2);
sprite.SetPosition(App.GetWidth()/2, App.GetHeight()/2);
int counter = 0;
sf::View view;
view.SetCenter(App.GetWidth()/2, App.GetHeight()/2);
while (App.IsOpened())
{
sf::Event Event;
while (App.PollEvent(Event))
{
if (Event.Type == sf::Event::Closed)
App.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App.Close();
}
counter++;
double scale = (sin(double(counter*0.01))+1)*6400+200;
view.SetSize(scale, scale);
App.SetView(view);
App.Clear();
App.Draw(sprite);
App.Display();
sf::Sleep(20);
}
return EXIT_SUCCESS;
}
I get this error: "An internal OpenGL call failed in Renderer.cpp (104) : GL_INVALID_ENUM, an unacceptable value has been specified for an enumerated argument". But it works and it looks much better. Try setting USEMIPMAPS to false to see the difference.
If you really need to downsize a sprite, you probably must create your mipmaps yourself and switch the sprite's image when appropriate.
Edit: I don't know why I didn't get the same results in the first place. Now I can change the lines
double scale = (sin(double(counter*0.01))+1)*6400+200;
view.SetSize(scale, scale);
to
double scale = (sin(double(counter*0.01))+1)*4;
sprite.SetScale(sf::Vector2f(scale, scale));
and it still works.
-
Sorry to bump this but I only just saw that last comment.
Would it be really necessarily to do all of that with the view?
Could it not just be done by creating the images 2,3 or 5 times bigger than needed and then just downsizing the sprite?