EDIT: Unless I figure something else out, I'm chalking this up to a bad card or drivers. Using only vertex and fragment shaders works fine, but the presence of a geometry shader makes the card glitch.
Hello, I have a strange problem that has baffled me for a couple days now. I've searched but haven't found anything that sounded like this problem.
I have a tile-based map that is 100 tiles wide and 20 tiles high (hard coded for testing). I have a buffer set up that contains the map tile codes and map xy coordinates for each tile code. I have shaders set up to take the map tile code and xy coordinates and render textured quads from them. I'm using a 256x256 pixel tile atlas for the texture. I'm currently sending all map tiles to the shader and letting the viewport handle what gets drawn.
The game renders correctly on one computer, but on another I get a strange flicker. I've attached a screenshot of how it looks when the flicker is not happening and one when it is. No values are changing between renders, so the image should be static. Different areas flicker for a frame. It looks like strands of 8 tiles are being drawn in the wrong position, but I can't figure out why.
Has anyone experienced anything like this?
Thanks for any help and suggestions!
For anyone curious, here is my render code:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
// Start the shader
GL20.glUseProgram(this.shader.getProgramID());
GL20.glUniformMatrix4(this.shader.projectionMatrixLocation, false, DisplayHelper.screenProjectionMatrix);
GL20.glUniform1i(this.shader.textureSamplerLocation, 0);
// Set up the texture.
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture.textureID);
// Set up the data buffer.
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, this.bufferHandle);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, this.buffer, GL15.GL_STATIC_DRAW);
// Set up the vertex attrib pointers.
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glVertexAttribPointer(0, 1, GL11.GL_FLOAT, false, TILE_CODE_STRIDE, TILE_CODE_OFFSET);
GL20.glVertexAttribPointer(1, 2, GL11.GL_FLOAT, false, POSITION_STRIDE, POSITION_OFFSET);
// Draw.
GL11.glDrawArrays(GL11.GL_POINTS, 0, TILES_ON_SCREEN);
// Clean up.
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL20.glUseProgram(0);
My shader code. I have them all in one file and separate them by name using anything above the first name (#version 330 core) in all three.
#version 330 core
>> vertex <<
layout(location = 0) attribute in float TileCode;
layout(location = 1) attribute in vec2 VertexPosition;
out int tile;
void main() {
tile = int(TileCode);
gl_Position = vec4(VertexPosition, 0.0, 1.0);
}
>> geometry <<
layout(points) in;
layout(triangle_strip, max_vertices=4) out;
const int TILES_PER_TEXTURE_ROW = 16;
const float TILE_DRAW_SIZE = 16.0;
const float TEXTURE_SIZE = 256.0;
uniform mat4 projectionMatrix;
in int tile[];
out vec2 texCoord;
void main() {
int code = tile[0];
if (code == 0) {
return;
}
// Set up the tile bound points.
vec4 topLeft = gl_in[0].gl_Position;
topLeft.x = topLeft.x * TILE_DRAW_SIZE;
topLeft.y = topLeft.y * TILE_DRAW_SIZE;
vec4 bottomRight = topLeft;
bottomRight.x += TILE_DRAW_SIZE;
bottomRight.y += TILE_DRAW_SIZE;
// Calculate tile texture coordinates.
int cx = code % TILES_PER_TEXTURE_ROW;
int cy = code / TILES_PER_TEXTURE_ROW;
float tx = (float(cx) * TILE_DRAW_SIZE) / TEXTURE_SIZE;
float ty = (float(cy) * TILE_DRAW_SIZE) / TEXTURE_SIZE;
float tx2 = (float(cx + 1) * TILE_DRAW_SIZE) / TEXTURE_SIZE;
float ty2 = (float(cy + 1) * TILE_DRAW_SIZE) / TEXTURE_SIZE;
// Top left.
gl_Position = projectionMatrix * vec4(topLeft.x, topLeft.y, 0.0, 1.0);
texCoord = vec2(tx, ty);
EmitVertex();
// Top right.
gl_Position = projectionMatrix * vec4(bottomRight.x, topLeft.y, 0.0, 1.0);
texCoord = vec2(tx2, ty);
EmitVertex();
// Bottom left.
gl_Position = projectionMatrix * vec4(topLeft.x, bottomRight.y, 0.0, 1.0);
texCoord = vec2(tx, ty2);
EmitVertex();
// Bottom right.
gl_Position = projectionMatrix * vec4(bottomRight.x, bottomRight.y, 0.0, 1.0);
texCoord = vec2(tx2, ty2);
EmitVertex();
EndPrimitive();
}
>> fragment <<
layout(location = 0) out vec4 FragColor;
uniform sampler2D Texture0;
in vec2 texCoord;
void main() {
// FragColor = vec4(1.0, 1.0, 1.0, 1.0);
FragColor = texture2D(Texture0, texCoord);
}