I am having a problem with rendering a quad in opengl via 4 lines (5 vertices via GL_LINE_STRIP). The rendering is generally working fine in terms of connecting the lines into a quad. The problem is, that the lines in the bottom left corner are not connected. Following screenshot shows what I am talking about. Left is a screenshot from the entire scene, right a close up zoom in where one can see that the lines do not connect correctly.
The coordinates for the corner vertices in NDC are (x,y)
top left -0.5, 0.5
bottom left -0.5, -0.5
bottom right 0.5, -0.5
top right 0.5, 0.5
I really tried to wrap my head around where this is coming from but I couldn't figure it out and I also didn't find any helpful information on the internet. It seems to me, that the line from top left to bottom left is just one pixel short and does not connect to the bottom line.
I included a working minimal example in c++. Maybe someone can help me find out where this is coming from. I am using Visual Studio 2017, OpenGL 460 core, glfw3 and glad 0.1.29.
Main program:
//cpp
#include <iostream>
#include <vector>
#include <cstdio>
//opengl, etc.
#include <glad/glad.h>
#include <glfw/glfw3.h>
//own
#include <shader.h>
//forward declarations
GLFWwindow* initOpenGL(const int pScreenWidth, const int pScreenHeight);
void framebufferSizeCallback(GLFWwindow *window, int width, int height);
int main(int argc, char *args[])
{
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 800;
GLFWwindow *window = initOpenGL(SCREEN_WIDTH, SCREEN_HEIGHT);
Shader shader("shader_code/vertex_shader_quad.glsl", "shader_code/fragment_shader_quad.glsl");
shader.use();
glfwSwapInterval(1);
std::vector<float> quadVertices;
quadVertices.push_back(-0.5f);
quadVertices.push_back(0.5f);
quadVertices.push_back(-0.5f);
quadVertices.push_back(-0.5f);
quadVertices.push_back(0.5f);
quadVertices.push_back(-0.5f);
quadVertices.push_back(0.5f);
quadVertices.push_back(0.5f);
quadVertices.push_back(-0.5f);
quadVertices.push_back(0.5f);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
unsigned int vbo, vao;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(float), &quadVertices.front(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_LINE_STRIP, 0, (quadVertices.size() / 2));
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glfwSwapBuffers(window);
glfwPollEvents();
//let program run until button is pressed
std::getchar();
}
GLFWwindow* initOpenGL(const int pScreenWidth, const int pScreenHeight)
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(pScreenWidth, pScreenHeight, "OpenGLRenderer", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create glfw window" << std::endl;
glfwTerminate();
return NULL;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebufferSizeCallback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return NULL;
}
return window;
}
void framebufferSizeCallback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
Shaders:
vertex shader:
#version 460 core
layout (location=0) in vec2 inPos;
out vec3 vertexColor;
void main()
{
gl_Position = vec4(inPos, 0.0f, 1.0f);
vertexColor = vec3(0.91f, 0.84f, 0.42f);
}
fragment shader
#version 460 core
in vec3 vertexColor;
out vec4 color;
void main()
{
color = vec4(vertexColor, 1.0f);
}
Custom Shader Class:
#include <shader.h>
Shader::Shader(const char *pVertexPath, const char *pFragmentPath)
{
std::string vertexCodeInput, fragmentCodeInput;
std::ifstream vertexFile, fragmentFile;
vertexFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fragmentFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
vertexFile.open(pVertexPath);
fragmentFile.open(pFragmentPath);
std::stringstream vertexFileStream, fragmentFileStream;
vertexFileStream << vertexFile.rdbuf();
fragmentFileStream << fragmentFile.rdbuf();
vertexFile.close();
fragmentFile.close();
vertexCodeInput = vertexFileStream.str();
fragmentCodeInput = fragmentFileStream.str();
}
catch(std::fstream::failure eX)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderSource = vertexCodeInput.c_str();
const char* fShaderSource = fragmentCodeInput.c_str();
unsigned int vertexShader, fragmentShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vShaderSource, NULL);
glCompileShader(vertexShader);
//check compilation result
int success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
char vShaderInfoLog[1024];
glGetShaderInfoLog(vertexShader, 1024, NULL, vShaderInfoLog);
std::cout << "Error::SHADER::VERTEX::COMPILATION_FAILED" << std::endl << vShaderInfoLog << std::endl;
}
success = 0;
//FRAGMENT SHADER
//create shader, load shader code, compile shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
char fShaderInfoLog[1024];
glGetShaderInfoLog(fragmentShader, 1024, NULL, fShaderInfoLog);
std::cout << "Error::SHADER::FRAGMENT::COMPILATION_FAILED" << std::endl << fShaderInfoLog << std::endl;
}
success = 0;
//create shader program, attach shaders
id = glCreateProgram();
glAttachShader(id, vertexShader);
glAttachShader(id, fragmentShader);
glLinkProgram(id);
glGetProgramiv(id, GL_LINK_STATUS, &success);
if (!success)
{
char shaderProgramInfoLog[1024];
glGetProgramInfoLog(id, 1024, NULL, shaderProgramInfoLog);
std::cout << "Error::SHADER::PROGRAM::COMPILATION_FAILED" << std::endl << shaderProgramInfoLog << std::endl;
}
success = 0;
//already linked shaders can be deleted
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
void Shader::use()
{
glUseProgram(id);
}
void Shader::setBoolUniform(const std::string pUniformName, const bool pValue) const
{
glUniform1i(glGetUniformLocation(id, pUniformName.c_str()), (int)pValue);
}
void Shader::setFloatUniform(const std::string pUniformName, const float pValue) const
{
glUniform1f(glGetUniformLocation(id, pUniformName.c_str()), pValue);
}
void Shader::setIntUniform(const std::string pUniformName, const unsigned int pValue) const
{
unsigned int uniformLocation = glGetUniformLocation(id, pUniformName.c_str());
glUniform1i(glGetUniformLocation(id, pUniformName.c_str()), pValue);
}
Thanks in advance!