首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >OpenGL:绘制立方体

OpenGL:绘制立方体
EN

Stack Overflow用户
提问于 2015-02-25 14:20:23
回答 3查看 5K关注 0票数 0

我刚开始学习OpenGL,这是我第一个绘制立方体的程序。我完全迷失在这里,因为我能够通过在2d中指定矩形的坐标来绘制一个矩形,但是我不能通过指定(x,y,z)格式的坐标来绘制立方体。我在这里错过了什么?

以下是代码:

代码语言:javascript
运行
复制
#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 );
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-25 15:31:26

您的程序中存在类型不匹配。在本声明中:

代码语言:javascript
运行
复制
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

您对OpenGL说要将您的数据解释为浮动,但是您的坐标点被声明为双倍。

我建议您在坐标类型声明中将GLdouble更改为GLfloat。

顺便说一句,有了这些点,你就不会得到一个立方体,而只是它的部分草图。

票数 4
EN

Stack Overflow用户

发布于 2015-02-26 08:51:24

除了其他答案..。好吧,可能有更多的选择--出了什么问题

  1. 错矩阵 你必须看着物体,所以你需要把相机的Z轴指向物体(+Z或-Z .取决于所使用的投影)。如果使用透视图,则对象必须在<Znear,Zfar>范围内。
  2. 你要通过8点立方体 这是不够的,因为立方体有6个边,每个边有4行.这是更多的分数,通过这种方式。如果您有一个不错的OpenGL驱动程序,那么您可以使用索引(元素数组),但是应该只对元素数组使用GLuintQuads .因为一些gfx驱动程序存在奇点原语和不同数据类型的问题(特别是过去的ATI .)。如果您得到了nVidia,那么您应该很好,但是为了避免以后的兼容性问题.
  3. 一些剩余的启用/禁用的 启用的纹理通常都用黑色绘制,如果网格不确定或者相机在里面,裁剪脸可以跳过。检查glDepthFunc并查看Z方向(或尝试禁用GL_DEPTH_TEST)
  4. 着色器 您正在使用VBO/VAO,但是在代码中没有着色器--无论如何。如果您不想使用着色器,那么对于、nVidia、兼容的HW,使用default layout locations (但这是肮脏的不兼容技巧,不应该用于公共应用程序.)。使用glVertexPointer,glColorPointer,...代替或编写简单的着色器模拟固定的功能,您需要的支持。

我的C++示例:

代码语言:javascript
运行
复制
//------------------------------------------------------------------------------
//--- 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() (包括扩展)
  • 在GL销毁之前调用vao_exit()
  • 调用vao_draw()内部绘制循环

地雷矩阵是这样的:

代码语言:javascript
运行
复制
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.0视场角为60度
  • 立方体是焦点前的10个单元,所以是znear摄像机投影平面之前的9.9个单元。
  • 立方体大小是两个单位(+/-1.0),所以它适合内部挫折.

抽奖是这样的:

代码语言:javascript
运行
复制
glDisable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
vao_draw();

Notes

例如,脸部没有严格的多边形缠绕,所以不要启用CULL_FACE!此外,纹理禁用是必要的(在我的应用程序),因为剩余的地雷GL引擎.,这只是脏,没有着色器,现在的例子,所以我使用nVidia的默认布局位置在不同的HW,你也需要着色器.见子弹#4

票数 1
EN

Stack Overflow用户

发布于 2015-02-25 14:34:40

看起来你的相机就在盒子里,这样你的脸就会被剔除。试着把盒子推到更远的z位置。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28721385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档