Members - Reputation: 301
Posted 13 December 2012 - 07:15 AM
I have written a very rudimentary D3D11 renderer and am now working with SFML (OpenGL). I am only interested in 2D games at the moment so I was just rendering quads to the screen in D3D and would like to do the same thing with GL in SFML.
However, I have one big problem. In order to work directly with the hardware I have to be in floating point coordinates, which is not only inconvenient for me, but is causing some bleed in my program. For example, I have a texture atlas with a single black pixel, surrounded by some blue pixel blocks representing buttons. I want to use that single black pixel and scale it up 1920x1080 times and use it as a black background. But when i do so I get some bleeding and there is a gradation of blue on my screen. I have a feeling this is due to floating point inaccuracy.
I need my games to be pixel accurate and I was wondering how I could do this in GL/D3D without having to resort to floating point numbers. At the same time, I don't only want to be able to run my game in 1920x1080 but at any resolution that the user wants in windowed mode. I am a bit lost as to how I would represent this with ints, as I don't want my character to move farther on the screen in windowed mode than in full screen, because if I say move 30 pixels left, 30 pixels is a lot in a 200x200 window but not much in a 1920x1080 fullscreen mode.
Does anyone know how to do this or am I stuck using the basic graphics package in SFML. I spent significant time learning D3D and basic 3D graphics principles and to be honest I don't want to sink anymore time there right now. I am not interested in 3D at all and am a bit peeved that I have to learn all this 3D stuff just to get a 2D game running very efficiently on the 3D hardware. Does anyone have an idea?
Members - Reputation: 948
Posted 13 December 2012 - 09:40 AM
You want scaling, so that means you won't be able to do 1 to 1 texel to pixel mapping no matter how hard you try. This means you're going to be bilinear filtering on your textures. With texture atlases you need to add a border around each of images so that the bilinear filtering doesn't accidentally pull in any adjacent images. An alternative is to modify your UVs so that the UV rectangle is squeezed inwards by half a texel on all sides, but that'll cut off a little of your image slightly so you won't always get away with it.
If you need mipmaps for your atlases then that can be extra tricky, and you'll generally need larger borders, possibly some custom mipmap generation that discourages bleeding across atlas tiles or some atlas generation rule that encourages atlas tiles to align with power of two grid lines so that there's less bleeding in your lower mips.
Edited by C0lumbo, 13 December 2012 - 09:49 AM.
Members - Reputation: 948
Posted 13 December 2012 - 09:47 AM
Could I deal in floats but use some math magic to make the top left of the screen 0.f,0.f and the bottom right 1920.f,1080f?
That's straightforward enough, I think. Assuming you're using shaders in OpenGL, you to use a projection matrix like the one documented here: http://msdn.microsoft.com/en-gb/library/windows/desktop/dd373965%28v=vs.85%29.aspx. If you're using fixed function OpenGL, then you can just use the glOrtho function directly.
The problem is that you might need to think about how to deal with different aspect ratios. Sometimes working to a 14:9 virtual resolution is best, then cut off bits or black bar it to cope with 4:3 and 16:9 - depends on your game really.
Edited by C0lumbo, 13 December 2012 - 09:48 AM.
Members - Reputation: 301
Posted 15 December 2012 - 07:11 AM
A few questions:
How can I sample my textures pixel accurately? I mean, one pixel of black should be enough to blow up to any resolution and fill the background with black, with no bleeding at all, am I correct? Or am I missing something?
Talking about the bleeding problem - I don't think this is really a floating point accuracy issue, it's a texture sampling issue.
What is bilinear filtering?
This means you're going to be bilinear filtering on your textures.
How many pixels thick should the border be, and in what color should the border be?
With texture atlases you need to add a border around each of images so that the bilinear filtering doesn't accidentally pull in any adjacent images.
What does "Modify the UV mean?"
An alternative is to modify your UVs so that the UV rectangle is squeezed inwards by half a texel on all sides
As a side note, I have switched over to using SFML so that rendering can be simple while I master other programming and game design concepts, but I noticed that if I place something at, for example, location (0, 1000) then it goes outside my screen if I have, say, a (800, 600) resolution. Is there any way in SFML to have the coordinates scale with the window, i.e. a y-coord of 1000 (or whatever, I really don't care) would always be just near the bottom of the screen just as it would in 1920x1080?
Thanks for all your help.