在 openGL 中使用索引缓冲区绘制立方体

问题描述 投票:0回答:1
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

#include <GL/glew.h>
#include <GL/glut.h>

#include <GL/glm/glm.hpp>
#include <GL/glm/gtx/transform.hpp> // rotate(), scale(), translate()
#include <GL/glm/gtc/quaternion.hpp>
#include <GL/glm/gtc/type_ptr.hpp>

using namespace std;

GLuint VertexArrayID;
GLuint programID;
float sx = 0;
float sy = 0;
bool projMode = true; // true: perspective, false: ortho

GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
{
    //create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    GLint Result = GL_FALSE;
    int InfoLogLength;

    //Read the vertex shader code from the file
    string VertexShaderCode;
    ifstream VertexShaderStream(vertex_file_path, ios::in);
    if (VertexShaderStream.is_open())
    {
        string Line = "";
        while (getline(VertexShaderStream, Line))
            VertexShaderCode += "\n" + Line;
        VertexShaderStream.close();
    }

    //Compile Vertex Shader
    printf("Compiling shader : %s\n", vertex_file_path);
    char const* VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
    glCompileShader(VertexShaderID);

    //Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        vector<char> VertexShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
    }

    //Read the fragment shader code from the file
    string FragmentShaderCode;
    ifstream FragmentShaderStream(fragment_file_path, ios::in);
    if (FragmentShaderStream.is_open())
    {
        string Line = "";
        while (getline(FragmentShaderStream, Line))
            FragmentShaderCode += "\n" + Line;
        FragmentShaderStream.close();
    }

    //Compile Fragment Shader
    printf("Compiling shader : %s\n", fragment_file_path);
    char const* FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
    glCompileShader(FragmentShaderID);

    //Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if (InfoLogLength > 0) {
        vector<char> FragmentShaderErrorMessage(InfoLogLength);
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
    }

    //Link the program
    fprintf(stdout, "Linking program\n");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    vector<char> ProgramErrorMessage(max(InfoLogLength, int(1)));
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}

void renderScene(void)
{
    //Clear all pixels
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //Let's draw something here

    glBindVertexArray(VertexArrayID);
    //define the size of point and draw a point.
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
    
    //Double buffer
    glutSwapBuffers();
}

void mouse(int button, int state, int x, int y) {
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        projMode = !projMode;
    }
}

void init()
{
    //initilize the glew and check the errors.
    GLenum res = glewInit();
    if (res != GLEW_OK)
    {
        fprintf(stderr, "Error: '%s' \n", glewGetErrorString(res));
    }

    //select the background color
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
    glEnable(GL_DEPTH_TEST);

    glDepthFunc(GL_LESS);
    glDepthRange(0.0f, 1.0f);
}

GLfloat cubeVertices[] = {
    // front
   -0.1f, 0.1f, 0.1f,
   -0.1f,-0.1f, 0.1f,
   0.1f,-0.1f, 0.1f,
   0.1f, 0.1f, 0.1f,
   -0.1f, 0.1f, 0.1f,
   0.1f,-0.1f, 0.1f,

    // back
    0.1f, 0.1f,-0.1f,
    -0.1f,-0.1f,-0.1f,
    -0.1f, 0.1f,-0.1f,
    0.1f, 0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    -0.1f,-0.1f,-0.1f,

    // left
    -0.1f,-0.1f,-0.1f,
    -0.1f,-0.1f, 0.1f,
    -0.1f, 0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,
    -0.1f, 0.1f, 0.1f,
    -0.1f, 0.1f,-0.1f,

   

    // right
    0.1f, 0.1f, 0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f, 0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f, 0.1f, 0.1f,
    0.1f,-0.1f, 0.1f,

    // bottom
    0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,
    0.1f,-0.1f,-0.1f,
    0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f, 0.1f,
    -0.1f,-0.1f,-0.1f,

    // top
    1.1f, 0.1f, 0.1f,
    0.1f, 0.1f,-0.1f,
    -0.1f, 0.1f,-0.1f,
    0.1f, 0.1f, 0.1f,
    -0.1f, 0.1f,-0.1f,
    -0.1f, 0.1f, 0.1f,
};

GLfloat cubeColors[] = {
    // red
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,
    1.0, 0.0, 0.0, 1.0,

    // green
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,
    0.0, 1.0, 0.0, 1.0,

    // blue
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,
    0.0, 0.0, 1.0, 1.0,

    // yellow
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,
    1.0, 1.0, 0.0, 1.0,

    // cyan
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,
    1.0, 0.0, 1.0, 1.0,

    // magenta
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
    0.0, 1.0, 1.0, 1.0,
};
/* idx | coord:
0 | (1,1,1)
1 | (-1, 1, 1)
2 | (-1,-1,1)
3 | (1, -1, 1)
4 | (1, -1, -1)
5 | (1, 1, -1)
6 | (-1, 1, -1)
7 | (-1, -1, -1) */
GLfloat cubeIndices[] = {
    // front
    0, 1, 2,
    0, 1, 3,

    // back
    5, 6, 7,
    5, 6, 4,
    
    // left
    1, 2, 6,
    1, 2, 7,

    // right
    0, 3, 4,
    0, 4, 5,

    // top
    0, 1, 5,
    0, 1, 6,

    // bottom
    2, 3, 4,
    2, 4, 7,
};

