Whatlahuhu
Whatlahuhu

Reputation: 19

draw sphere in OpenGL 4.0

my OpenGL version is 4.0. I would like to draw a sphere through latitude and longitude. I use this method:

x=ρsinϕcosθ
y=ρsinϕsinθ
z=ρcosϕ

This is a part of my code:

glm::vec3 buffer[1000];
glm::vec3 outer;
buffercount = 1000;
float section = 10.0f;
GLfloat  alpha, beta;
int index = 0;
for (alpha = 0.0 ; alpha <= PI; alpha += PI/section)
{
    for (beta = 0.0 ; beta <= 2* PI; beta += PI/section)
    {

        outer.x = radius*cos(beta)*sin(alpha);
        outer.y = radius*sin(beta)*sin(alpha);
        outer.z = radius*cos(alpha);

        buffer[index] = outer;
        index = index +1;

    }

}

GLuint sphereVBO, sphereVAO;

glGenVertexArrays(1, &sphereVAO);
glGenBuffers(1,&sphereVBO);
glBindVertexArray(sphereVAO);

glBindBuffer(GL_ARRAY_BUFFER,sphereVBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(glm::vec3) *buffercount  ,&buffer[0], GL_STATIC_DRAW);

glEnableVertexAttribArray(0);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
...
while (!glfwWindowShouldClose(window))
{
...
...

 for (GLuint i = 0; i < buffercount; i++)
    {
        ...
        ...
        glm::mat4 model;
        model = glm::translate(model, buffer[i]);
        GLfloat angle = 10.0f * i;
        model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
        glUniformMatrix4fv(modelMat, 1, GL_FALSE, glm::value_ptr(model));
    }


    glDrawArrays(GL_TRIANGLE_FAN, 0, 900);
    glfwSwapBuffers(window);
}

if section = 5, the performance is like this:

enter image description here

if section = 20. the performance is like this:

enter image description here

I think that I might have logic problem in my code. I am struggle in this problem...

-----update-----

I edited my code, It doesn't have any error, but I got a blank screen. I guess that something wrong in my vertex shader. I might pass wrong variables to vertex sheder. Please help me.

gluperspective is deprecated in my OpenGL 4.1 I switch to :

float aspect=float(4.0f)/float(3.0f);
glm::mat4 projection_matrix =  glm::perspective(60.0f/aspect,aspect,0.1f,100.0f); 

It shows that this error: constant expression evaluates to -1 which cannot be narrowed to type 'GLuint'(aka 'unsigned int')

GLuint sphere_vbo[4]={-1,-1,-1,-1};
GLuint sphere_vao[4]={-1,-1,-1,-1};

I'm not sure how to revise it...I switch to:

GLuint sphere_vbo[4]={1,1,1,1};
GLuint sphere_vao[4]={1,1,1,1};

I put Spektre's code in spherer.h file

This is a part of my main.cpp file:

...
...
Shader shader("basic.vert", "basic.frag");

sphere_init();

while (!glfwWindowShouldClose(window))
{

    glfwPollEvents();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    shader.Use();

    GLuint MatrixID = glGetUniformLocation(shader.Program, "MVP");

    GLfloat radius = 10.0f;
    GLfloat camX = sin(glfwGetTime()) * radius;
    GLfloat camZ = cos(glfwGetTime()) * radius;

    // view matrix
    glm::mat4 view;
    view = glm::lookAt(glm::vec3(camX, 0.0, camZ), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));
    glm::mat4 view_matrix  = view;

    // projection matrix
    float aspect=float(4.0f)/float(3.0f);
    glm::mat4 projection_matrix = glm::perspective(60.0f/aspect,aspect,0.1f,100.0f);

    // model matrix
    glm::mat4 model_matrix = glm::mat4(1.0f);// identity

    //ModelViewProjection
    glm::mat4 model_view_projection = projection_matrix * view_matrix * model_matrix;

    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &model_view_projection[0][0]);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0,0.0,-10.0);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    sphere_draw();
    glFlush();
    glfwSwapBuffers(window);
}

sphere_exit();
glfwTerminate();
return 0;
} 

This is my vertex shader file:

#version 410 core 

uniform mat4 MVP;

layout(location = 0) in vec3 vertexPosition_modelspace;
out vec4 vertexColor;

void main()
{
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
    vertexColor = vec4(0, 1, 0, 1.0);
}

I added error-check function get_log in my shader.h file.

...
...
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
get_log(vertex);

...
...
void get_log(GLuint shader){

GLint isCompiled = 0;
    GLchar infoLog[1024];
    glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
    if(isCompiled == GL_FALSE)
    {
        printf("----error--- \n");
        GLint maxLength = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
        glGetShaderInfoLog(shader, 1024, NULL, infoLog);
        std::cout << "| ERROR::::" << &infoLog << "\n| -- ------------------    --------------------------------- -- |" << std::endl;

        glDeleteShader(shader); // Don't leak the shader.

    }else{
        printf("---no error --- \n");
    }

}

