I’m trying to use glfw+glad to draw lines with mouse click input coordinates. At first i tried to use glBegin,glVertex2f but they seems to be no longer suppotered in OpenGL3+. So i tried to use VAO,VBO to draw lines,but the actual program doesn’t react on my click.
Progame Running:
Program Running
Here is my code:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
#include <cmath>
class Vec3 {
public:
float x, y, z;
Vec3() : x(0), y(0), z(0) {}
Vec3(float x, float y, float z) : x(x), y(y), z(z) {}
Vec3 operator+(const Vec3& other) const {
return Vec3(x + other.x, y + other.y, z + other.z);
}
Vec3 operator-(const Vec3& other) const {
return Vec3(x - other.x, y - other.y, z - other.z);
}
Vec3 operator*(float scalar) const {
return Vec3(x * scalar, y * scalar, z * scalar);
}
Vec3 operator/(float scalar) const {
return Vec3(x / scalar, y / scalar, z / scalar);
}
};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
void mouse_button_callback(GLFWwindow* window,int button, int action, int mods);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
bool firstClick = true;
float x0,y0,z0,x1,y1,z1;
class Line{
int shaderProgram;
unsigned int VBO,VAO;
std::vector<float> vertices;
Vec3 startPoint;
Vec3 endPoint;
Vec3 lineColor;
public:
Line(Vec3 start,Vec3 end){
startPoint = start;
endPoint = end;
lineColor = Vec3(1.0f,1.0f,1.0f);
init();
}
void init(){
const char *vertexShaderSource = "#version 330 coren"
"layout (location = 0) in vec3 aPos;n"
"void main()n"
"{n"
" gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);n"
"}";
const char* fragmentShaderSource = "#version 330 coren"
"out vec4 FragColor;n"
"uniform vec3 color;n"
"void main()n"
"{n"
" FragColor = vec4(color, 1.0f);n"
"}n";
//vertex Shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
glCompileShader(vertexShader);
//check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILEDn" << infoLog << std::endl;
}
//fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
glCompileShader(fragmentShader);
//check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILEDn" << infoLog << std::endl;
}
//link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glLinkProgram(shaderProgram);
//check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILEDn" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGenVertexArrays(1,&VAO);
glGenBuffers(1,&VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices.data(),GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
}
void updateVerticesDDA(){
vertices.clear();
float x0 = startPoint.x;
float y0 = startPoint.y;
float x1 = endPoint.x;
float y1 = endPoint.y;
float dx = x1 - x0;
float dy = y1 - y0;
float steps = std::max(std::abs(dx), std::abs(dy));
float xIncrement = dx / steps;
float yIncrement = dy / steps;
float x = x0;
float y = y0;
for (int i = 0; i <= steps; ++i)
{
vertices.push_back(x);
vertices.push_back(y);
vertices.push_back(0.0f); // z-coordinate
x += xIncrement;
y += yIncrement;
}
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data());
}
int draw(){
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_POINTS,0,vertices.size()/3);
return 1;
}
~Line(){
glDeleteVertexArrays(1,&VAO);
glDeleteBuffers(1,&VBO);
glDeleteProgram(shaderProgram);
}
void updateVerticesBresenham() {
vertices.clear();
int x0 = startPoint.x * SCR_WIDTH / 2 + SCR_WIDTH / 2;
int y0 = startPoint.y * SCR_HEIGHT / 2 + SCR_HEIGHT / 2;
int x1 = endPoint.x * SCR_WIDTH / 2 + SCR_WIDTH / 2;
int y1 = endPoint.y * SCR_HEIGHT / 2 + SCR_HEIGHT / 2;
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sx = (x0 < x1) ? 1 : -1;
int sy = (y0 < y1) ? 1 : -1;
int err = dx - dy;
while (true)
{
vertices.push_back((x0 - SCR_WIDTH / 2) / (SCR_WIDTH / 2));
vertices.push_back((SCR_HEIGHT / 2 - y0) / (SCR_HEIGHT / 2));
vertices.push_back(0.0f); // z-coordinate
if (x0 == x1 && y0 == y1)
break;
int e2 = 2 * err;
if (e2 > -dy)
{
err -= dy;
x0 += sx;
}
if (e2 < dx)
{
err += dx;
y0 += sy;
}
}
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(float), vertices.data());
}
};
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Line Drawing with DDA / Bresenham", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
Vec3 start(x0,y0,z0);
Vec3 end(x1,y1,z1);
Line line(start,end);
//loop for render
while(!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.2f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
line.updateVerticesDDA();
line.draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window){
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window,true);
}
void mouse_button_callback(GLFWwindow* window,int button,int action,int mods){
if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
double xpos,ypos;
glfwGetCursorPos(window,&xpos,&ypos);
if (firstClick)
{
x0 = (xpos - SCR_WIDTH / 2) / (SCR_WIDTH / 2);
y0 = (SCR_HEIGHT / 2 - ypos) / (SCR_HEIGHT / 2);
z0 = 0.0f; // 2D plane
firstClick = false;
}
else
{
x1 = (xpos - SCR_WIDTH / 2) / (SCR_WIDTH / 2);
y1 = (SCR_HEIGHT / 2 - ypos) / (SCR_HEIGHT / 2);
z1 = 0.0f; // 2D plane
firstClick = true;
}
}
}
I don’t know whether it’s the mouse callback function or the Line class that went wrong, and i’ve just started to learn OpenGL so it’s quite complex for me to check the VBO stuff.
Please help me to figure out what part went wrong, thxxx!!!
BTW can the VBO method enable straight line drawing under the DDA algorithm? It’s kinda easy when using glVertex2f method (I tried to updates vertices and draw many points but i got stuck here qaq)
Azemmmm is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
6