OpenGl: The tile atlas renderer I just tried to make has vertical lines between some of the tiles

So these go from the top of the window to the bottom. This I guess would be some kind of rounding error in the x axis.

This is My Code:


#include <vector>
#include <iostream>
#define GLEW_STATIC
#include "GL/glew.h"
#include "GLFW/glfw3.h"

#include "ShaderProgram.h"
#include "Texture2D.h"

using namespace std;
GLFWwindow* pWindow;
bool fullscreen = false;
bool gWire;
void onkey(GLFWwindow* window, int key, int scancode, int action, int mode);
bool initOpengl();
int main()
{
	if (!initOpengl()) {
		cout << "Initialization failed" << endl;
		return -1;
	}

	//GLfloat vertices[] = {
	//	-0.5f,  0.5f, 0.0f, 0.0f, 1.0f,
	//	 0.0f,  0.5f, 0.0f, 1.0f, 1.0f,
	//	 0.0f, -0.5f, 0.0f, 1.0f, 0.0f,
	//	-0.5f, -0.5f, 0.0f, 0.0f, 0.0f
	//};

	GLfloat verts[] = {
		0, 0, 0, 0, 1,
		1, 0, 0, 1, 1,
		1, 1, 0, 1, 0,
		0, 1, 0, 0, 0
	};

    GLuint indus[] = {
        0, 1, 2, 0, 2, 3 };

	vector<GLuint> induces;
	for (int i = 0; i < 80; i++) {
		for (int j = 0; j < 6; j++) induces.push_back(i * 4 + indus[j]);
	}
	vector<GLfloat> vertices;
	int muld;
	for (int y = 0; y < 8; y++) {
		for (int x = 0; x < 10; x++) {
			for (int i = 0; i < 4; i++) {
				muld = i * 5;
				vertices.push_back((GLfloat)-1 + verts[muld] / (GLfloat)5 + (GLfloat)x / (GLfloat)5);
				vertices.push_back((GLfloat)1 - (verts[muld + 1] / (GLfloat)4 + (GLfloat)y / (GLfloat)4));
				vertices.push_back((GLfloat)0);
				vertices.push_back(verts[muld + 3] / (GLfloat)85);
				vertices.push_back(1 - verts[muld + 4] / (GLfloat)85);
			}
		}
	}
	GLuint vbo, ibo, vao;
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(), &vertices[0], GL_STATIC_DRAW);

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);


	//position
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), NULL);
	glEnableVertexAttribArray(0);

	//tex coords
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	glEnableVertexAttribArray(1);

	glGenBuffers(1, &ibo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * induces.size(), &induces[0], GL_STATIC_DRAW);

	ShaderProgram shader;
	shader.loadShaders("Shaders/basic.vert", "Shaders/basic.frag");

	Texture2D tex;
	tex.loadTexture("Textures/tiles.png", true, true);
	while (!glfwWindowShouldClose(pWindow)) {
		glfwPollEvents();


		glClear(GL_COLOR_BUFFER_BIT);

		tex.bind();
		glUniform1i(glGetUniformLocation(shader.getProgram(), "MyTexture"), 0);
		shader.use();

		glBindVertexArray(vao);
		glDrawElements(GL_TRIANGLES, 480, GL_UNSIGNED_INT, 0);
		glBindVertexArray(0);
		glfwSwapBuffers(pWindow);
	}

	glDeleteVertexArrays(1, &vao);
	glDeleteBuffers(1, &vbo);
	glDeleteBuffers(1, &ibo);
	glfwTerminate();
	return 0;
}

bool initOpengl() {
	if (!glfwInit()) {
		cout << "GLFW Initialization failed" << endl;
		false;
	}

	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);



	if (fullscreen) {
		GLFWmonitor* mon = glfwGetPrimaryMonitor();
		const GLFWvidmode* mode = glfwGetVideoMode(mon);
		if (mode != NULL) {
			pWindow = glfwCreateWindow(mode->width, mode->height, "Hello", NULL, NULL);
		}
	}
	else {
		pWindow = glfwCreateWindow(1024, 768, "Hello", NULL, NULL);
	}

	if (pWindow == NULL) {
		cout << "Could not make window" << endl;
		glfwTerminate();
		return false;
	}

	glfwMakeContextCurrent(pWindow);

	glfwSetKeyCallback(pWindow, onkey);

	glewExperimental = GL_TRUE;
	if (glewInit() != GLEW_OK) {
		cout << "GLEW Initialization failed" << endl;
		return false;
	}

	glClearColor(.5, .5, 1, 1);
	return true;
}

void onkey(GLFWwindow* window, int key, int scancode, int action, int mode) {
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE);
	
}

That’s certainly a possibility. In floating-point arithmetic, x/5+1/5 ≠ (x+1)/5. This wouldn’t be an issue for the y axis because y/4+1/4 = (y+1)/4 if y is a small integer.

Also, when using a texture atlas, you need to ensure tiles don’t bleed into each other if the filters aren’t GL_NEAREST. Using GL_LINEAR works for minification, but for magnification you need a border around each tile (i.e. texture coordinates need to be at least half a texel in from tile boundaries). If using mipmaps, you need to clamp the maximum level so texels aren’t crossing tile boundaries.