PDA

View Full Version : Tile Game Flicker When Moving View



dkorenak
08-01-2016, 12:37 AM
I have a tile based game that has flickering within moving tiles only. The character image centered in the screen does not exhibit this flicker. The flickering is most noticeable along tile edges and sharp dark lines within tiles. For the areas within tiles where there are not sharp lines, the image looks slightly blurred. This flicker only occurs when a key is pressed and tiles are translated. How do I eliminate this flickering? Thanks.

GClements
08-01-2016, 09:11 AM
How do I eliminate this flickering?
That depends upon what's causing it.

If the texture is being down-sampled, ensure that it contains all sufficient mipmap levels and the minification filter uses mipmaps.

If it's being up-sampled with linear filtering and you're using a texture atlas, edge pixels will be blended with pixels from adjacent tiles. The solution is to add a border to each tile and adjust the texture coordinates accordingly.

If you aren't using texture filtering, then you need to scroll in integer multiples of a pixel. Ideally the scale factor should be an integer. If that isn't possible, then consider rendering 1:1 to a texture then upscaling to the screen resolution using a high-quality low-pass filter such as Lanczos.

Alternatively, up-scale the textures with a good filter (and hand-edit them if necessary) so that you're always down-sampling (with mipmaps).

dkorenak
08-01-2016, 11:49 AM
That depends upon what's causing it.

If the texture is being down-sampled, ensure that it contains all sufficient mipmap levels and the minification filter uses mipmaps.

If it's being up-sampled with linear filtering and you're using a texture atlas, edge pixels will be blended with pixels from adjacent tiles. The solution is to add a border to each tile and adjust the texture coordinates accordingly.

If you aren't using texture filtering, then you need to scroll in integer multiples of a pixel. Ideally the scale factor should be an integer. If that isn't possible, then consider rendering 1:1 to a texture then upscaling to the screen resolution using a high-quality low-pass filter such as Lanczos.

Alternatively, up-scale the textures with a good filter (and hand-edit them if necessary) so that you're always down-sampling (with mipmaps).


I am new to OpenGL and am unsure about some of your suggestions. I have based quite a bit of my code on an OpenTK tutorial. I do have 4 texture parameters set. Here is the function where I load in textures:


Public Shared Function LoadTexture(ByVal path As String) As Texture2D
If Not (File.Exists("Content\Tiles\" + path)) Then
Throw New FileNotFoundException("File not found at Content/" & path & "")
End If

Dim id As Integer = GL.GenTexture()
GL.BindTexture(TextureTarget.Texture2D, id)

Dim bmp As Bitmap = New Bitmap("Content\Tiles\" & path)
Dim data As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb )
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)

bmp.UnlockBits(data)

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, CInt(TextureWrapMode.ClampToEdge)) 'ClampToEdge
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, CInt(TextureWrapMode.ClampToEdge))
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, CInt(TextureMinFilter.Linear)) 'Linear
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, CInt(TextureMagFilter.Linear)) 'Linear


Return New Texture2D(id, bmp.Width, bmp.Height)
End Function

The images I am using are larger than the pixel area that they take up on screen. The game is 2D and uses a grid that is 8x8 tiles in the screen area. I did just try to make sure my image sizes were powers of 2 and made my tiles 128X128 pixels. This did not change the jittery or flickering effect when I tested it. I only have one image for each tile, and I never make a call to create a mipmap that I am aware of. I tried to set the TextureMinFilter to LinearMipmapLinear but it left the screen blank.

I am not sure how I could scroll just 1 pixel at a time. The translation parameters change by the speed value of 0.005 every time the OpenGL Control is Invalidated. At 60 FPS, the character moves a screen distance of 0.3 screen units in one second. I do set up a viewport with the pixel size of the screen. I will try to take those values and divide by 2 then take the reciprocal to get the pixel size in screen units, and then I will try that value in the translation function. Please let me know if showing you more code will be helpful. Thanks.

GClements
08-01-2016, 01:43 PM
The images I am using are larger than the pixel area that they take up on screen.

If you're down-scaling, you need to use mipmaps, otherwise you'll get aliasing.

Either:
a) create the mipmap layers in software and upload each level with a call to glTexImage2D() (rather than only uploading level 0).
b) use gluBuild2DMipmaps() instead of glTexImage2D()
c) if you can assume OpenGL 3.0 or later, use glGenerateMipmap()

dkorenak
08-01-2016, 05:04 PM
If you're down-scaling, you need to use mipmaps, otherwise you'll get aliasing.

Either:
a) create the mipmap layers in software and upload each level with a call to glTexImage2D() (rather than only uploading level 0).
b) use gluBuild2DMipmaps() instead of glTexImage2D()
c) if you can assume OpenGL 3.0 or later, use glGenerateMipmap()

I have tried setting the viewport to a power of 2 such as 2048 x 1024 and have created tiles that are 1/8 those dimensions (256 x 128 pixels), so that the area occupied by the tile is exactly what I would expect the pixel area to be. This did not work. I also tried method c) using the GenerateMipmap function but it did not seem to change anything. I may be applying it incorrectly. I also experimented with changing the sample value passed into the GraphicsMode property, and I tried to give the control a hint that I wanted to use mipmaps by the commands GL.Enable(EnableCap.Multisample) and GL.Hint(HintTarget.GenerateMipmapHint, HintMode.Nicest). None of those attempts helped. I could not find the function gluBuild2DMipmaps(). Here is the code that I tried with the call to glGenerateMipmap():


Public Shared Function LoadTexture(ByVal path As String) As Texture2D
If Not (File.Exists("Content\Tiles\" + path)) Then
Throw New FileNotFoundException("File not found at Content/" & path & "")
End If

Dim id As Integer = GL.GenTexture()
GL.BindTexture(TextureTarget.Texture2D, id)

Dim bmp As Bitmap = New Bitmap("Content\Tiles\" & path)
Dim data As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb )
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0)

GL.GenerateMipmap(GenerateMipmapTarget.Texture2D)

bmp.UnlockBits(data)

GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, CInt(TextureWrapMode.ClampToEdge)) 'ClampToEdge
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, CInt(TextureWrapMode.ClampToEdge))
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, CInt(TextureMinFilter.Linear)) 'Linear
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, CInt(TextureMagFilter.Linear)) 'Linear


Return New Texture2D(id, bmp.Width, bmp.Height)
End Function

dkorenak
08-02-2016, 05:28 PM
After some more research, I think that what I am seeing is "motion blur". It is a uniform blur that happens in the direction of motion for some monitors or software that have refresh rates of 60 Hz or less. I clocked my game at 60 FPS and my computer monitor has a refresh rate of 60 Hz. There is a website www.blurbusters.com that has articles about this kind of blur. One article can be found at www.blurbusters.com/faq/lcd-motion-artifacts/ which explains different kinds of blur that can happen to LCD screens. There is also a page that has a test where multiple frame rates can be tested for moving objects. It can be found at www.testufo.com/#test=framerates. When I saw the motion of the UFO character in the test at 60 Hz it looked like the kind of blur I was seeing in the background of my game. Unfortunately, the only solutions that they give have to do with increasing the refresh rate of the monitor or using some other technology.

If anyone has any tips or tricks for improving this kind of blur or thinks that something other than what I described is to blame, I would definitely appreciate the advice.

foodadditives
08-18-2016, 11:55 PM
I am also looking forward some to improve this issue