切换顶点/颜色缓冲区的正确方法OpenGL

时间:2016-09-30 23:28:58

标签: c++ opengl

我正在尝试使用一个名为box()的常用函数在OpenGL 4.5中绘制多个框。它似乎工作得相当好,我可以让它制作多个盒子。

然而,我在绘制将成为圆柱底部的东西时遇到了麻烦。我试图通过制作多个三角形来生成面部。三角形在中心共享一个顶点,其他顶点基于角度。

我知道你可以使用三角形扇形或条形来做到这一点,但我需要能够为以后的每个顶点指定法线。

我的问题是,当我渲染这个场景时,我只看到一个孤独的三角形浮动。这提出了两个主要问题:

1)我哪里错了?我通过printf输出验证了x和z坐标是否正确,只是为了看看生成了什么。

2)在绘制完全不同的形状时,交换顶点和颜色缓冲区的正确方法是什么。例如,我需要能够最终调用box(),进行一些变换,调用cylinder()等。

//compiled with g++ -std=c++11 test.cpp -Wall -Werror -lglut -lGLU -lGL -lm -lGLEW


// Link statically with GLEW
#define GLEW_STATIC

// Headers
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

using namespace glm;

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

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>

#include <chrono>
using namespace std::chrono;

#include "cube.h"

#define Cos(x) (cos((x)*3.1415927/180))
#define Sin(x) (sin((x)*3.1415927/180))

GLuint MatrixID;
glm::mat4 MVP;
GLuint vertexbuffer;
GLuint colorbuffer;
GLuint shaderProgram;

high_resolution_clock::time_point t_start;

static const GLchar* vertexSource = {
        "#version 330 core\n"
        "\n"
        "// Input vertex data, different for all executions of this shader.\n"
        "layout(location = 0) in vec3 vertexPosition_modelspace;"
        "layout(location = 1) in vec3 vertexColor;"
        "\n"
        "// Output data ; will be interpolated for each fragment.\n"
        "out vec3 fragmentColor;"
        "// Values that stay constant for the whole mesh.\n"
        "uniform mat4 MVP;"
        "\n"
        "void main(){   "
        "\n"
        "   // Output position of the vertex, in clip space : MVP * position\n"
        "   gl_Position =  MVP * vec4(vertexPosition_modelspace,1);"
        "\n"
        "   // The color of each vertex will be interpolated\n"
        "   // to produce the color of each fragment\n"
        "   fragmentColor = vertexColor;"
        "}"
    };

static const GLchar* fragmentSource = {
        "#version 330 core\n"
        "\n"
        "// Interpolated values from the vertex shaders\n"
        "in vec3 fragmentColor;"
        "\n"
        "// Ouput data\n"
        "out vec3 color;"
        "\n"
        "void main(){"
        "\n"
        "   // Output color = color specified in the vertex shader, \n"
        "   // interpolated between all 3 surrounding vertices\n"
        "   color = fragmentColor;"
        "\n"
        "}"
    };

void checkError(int line)
{
    GLint err;

    do
    {
        err = glGetError();
        switch (err)
        {
            case GL_NO_ERROR:
                //printf("%d: No error\n", line);
                break;
            case GL_INVALID_ENUM:
                printf("%d: Invalid enum!\n", line);
                break;
            case GL_INVALID_VALUE:
                printf("%d: Invalid value\n", line);
                break;
            case GL_INVALID_OPERATION:
                printf("%d: Invalid operation\n", line);
                break;
            case GL_INVALID_FRAMEBUFFER_OPERATION:
                printf("%d: Invalid framebuffer operation\n", line);
                break;
            case GL_OUT_OF_MEMORY:
                printf("%d: Out of memory\n", line);
                break;
            default:
                printf("%d: glGetError default case. Should not happen!\n", line);
        }
    } while (err != GL_NO_ERROR);
}



int loadShaders()
{
    GLuint vertexShader;
    GLuint fragmentShader;

    // Create shaders
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);
        checkError(__LINE__);
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);
      checkError(__LINE__);  
    // Create program and link to shaders
    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glBindFragDataLocation(shaderProgram, 0, "color");
    glLinkProgram(shaderProgram);
  checkError(__LINE__);
    glUseProgram(shaderProgram);

    //TODO: add error checking and return code.
    checkError(__LINE__);
    return 0;
}

