user7695301
user7695301

Reputation: 7

What have I done wrong to render circle with mid point theoram using opengl?

I am not able to render circle with my following programme ,unable to detect problem in my code . This code compiles fine and runs but does not show the required output

This is the output:

In This code firstly initialization takes place using glfw then shaders are defined and uniform projection matrix is set up accordingly then rendering loop begins in which midPointCircleAlgo function is called which does the rendering , further plot function displays output on screen . Where am I going wrong .

This is vertex shader: -

#version 330 core
layout (location = 0) in vec2 apos;
uniform mat4 projection;
void main()
{
    gl_Position = projection*vec4(apos,0.0,1.0);
}
#include <glad/glad.h> 
#include <GLFW/glfw3.h>
#include <iostream>
#include "Header.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>


void framebuffer_size_callback(GLFWwindow *window, int width, int height); 
void plot(int x, int y);
void midPointCircleAlgo(int r);

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(800,600,"Circle",NULL,NULL);
    if(!window){
        std::cout << "Failed to open window";
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    glViewport(0,0,800,600);
    glfwSetFramebufferSizeCallback(window,framebuffer_size_callback);

    Shader shader("shader.vs","shader.fs");//I use a header file containing shader abstraction
    glm::mat4 projection;
    projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

    int pmatrix = glGetUniformLocation(shader.ID, "projection");
    shader.use();
    glUniformMatrix4fv(pmatrix,1,GL_FALSE,glm::value_ptr(projection));

    int r = 10;

    while(!glfwWindowShouldClose(window))
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        //render Circle
        shader.use();
        midPointCircleAlgo(10);

    glfwSwapBuffers(window);
        glfwPollEvents();    
    }

    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow *window,int width,int height){
    glViewport(0,0,width,height);   
}



void midPointCircleAlgo(int r)
{
    int x = 0;
    int y = r;
    float decision = 5 / 4 - r;
    plot(x, y);

    while (y > x)
    {
        if (decision < 0)
        {
            x++;
            decision += 2 * x + 1;
        }
        else
        {
            y--;
            x++;
            decision += 2 * (x - y) + 1;
        }
        plot(x, y);
        plot(x, -y);
        plot(-x, y);
        plot(-x, -y);
        plot(y, x);
        plot(-y, x);
        plot(y, -x);
        plot(-y, -x);
    }

}

void plot(int x,int y) 
{
    int vertices[] = { x,y};
    unsigned int VBO,VAO;
    glGenBuffers(1,&VBO);
    glGenVertexArrays(1,&VAO);
    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);

    glVertexAttribPointer(0, 2, GL_INT, GL_TRUE, 0, (void *)0);
    glEnableVertexAttribArray(0);   
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glDrawArrays(GL_POINTS, 0, 2);

    glDeleteBuffers(1, &VBO);
    glDeleteVertexArrays(1, &VAO);

}

Upvotes: 1

Views: 233

Answers (1)

Rabbid76
Rabbid76

Reputation: 211166

The first issue is the orthographic projection.

projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

Since your geometry is drawn at a z-coordinate of 0.0, it is clipped by the near plane of the projection (0.1). The circle is drawn around (0, 0), so you should choose a projection which keeps the center in the center of the viewport:

projection = glm::ortho(-400.0f, 400.0f, -300.0f, 300.0f, -1.0f, 1.0f);

When you use glVertexAttribPointer

glVertexAttribPointer(0, 2, GL_INT, GL_TRUE, 0, (void *)0);

then, the 4th parameter specifies whether fixed-point data values should be normalized (GL_TRUE) or converted directly as fixed-point values (GL_FALSE). This means, if the parameter is GL_TRUE, then the value in the range of the data type int are mapped to floating point values in the range [-1.0, 1.0]. You wan to convert the integral values 1:1 to flation point values, so the parameter has to be GL_FALSE:

 glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, (void *)0);

Note, alternatively you can use glVertexAttribIPointer (focus on I), which is for integral vertex shader input attributes:

glVertexAttribIPointer(0, 2, GL_INT, 0, (void *)0);

Of course, then the data type of the attribute in the vertex shader has to be ivec2 rather than vec2:

#version 330 core

layout (location = 0) in ivec2 apos;

uniform mat4 projection;

void main()
{ 
    gl_Position = projection * vec4(vec2(apos), 0.0, 1.0);
}

The idea of a buffer is to stor as many data as possible in the buffer and then render all the vertices at once.
But even if you want to draw a single point, it is a bad idea to create a Vertex Array Object and a Vertex Buffer Object for each point and to destroy it immediately after the drawing.

Create an empty buffer and and a vertex array object at initialization, before the main loop:

unsigned int VBO, VAO;

int main() {

    // [...]

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

    glGenBuffers(1,&VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, 2*sizeof(int), 0, GL_DYNAMIC_DRAW);

    glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, (void *)0);
    //glVertexAttribIPointer(0, 2, GL_INT, 0, (void *)0);
    glEnableVertexAttribArray(0);

    while(!glfwWindowShouldClose(window))
    {
        // [...]
    }

    // [...]
}

Use glBufferSubData to init/change the content of the buffer objects data store, before drawing the point:

void plot(int x, int y) 
{
    int vertices[] = {x, y};

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    glDrawArrays(GL_POINTS, 0, 1);
}

Side note, the 3rd parameter of glDrawArrays is the number of vertex coordinates, but not the number of elements in the array. The tuple size number of components per coordinate) is set in the vertex attribute specification.

Upvotes: 1

Related Questions