簡體   English   中英

OpenGL:繪制立方體

[英]OpenGL: drawing a cube

我剛剛開始學習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 );
}

您的程序中有類型不匹配。 在此聲明中:

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

您是在說OpenGL將數據解釋為float,但是坐標點被聲明為double。

我建議您在坐標類型聲明時將GLdouble更改為GLfloat。

順便說一句,有了這些點,您將不會得到立方體,而只會得到它的局部草圖

除了其他答案外……還有更多選擇可以解決問題

  1. 錯誤的矩陣

    您必須實際查看對象,因此需要將相機的Z軸指向該對象(+ Z或-Z ...取決於所使用的投影)。 如果使用透視圖,則您的對象必須在<Znear,Zfar>范圍內

  2. 您正在通過8分立方體

    這是不夠的,因為多維數據集有6個面,每個面有4條線...以這種方式傳遞的點更多。 如果您有一個不錯的OpenGL驅動程序,則可以使用索引(元素數組),但應僅對元素數組使用GLuintQuads ...,因為某些gfx驅動程序存在奇數點基元和不同數據類型的問題(尤其是ATI中的ATI )過去...)。 如果您擁有nVidia,則應該可以,但是為了避免以后出現兼容性問題,...

  3. 啟用/禁用的功能

    啟用的紋理通常以黑色全部繪制,如果網格不正常或相機位於內部,則剔除的面孔可以跳過...另外,請檢查glDepthFunc並查看Z方向(或嘗試禁用GL_DEPTH_TEST

  4. 着色器

    您正在使用VBO / VAO,但是您的代碼中卻沒有着色器。 如果您不想使用着色器,則對於兼容nVidia的硬件,請使用默認布局位置 (但這是骯臟的不兼容技巧,不應用於公共應用程序...) 使用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
  • GL初始化后調用vao_init() (包括擴展名)
  • 在銷毀總帳前致電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.1zfar=100.0FOV角度為60度
  • 立方體在對焦點之前10個單位,因此在znear相機投影平面之前9.9個單位
  • 多維數據集大小為2個單位(+/- 1.0),因此適合放在截錐體中...

抽獎電話是這樣的:

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

[筆記]

例如,面沒有嚴格的多邊形纏繞,因此不要啟用CULL_FACE 另外,由於我的GL引擎的殘留,紋理禁用也是必需的(在我的App中)... 這只是一個骯臟的沒有着色器的示例,因此我使用了nVidia的默認布局位置,因此在不同的硬件上,您也需要着色器...請參見bullet #4

看來您的相機位於盒子內部,因此面部被剔除。 嘗試將盒子推到更遠的z位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM