3

对于看过我之前问题的任何人,在完成了 2.1 版的红皮书之后,我现在转向 4.3 版。(你说老胡说,因为你们中的许多人多年来一直告诉我这样做。)

所以,我已经深入第 3 章,但仍然没有让第 1 章的示例程序正常工作。

我有两个问题。(实际上是3。)首先,它不编译。好的,这是一个问题,但考虑到接下来的两个,有点无关紧要。其次,我不完全了解它是如何工作的或它试图做什么,但我们会继续讨论的。

第三,在我看来,这段代码的作者是个十足的魔术师。我建议这里正在发生各种修补黑客行为。这很可能是因为第 2 个问题,即我不明白它要做什么。写这本书的人当然不是白痴,但请耐心等待,我举个例子。

这是取自main.cpp文件顶部的一段代码。稍后我将包含文件的其余部分,但现在:

enum VAO_IDs {
    Triangles,
    NumVAOs
};

如果我理解正确,这给出VAO_IDs::Triangles了 的值1,因为枚举是从零开始的。(我希望我在这里是正确的,否则我会很尴尬。)

片刻之后,您可以看到这一行:

GLuint VAOs[NumVAOs];

GLuint由于 NumVAOs 等于 1,它声明了一个包含 1 个 GLuint 的数组。现在,首先,不应该VAO_IDs::NumVAOs吗?

其次,到底为什么以这种方式使用枚举?出于显而易见的原因,我永远不会使用这样的枚举 - 不能有多个具有相同值的数据,没有明确指定值等等......

我在这里吠叫正确的树吗?这样做是没有意义的...... VAO 应该是一个全球性的,像这样,肯定吗?GLuint NumVAOs = 1;这只是对枚举的滥用!

事实上,下面的语句const GLuint NumVertices = 6;出现了。这是有道理的,不是吗,因为我们可以根据需要更改值 6,但我们不能将 NumVAOs 更改为 0,例如,因为 Triangles 已经设置为 0。(为什么它在枚举中?说真的?)

无论如何,忘记枚举的......现在......好吧,所以我做了很多事情,这就是问题的结束......我有任何进一步的评论现在都在代码中。你可以忽略大部分 glfw 的东西,它本质上与 glut 相同。

// ----------------------------------------------------------------------------
//
// Triangles - First OpenGL 4.3 Program
//
// ----------------------------------------------------------------------------

#include <cstdlib>
#include <cstdint>
#include <cmath>

#include <stdio.h>
#include <iostream>

//#include <GL/gl.h>
//#include <GL/glu.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>


/// OpenGL specific
#include "vgl.h"
#include "LoadShaders.h" // These are essentially empty files with some background work going on, nothing declared or defined which is relevant here

enum VAO_IDs {
    Triangles,
    NumVAOs
};
// So Triangles = 0, NumVAOs = 1
// WHY DO THIS?!

enum Buffer_IDs {
    ArrayBuffer,
    NumBuffers
};

enum Attrib_IDs {
    vPosition = 0
}
// Please, please, please someone explain the enum thing to me, why are they using them instead of global -just- variables.
// (Yeah an enum is a variable, okay, but you know what I mean.)

GLuint VAOs[NumVAOs]; // Compile error: expected initializer before 'VAOs'
GLuint Buffers[NumBuffers]; // NumBuffers is hidden in an enum again, so it NumVAOs

const GLuint NumVertices = 6; // Why do something different here?

// ----------------------------------------------------------------------------
//
// Init
//
// ----------------------------------------------------------------------------

void init()
{
    glGenVertexArrays(NumVAOs, VAOs); // Error: VAOs was not declared in this scope
    glBindVertexArray(VAOs[Triangles]);

    GLfloat vertices[NumVertices][2] = {
        { -0.90, -0.90 },
        { +0.85, -0.90 },
        { -0.90, +0.85 },
        { +0.90, -0.85 },
        { +0.90, +0.90 },
        { -0.85, +0.90 }
    };

    glGenBuffers(NumBuffers, Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    ShaderInfo shaders[] = {
        { GL_VERTEX_SHADER, "triangles.vert" },
        { GL_FRAGMENT_SHADER, "triangles.frag" },
        { GL_NONE, nullptr }
    };

    GLuint program = LoadShaders(shaders);
    glUseProgram(program);

    glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    glEnableVertexAttribArray(vPosition);
}

// ----------------------------------------------------------------------------
//
// Display
//
// ----------------------------------------------------------------------------

void display()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBindVertexArray(VAOs[Triangles]);
    glDrawArrays(GL_TRIANGLES, 0, NumVertices); // Error VAOs not declared

    glFlush();
}

// ----------------------------------------------------------------------------
//
// Main
//
// ----------------------------------------------------------------------------

void error_handle(int error, const char* description)
{
    fputs(description, stderr);
}

void key_handle(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);

}


void handle_exit()
{

}


int main(int argc, char **argv)
{

    // Setup exit function
    atexit(handle_exit);


    // GLFW Window Pointer
    GLFWwindow* window;


    // Setup error callback
    glfwSetErrorCallback(error_handle);


    // Init
    if(!glfwInit())
    {
        exit(EXIT_FAILURE);
    }


    // Setup OpenGL
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);


    // Set GLFW window hints
    glfwWindowHint(GLFW_DEPTH_BITS, 32);
    glfwWindowHint(GLFW_RED_BITS, 8);
    glfwWindowHint(GLFW_GREEN_BITS, 8);
    glfwWindowHint(GLFW_BLUE_BITS, 8);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


    // Init GLEW
    if(glewInit())
    {
        printf("GLEW init failure!\n", stderr);
        exit(EXIT_FAILURE);
    }


    // Init OpenGL
    init();


    // Create Window
    window = glfwCreateWindow(800, 600, "Window Title", nullptr, nullptr);
    if(!window)
    {
        glfwTerminate();
        return EXIT_FAILURE;
    }

    // Make current
    glfwMakeContextCurrent(window);


    // Set key callback
    glfwSetKeyCallback(window, key_handle);


    // Check OpenGL Version
    char* version;
    version = (char*)glGetString(GL_VERSION);
    printf("OpenGL Application Running, Version: %s\n", version);


    // Enter main loop
    while(!glfwWindowShouldClose(window))
    {
        // Event polling
        glfwPollEvents();

        // OpenGL Rendering

        // Setup OpenGL viewport and clear screen
        float ratio;
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        ratio = width / height;

        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Setup projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0, ratio, 0.1, 10.0);

        // Render
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        // Swap Buffers
        glfwSwapBuffers(window);
    }


    // Free glfw memory allocated for window
    glfwDestroyWindow(window);


    // Exit
    glfwTerminate();
    exit(EXIT_SUCCESS);
}

我意识到这是一个非常冗长的问题,但我认为重要的是解释为什么我认为它的代码很疯狂,而不是像很容易那样说“我不明白”。有人可以解释为什么这些非常聪明的人决定这样做,以及为什么会出现错误。(我在网上找不到任何关于此的内容。)

4

1 回答 1

2

The author is using the automatic numbering property of enums to automatically update the definition for the NumVAOs and NumBuffers values. For example, when new VAO IDs are added to the enum the NumVAOs value will still be correct as long as it is listed last in the enum.

enum VAO_IDs {
    Triangles,
    Polygons,
    Circles,
    NumVAOs
};

Most likely your compiler does not support this trick.

于 2013-07-23T00:57:08.357 回答