glm::mat4 Projection;
glm::mat4 View;
glm::mat4 Model;

void box()
{
    MVP        = Projection * View * Model; 

    // Send our transformation to the currently bound shader
    // in the "MVP" uniform
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

    glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
    Model = glm::mat4(1.0);
}


typedef struct __vertex
{
    GLfloat x;
    GLfloat y;
    GLfloat z;
} vertex_t;

typedef struct __color
{
    GLfloat r;
    GLfloat g;
    GLfloat b;
} color_t;

void cylinder()
{
    int theta = 0;
    int dt = 15;
    int i = 0;

    vertex_t *pVert;
    color_t *pColor;

    // Bottom face
    // 360 / dt = number of triangles
    // Multiplied by 3 verticies per triangle
    // Multiplied by 3 floating points to describe each vertex
    GLfloat *vertex_buffer_data = new GLfloat[360 / dt * 9];
    GLfloat *color_buffer_data = new GLfloat[360 / dt * 9];

    for (theta=0; theta < 360; theta += dt, i += sizeof(vertex_t) / sizeof(GLfloat))
    {
        pVert = (vertex_t *)(vertex_buffer_data + i);
        pColor = (color_t *)(color_buffer_data + i);

        printf("theta: %d\n", theta);
        pVert[0].x = 0;
        pVert[0].y = 0;
        pVert[0].z = 0;

        pVert[1].x = Cos(theta);
        pVert[1].y = 0;
        pVert[1].z = Sin(theta);
        printf("Vertex 1: %f %f %f\n", pVert[1].x, pVert[1].y, pVert[1].z);

        pVert[2].x = Cos(theta + dt);
        pVert[2].y = 0;
        pVert[2].z = Sin(theta + dt);
        printf("Vertex 2: %f %f %f\n", pVert[2].x, pVert[2].y, pVert[2].z);

        pColor[0].r = 1.0f;
        pColor[0].g = 1.0f;
        pColor[0].b = 1.0f;

        pColor[1].r = Cos(theta)*Cos(theta);
        pColor[1].g = Sin(theta)*Sin(theta);
        pColor[1].b = Cos(theta)*Cos(theta);

        pColor[1].r = Cos(theta + dt)*Cos(theta + dt);
        pColor[1].g = Sin(theta + dt)*Sin(theta + dt);
        pColor[1].b = Cos(theta + dt)*Cos(theta + dt);
    }

    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, vertex_buffer_data, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 360 / dt * 9, color_buffer_data, GL_STATIC_DRAW);

    MVP = Projection * View * Model;

    // Send our transformation to the currently bound shader, 
    // in the "MVP" uniform
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

    glDrawArrays(GL_TRIANGLES, 0, 360 / dt * 9); // 12*3 indices starting at 0 -> 12 triangles

    Model = glm::mat4(1.0);
    delete[] vertex_buffer_data;
    delete[] color_buffer_data;

}

void display()
{

    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);

    // Camera matrix
    View       = glm::lookAt(
                                glm::vec3(0,3,0), // Camera is at (4,3,-3), in World Space
                                glm::vec3(0,0,0), // and looks at the origin
                                glm::vec3(0,0,1)  // Head is up (set to 0,-1,0 to look upside-down)
                           );
    //auto t_now = high_resolution_clock::now();
    //float time = duration_cast<duration<float>>(t_now - t_start).count();



    glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    Model = glm::mat4(1.0);
    cylinder();

    /*
    Model =  glm::scale(Model, glm::vec3(0.5, 0.5, 0.5)) * glm::rotate(Model, glm::radians(180.0f), glm::vec3(0.0f, 0.0f, 1.0f));

    box();


    Model = glm::translate(Model, glm::vec3(0.5, 2.5, 0.0)) * glm::scale(Model, glm::vec3(0.25, 0.25, 0.25)) * glm::rotate(Model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 1.0f));

    box();
        */
    glFlush();
    glutSwapBuffers();
}

