Question
I'm working on a side-scrolling game that has a 2D grid for rendering to the screen. I'm using OpenGL, and I've optimized my game so that nothing invisible is attempted to be drawn.
As of now, I create a grid based off of my game's window size. Each tile in the grid takes up 32x32 pixels. This grid is made up of square primitives, and each is drawn using an individual vertex buffer object. When the window is resized, the grid changes as well.
My games updating thread will constantly feed images into this grid, and this is what creates my game's scenery.
I've implemented a mechanism for user input to move this grid around (simulating character movement); however, I notice a visual artifacts of slightly slanted horizontal lines that flicker across the screen. They are about 20 pixels in height.
Example of the artifact:
In the image above, you can see the black line that crosses the entire image. This is the artifact I'm receiving.
I'm curious what are the possible causes for this type of visual artifact. My grid is constantly moving back and forth and reapplying the textures to each square during each iteration of my game loop (update thread). However, I see no reason why something like this would appear.
Does anyone have an idea what could be happening here?
Does anyone know how to minimize graphical artifacts in general?
I am using the fixed-function pipeline right now, so I bet that there would be a huge improvement after moving to using shaders. However, I'm not convinced that this alone will solve my problem.
Code Snippets
Originally I didn't want to share code, but I'll give some snippets of where all the interesting stuff is happening. For each snippet, I'll explain where it is used and how it connects to other snippets.
Grid Movement
The grid is moved by passing the movement amount to this function. The algorithm in here simply forces the grid location to wrap around a box that has the corners (-1, -1) and (0, 0). That way, emptiness is never seen around the grids border. I send the user input to this function. This function is called on my game's updating thread.
@Override
public void move(double x, double y) {
//First, obtain only the integer parts of each coordinate.
double moveX = (x%1);
double moveY = (y%1);
//Determine new location for the grid.
double endX = (location.x + moveX);
if(moveX >= 0) //Moving right
{ if(endX >= 0) endX--; }
else //Moving left
{ if(endX < -1) endX++; }
double endY = (location.y + moveY);
if(moveY >= 0) //Moving right
{ if(endY >= 0) endY--; }
else //Moving left
{ if(endY < -1) endY++; }
location.x = endX; //location stores the new coordinate for the grid (bottom-left)
location.y = endY;
}
Grid Rendering
This function renders the grid by iterating through each square VBO that is inside of it.
It applies the correct texture, translates the square, then draws it. This function is called on my games's rendering thread.
public void render(GL2 gl){
for(int yIndex = 0; yIndex < NUM_BLOCKS_Y; yIndex++) {
for(int xIndex = 0; xIndex < NUM_BLOCKS_X; xIndex++) {
Square tmpSquare = squares.get(yIndex * NUM_BLOCKS_X + xIndex);
tmpSquare.setTexture(blockIDs[xIndex][yIndex]);
tmpSquare.moveTo(location.x + xIndex, location.y + yIndex);
tmpSquare.render(gl);
}
}
}
Debug Notes
I also went ahead and did a couple test runs to see if I could find anything interesting. Here's what I learned:
First of all, the reason the line in the picture above is black is because that is what my glClearColor is set to. I changed the clear color, and that changed the artifact's color too.
Also, my rendering thread is separate from my updating thread. And the updating thread is fixed at a desired FPS. When I set to 50 FPS, in other words, 50 updates per second, and when I change the movement speed to be 50, 25, 12.5, or 6.25, the grid does not shift back and forth because it catches the edge of the box mentioned above. When I set the updater to 30 FPS, and the movement speed to 60, 30, 15, 7.5, or 3.75, the grid still does not change. Since the grid isn't bouncing back and forth, I don't receive the gap that appears in between the rows as before. NOTE: The jaggedness reappears when setting to half of 6.25 @ 50FPS, or half of 3.75 @ 50FPS; and the jaggedness appears when not moving by a 2^x * FPS.
It seems to me that when the movement speed is set so that the grid moves back and forth, not all of the square positions are moving fast enough.