int main(int argc, char** argv)
{
    //init GLUT and create Window
    //initialize the GLUT
    glutInit(&argc, argv);
    //GLUT_DOUBLE enables double buffering (drawing to a background buffer while the other buffer is displayed)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

    //These two functions are used to define the position and size of the window. 
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(480, 480);
    //This is used to define the name of the window.
    glutCreateWindow("Simple OpenGL Window");

    //call initization function
    init();
    //0.
    programID = LoadShaders("VertexShader.txt", "FragmentShader.txt");
    glUseProgram(programID);

    /**************************************************/
    // model matrix
    glm::mat4 model = glm::mat4(1.0f); 
    float rotateAngle = 45.0f; 
    glm::vec3 rotateAxis(0.0f, 1.0f, 0.0f); 
    model = glm::rotate(model, glm::radians(rotateAngle), rotateAxis);

    glm::vec3 scaleVec(5.0f, 5.0f, 5.0f); 
    model = glm::scale(model, scaleVec);

    glm::vec3 translateVec(0.0f, 0.0f, 0.0f);
    model = glm::translate(model, translateVec);

    // view matrix
    glm::mat4 view = glm::lookAt(glm::vec3(5.0f, -5.0f, -5.0f),
        glm::vec3(0.0f, 0.0f, 0.0f), 
        glm::vec3(0.0f, 1.0f, 0.0f)); 

    // proj matrix
    glm::mat4 proj;
    int width = glutGet(GLUT_WINDOW_WIDTH);
    int height = glutGet(GLUT_WINDOW_HEIGHT);
    if (projMode) {
        float aspectRatio = float(width) / height; 
        proj = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 100.0f); 
    }
    else {
        float orthoSize = 5.0f;
        proj = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, 0.1f, 0.6f);
    }

    // model, view, proj matrix to shader
    GLint modelLoc = glGetUniformLocation(programID, "model");
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    GLint viewLoc = glGetUniformLocation(programID, "view");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

    GLint projLoc = glGetUniformLocation(programID, "proj");
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(proj));

    /**************************************************/
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    float vtxs[] = { -0.5, 0.0, 0.0, 0.5, 0.3, 0.0 };
    GLuint VBOs[3];
    glGenBuffers(3, VBOs);

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * 3 * 2 * 6, cubeVertices, GL_STATIC_DRAW);
    GLuint posAttribLoc = glGetAttribLocation(programID, "inPos");
    glVertexAttribPointer(posAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(posAttribLoc);     
    
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 3 * 2 * 6, cubeColors, GL_STATIC_DRAW); 
    GLuint colAttribLoc = glGetAttribLocation(programID, "color");
    glVertexAttribPointer(colAttribLoc, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(colAttribLoc);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBOs[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(float) * 6 * 6, cubeIndices, GL_STATIC_DRAW);
    GLuint idxAttribLoc = glGetAttribLocation(programID, "index");
    glVertexAttribPointer(idxAttribLoc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(0));
    glEnableVertexAttribArray(idxAttribLoc);

    glutDisplayFunc(renderScene);
    glutMouseFunc(mouse);

    //enter GLUT event processing cycle
    glutMainLoop();

    glDeleteVertexArrays(1, &VertexArrayID);

    return 1;
}

我想用上面的代码绘制一个 3D 立方体,但我得到一个白色的窗口。如何在窗口上显示 3D 立方体? 如果我对 VBO 和 IBO 使用像“VBOs”这样的数组,如上面的代码所示,会出现问题吗?

另外,你能告诉我如何绘制多个立方体吗? 最后,如果您告诉我我的代码中还有其他问题,我将非常感谢您。

我是一个完全的初学者,说实话,我并不完全理解图形管道。但我真的很感谢你对我的作业的帮助。

opengl rotation projection glm translate
1个回答
0
投票

type
的参数
glDrawElements
为整数1。

您已将索引定义为实数数组:

GLfloat cubeIndices[] = {
    // front
    0, 1, 2,

因此,当

glDrawElements
工作并读取
cubeIndices
的内存时,它会遇到一些巨大的值(例如,整数值 1 作为浮点数为 0x3f80'0000)。您定义的索引完全不在顶点属性数组确定的范围内。

© www.soinside.com 2019 - 2024. All rights reserved.