I tested both fragment shader and vertex shader, it both showed ---no error---

Upvotes: 0

Views: 10502

Answers (1)

Spektre
Spektre

Reputation: 51933

As I mentioned in the comments you need to add indices to your mesh VAO/VBO. Not sure why GL_QUADS is not implemented on your machine that makes no sense as it is basic primitive so to make this easy to handle I use only GL_TRIANGLES which is far from ideal but what to heck ... Try this:

//---------------------------------------------------------------------------
const int na=36;        // vertex grid size
const int nb=18;
const int na3=na*3;     // line in grid size
const int nn=nb*na3;    // whole grid size
GLfloat sphere_pos[nn]; // vertex
GLfloat sphere_nor[nn]; // normal
//GLfloat sphere_col[nn];   // color
GLuint  sphere_ix [na*(nb-1)*6];    // indices
GLuint sphere_vbo[4]={-1,-1,-1,-1};
GLuint sphere_vao[4]={-1,-1,-1,-1};

void sphere_init()
    {
    // generate the sphere data
    GLfloat x,y,z,a,b,da,db,r=3.5;
    int ia,ib,ix,iy;
    da=2.0*M_PI/GLfloat(na);
    db=    M_PI/GLfloat(nb-1);
    // [Generate sphere point data]
    // spherical angles a,b covering whole sphere surface
    for (ix=0,b=-0.5*M_PI,ib=0;ib<nb;ib++,b+=db)
     for (a=0.0,ia=0;ia<na;ia++,a+=da,ix+=3)
        {
        // unit sphere
        x=cos(b)*cos(a);
        y=cos(b)*sin(a);
        z=sin(b);
        sphere_pos[ix+0]=x*r;
        sphere_pos[ix+1]=y*r;
        sphere_pos[ix+2]=z*r;
        sphere_nor[ix+0]=x;
        sphere_nor[ix+1]=y;
        sphere_nor[ix+2]=z;
        }
    // [Generate GL_TRIANGLE indices]
    for (ix=0,iy=0,ib=1;ib<nb;ib++)
        {
        for (ia=1;ia<na;ia++,iy++)
            {
            // first half of QUAD
            sphere_ix[ix]=iy;      ix++;
            sphere_ix[ix]=iy+1;    ix++;
            sphere_ix[ix]=iy+na;   ix++;
            // second half of QUAD
            sphere_ix[ix]=iy+na;   ix++;
            sphere_ix[ix]=iy+1;    ix++;
            sphere_ix[ix]=iy+na+1; ix++;
            }
        // first half of QUAD
        sphere_ix[ix]=iy;       ix++;
        sphere_ix[ix]=iy+1-na;  ix++;
        sphere_ix[ix]=iy+na;    ix++;
        // second half of QUAD
        sphere_ix[ix]=iy+na;    ix++;
        sphere_ix[ix]=iy-na+1;  ix++;
        sphere_ix[ix]=iy+1;     ix++;
        iy++;
        }
    // [VAO/VBO stuff]
    GLuint i;
    glGenVertexArrays(4,sphere_vao);
    glGenBuffers(4,sphere_vbo);
    glBindVertexArray(sphere_vao[0]);
    i=0; // vertex
    glBindBuffer(GL_ARRAY_BUFFER,sphere_vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(sphere_pos),sphere_pos,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    i=1; // indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,sphere_vbo[i]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(sphere_ix),sphere_ix,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,4,GL_UNSIGNED_INT,GL_FALSE,0,0);
    i=2; // normal
    glBindBuffer(GL_ARRAY_BUFFER,sphere_vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(sphere_nor),sphere_nor,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
/*
    i=3; // color
    glBindBuffer(GL_ARRAY_BUFFER,sphere_vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(sphere_col),sphere_col,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
*/
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
    }
void sphere_exit()
    {
    glDeleteVertexArrays(4,sphere_vao);
    glDeleteBuffers(4,sphere_vbo);
    }
void sphere_draw()
    {
    glEnable(GL_CULL_FACE);
    glFrontFace(GL_CCW);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glBindVertexArray(sphere_vao[0]);
//  glDrawArrays(GL_POINTS,0,sizeof(sphere_pos)/sizeof(GLfloat));                   // POINTS ... no indices for debug
    glDrawElements(GL_TRIANGLES,sizeof(sphere_ix)/sizeof(GLuint),GL_UNSIGNED_INT,0);    // indices (choose just one line not both !!!)
    glBindVertexArray(0);
    }

void gl_draw()
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float aspect=float(xs)/float(ys);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0/aspect,aspect,0.1,100.0);
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0,0.0,-10.0);

    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    sphere_draw();

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------

Usage is simple after OpenGL context is created and extensions loaded call sphere_init() before closing app call sphere_exit() (while OpenGL context is still running) and when you want to render call sphere_draw(). I make an gl_draw() example with some settings and here the preview of it:

preview

The point is to create 2D grid of points covering whole surface of sphere (via spherical long,lat a,b angles) and then just create triangles covering whole grid...

Upvotes: 4

Related Questions