OpenGL: рисование куба

Я только начал изучать OpenGL, и это моя первая программа для рисования куба. Я совершенно растерялся, поскольку смог нарисовать прямоугольник, указав координаты для прямоугольника в 2d, но я не могу нарисовать куб, указав координаты в формате (x, y, z). Что мне здесь не хватает?

Вот код:

#include <GL/glew.h>
#include <GL/gl.h>
#include <math.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

// Open an OpenGL window
GLFWwindow* window;

/****Step 1: define vertices in (x, y, z) form****/

// Coordinates to draw a cube
const GLdouble coordinates[8][3] = {
    {-0.5, -0.5, -0.5},
    {0.5, -0.5, -0.5},
    {0.5, -0.5, 0.5},
    {-0.5, -0.5, 0.5},
    {-0.5, 0.5, 0.5},
    {-0.5, 0.5, -0.5},
    {0.5, 0.5, -0.5},
    {0.5, 0.5, 0.5}
};
/************************/


int main( void ) {
    if (!glfwInit()){
        fprintf(stderr, "Failed to initialize GLFW.\n");
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(700, 500, "Hello World", NULL, NULL);
    if (window == NULL) {
            fprintf(stderr, "glfw failed to create window.\n");
            //glfwTerminate();
            return -1;
            }
    // Make the window's context current
    glfwMakeContextCurrent(window);

    glewInit();
    if (glewInit() != GLEW_OK){
        fprintf(stderr, "Failed to initialize GLEW: %s.\n", glewGetErrorString(glewInit()));
        return -1;
    }
    // 4x anti aliasing
    glfwWindowHint(GLFW_SAMPLES, 4);

    int cube_size = sizeof(coordinates)/sizeof(coordinates[0]);
    /**Step 2: send this cube vertices to OpenGL through a buffer**/
    GLuint vertexBuffer; // Declare vertex buffer
    glGenBuffers(1, &vertexBuffer); // generating 1 buffer, put resulting identifier in this buffer
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, cube_size*12, coordinates, GL_STATIC_DRAW);
    /************************/

    std::cout << sizeof(coordinates)/sizeof(coordinates[0]);

    /**Step 3: Main loop for OpenGL draw the shape**
    /* Main loop */
    do{
        glClearColor(1.0, 0.1, 0.1, .0);
        glClear(GL_COLOR_BUFFER_BIT);

        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
        glDrawArrays(GL_LINE_LOOP, 0, cube_size);
        glDisableVertexAttribArray(0);

        // Swap front and back rendering buffers
        glfwSwapBuffers(window);
        //Poll for and process events
        glfwPollEvents();
    } // check if the ESC key was pressed or the window was closed
    while(glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0);
    /***********************************************/


    // Close window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();
    // Exit program
    exit( EXIT_SUCCESS );
}

3 ответа

Решение

У вас несоответствие типов в вашей программе. В этой декларации:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

вы говорите OpenGL интерпретировать ваши данные как плавающие, но ваши координаты объявляются двойными.

Я предлагаю вам изменить GLdouble на GLfloat при объявлении типа координат.

Кстати, с этими точками вы не получите куб, а только его частичный набросок

В дополнение к другим ответам... ну может быть больше вариантов, что не так

  1. неправильные матрицы

    Вы должны смотреть на объект на самом деле, поэтому вам нужно направить ось Z камеры к объекту (+Z или -Z ... зависит от используемой проекции). Если вы используете перспективу, то ваш объект должен быть внутри <Znear,Zfar> спектр

  2. Вы проходите 8 очков куба

    Этого недостаточно, поскольку у куба есть 6 сторон, каждая из которых имеет 4 линии... это немного больше точек, которые нужно пройти таким образом. Если у вас есть достойный драйвер OpenGL, вы можете использовать индексы (массив элементов), но тогда вы должны использовать только GLuint а также Quads для массива элементов... потому что у некоторых драйверов gfx были проблемы с примитивами нечетных точек и разными типами данных (особенно ATI в прошлом...). Если у вас есть nVidia, то у вас все будет хорошо, но чтобы избежать проблем с совместимостью в будущем...

  3. что-то осталось включено / отключено

    включенные текстуры, как правило, рисуют все черным цветом, отборная грань может пропустить, если сетка не в порядке или камера находится внутри... Также проверьте glDepthFunc и просмотр направления Z (или попробуйте отключить GL_DEPTH_TEST)

  4. шейдер

    Вы используете VBO/VAO, но в вашем коде нет шейдеров. Если вы не хотите использовать шейдеры, тогда для HVidia- совместимых HW используйте расположение макетов по умолчанию (но это грязная несовместимая уловка и не должна использоваться для публичных приложений...). использование glVertexPointer,glColorPointer,... вместо этого или напишите легкий шейдер, эмулирующий фиксированную функциональность того, что вам нужно, поддерживается