void reshape(int width,int height)
{
    //  Set viewport as entire window
    glViewport(0,0, width,height);
    glutPostRedisplay();
}

void idle()
{
    //glutPostRedisplay();
}
int init(int argc, char** argv)
{
    t_start = high_resolution_clock::now();
    glutInitWindowSize(640, 400);
    glutInitWindowPosition (140, 140);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
    glutInit(&argc, argv);

    glutCreateWindow( "OpenGL Application" );
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);

    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        return -1;
    }

    loadShaders();

    glEnable(GL_DEPTH_TEST);


    MatrixID = glGetUniformLocation(shaderProgram, "MVP");

    // Load models
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_vertex_buffer_data), g_cube_vertex_buffer_data, GL_STATIC_DRAW);


    glGenBuffers(1, &colorbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_cube_color_buffer_data), g_cube_color_buffer_data, GL_STATIC_DRAW);


    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // 2nd attribute buffer : colors
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
    glVertexAttribPointer(
        1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
        3,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );



    return 0;   
}

int main(int argc, char** argv)
{
    if (init(argc, argv) != 0) { return -1; }

    glutMainLoop();

    return 0;
}

cube.h只是顶点和颜色的缓冲区:

#ifndef __CUBE_H__
#define __CUBE_H__

    static const GLfloat g_cube_vertex_buffer_data[] = { 
        -1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
         1.0f, 1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f,-1.0f,
         1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,
         1.0f,-1.0f,-1.0f,
         1.0f, 1.0f,-1.0f,
         1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f,-1.0f,
         1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,
        -1.0f,-1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f,-1.0f, 1.0f,
         1.0f,-1.0f, 1.0f,
         1.0f, 1.0f, 1.0f,
         1.0f,-1.0f,-1.0f,
         1.0f, 1.0f,-1.0f,
         1.0f,-1.0f,-1.0f,
         1.0f, 1.0f, 1.0f,
         1.0f,-1.0f, 1.0f,
         1.0f, 1.0f, 1.0f,
         1.0f, 1.0f,-1.0f,
        -1.0f, 1.0f,-1.0f,
         1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f,-1.0f,
        -1.0f, 1.0f, 1.0f,
         1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
         1.0f,-1.0f, 1.0f
    };

    // One color for each vertex. They were generated randomly.
    static const GLfloat g_cube_color_buffer_data[] = { 
        0.583f,  0.771f,  0.014f,
        0.609f,  0.115f,  0.436f,
        0.327f,  0.483f,  0.844f,
        0.822f,  0.569f,  0.201f,
        0.435f,  0.602f,  0.223f,
        0.310f,  0.747f,  0.185f,
        0.597f,  0.770f,  0.761f,
        0.559f,  0.436f,  0.730f,
        0.359f,  0.583f,  0.152f,
        0.483f,  0.596f,  0.789f,
        0.559f,  0.861f,  0.639f,
        0.195f,  0.548f,  0.859f,
        0.014f,  0.184f,  0.576f,
        0.771f,  0.328f,  0.970f,
        0.406f,  0.615f,  0.116f,
        0.676f,  0.977f,  0.133f,
        0.971f,  0.572f,  0.833f,
        0.140f,  0.616f,  0.489f,
        0.997f,  0.513f,  0.064f,
        0.945f,  0.719f,  0.592f,
        0.543f,  0.021f,  0.978f,
        0.279f,  0.317f,  0.505f,
        0.167f,  0.620f,  0.077f,
        0.347f,  0.857f,  0.137f,
        0.055f,  0.953f,  0.042f,
        0.714f,  0.505f,  0.345f,
        0.783f,  0.290f,  0.734f,
        0.722f,  0.645f,  0.174f,
        0.302f,  0.455f,  0.848f,
        0.225f,  0.587f,  0.040f,
        0.517f,  0.713f,  0.338f,
        0.053f,  0.959f,  0.120f,
        0.393f,  0.621f,  0.362f,
        0.673f,  0.211f,  0.457f,
        0.820f,  0.883f,  0.371f,
        0.982f,  0.099f,  0.879f
    };

#endif // __CUBE_H__

0 个答案:

没有答案