1
Graphics / Downsizing image without quality loss
« on: July 06, 2011, 07:30:30 pm »
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:
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
to
and it still works.
Code: [Select]
#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
Code: [Select]
double scale = (sin(double(counter*0.01))+1)*6400+200;
view.SetSize(scale, scale);
to
Code: [Select]
double scale = (sin(double(counter*0.01))+1)*4;
sprite.SetScale(sf::Vector2f(scale, scale));
and it still works.