мой пример C++:

//------------------------------------------------------------------------------
//--- Open GL VAO example ------------------------------------------------------
//------------------------------------------------------------------------------
#ifndef _OpenGL_VAO_example_h
#define _OpenGL_VAO_example_h
//------------------------------------------------------------------------------
GLuint vbo[4]={-1,-1,-1,-1};
GLuint vao[4]={-1,-1,-1,-1};
const GLfloat vao_pos[]=
    {
//  x    y    z
    -1.0,-1.0,-1.0,
    +1.0,-1.0,-1.0,
    +1.0,+1.0,-1.0,
    -1.0,+1.0,-1.0,
    -1.0,-1.0,+1.0,
    +1.0,-1.0,+1.0,
    +1.0,+1.0,+1.0,
    -1.0,+1.0,+1.0,
    };

const GLfloat vao_col[]=
    {
//  r   g   b
    0.0,0.0,0.0,
    1.0,0.0,0.0,
    1.0,1.0,0.0,
    0.0,1.0,0.0,
    0.0,0.0,1.0,
    1.0,0.0,1.0,
    1.0,1.0,1.0,
    0.0,1.0,1.0,
    };

const GLuint vao_ix[]=
    {
    0,1,2,3,
    4,5,6,7,
    0,1,5,4,
    1,2,6,5,
    2,3,7,6,
    3,0,4,7,
    };
//---------------------------------------------------------------------------
void vao_init()
    {
    GLuint i;
    glGenVertexArrays(4,vao);
    glGenBuffers(4,vbo);
    glBindVertexArray(vao[0]);
    i=0; // vertex
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_pos),vao_pos,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,0,0);
    i=1; // indices
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vao_ix),vao_ix,GL_STATIC_DRAW);
    glEnableVertexAttribArray(i);
    glVertexAttribPointer(i,4,GL_UNSIGNED_INT,GL_FALSE,0,0);
    i=2; // normal
    i=3; // color
    glBindBuffer(GL_ARRAY_BUFFER,vbo[i]);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vao_col),vao_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 vao_exit()
    {
    glDeleteVertexArrays(4,vao);
    glDeleteBuffers(4,vbo);
    }
//---------------------------------------------------------------------------
void vao_draw()
    {
    glBindVertexArray(vao[0]);
//  glDrawArrays(GL_LINE_LOOP,0,8);                 // lines ... no indices
    glDrawElements(GL_QUADS,24,GL_UNSIGNED_INT,0);  // indices (choose just one line not both !!!)
    glBindVertexArray(0);
    }
//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------
//--- end. ---------------------------------------------------------------------
//------------------------------------------------------------------------------

Вот как это выглядит:

пример

  • левая сторона окрашена glDrawArrays
  • правая сторона окрашена glDrawElements
  • вызов vao_init() после инициализации GL (включая расширения)
  • вызов vao_exit() до уничтожения ГЛ
  • вызов vao_draw() внутри цикла отрисовки

Мои матрицы такие:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,float(scr.xs)/float(scr.ys),0.1,100.0);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-10.0);

где:

  • scr.xs,scr.ys такое разрешение окна GL
  • modelview вращается в таймере, чтобы оживить куб...
  • znear=0.1, zfar=100.0, Угол обзора составляет 60 градусов
  • куб находится за 10 единиц до точки фокусировки, поэтому за 9,9 единиц до znear плоскость проецирования камеры
  • размер куба составляет 2 единицы (+/-1,0), поэтому он помещается внутри усеченного...

Назови колл так:

glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
vao_draw();

[Заметки]

В примере грани не имеют строгой многоугольной намотки, поэтому не включайте CULL_FACE!!! Также необходимо отключить текстуру (в моем приложении) из-за остатка от моего движка GL... Это просто грязный пример без шейдера, поэтому я использовал расположение макетов по умолчанию в nVidia, так что на разных HW вам также нужен шейдер... см. Маркер #4

Кажется, что ваша камера находится внутри коробки, поэтому лицо выбраковывается. Попробуйте переместить коробку в более удаленное положение z.

Другие вопросы по тегам