OpenGL Programming Guild 第八版,示例程序和'NumVAOs'



对于看过我之前问题的人来说,在阅读了2.1版的红皮书之后,我现在将转到4.3版。(你说的是骗人的,因为你们中的许多人多年来一直告诉我要这样做。)

所以,我已经深入研究了第三章,但仍然没有得到第一章的示例程序。

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

第三,在我看来,这个代码的作者是一个完全的魔术师。我认为这里正在发生各种各样的小把戏。这很可能是因为第二个问题,事实上我不明白它想做什么。写这本书的人当然不是白痴,但请耐心等待,我会举一个例子。

以下是main.cpp文件顶部的一段代码。稍后我将包括文件的其余部分,但现在:

enum VAO_IDs {
    Triangles,
    NumVAOs
};

如果我理解正确,这将为VAO_IDs::Triangles提供1的值,因为枚举是基于零的。(我希望我在这里是正确的,否则我会很尴尬。)

过一会儿,你可以看到这行:

GLuint VAOs[NumVAOs];

它声明了一个GLuint的数组,其中包含1个GLuint,因为NumVAOs等于1。首先,它不应该是VAO_IDs::NumVAOs吗?

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

我在这里叫对树了吗?这样做毫无意义。。。VAO应该是全球性的,当然是这样吗?GLuint NumVAOs = 1;这只是滥用枚举!

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

不管怎样,忘记枚举。。。现在。。。好吧,所以我做了一件大事,这就是问题的结束。。。我的任何进一步评论现在都在代码中。你可以忽略大多数glfw的东西,它本质上与供过于求相同。

// ----------------------------------------------------------------------------
//
// 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: %sn", 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);
}

我意识到这是一个非常冗长的问题,但我认为重要的是解释为什么我认为它是疯狂的代码,而不是简单地说"我不明白"。有人能解释一下为什么这些非常聪明的人决定这样做,以及为什么会有错误吗。(我在网上找不到任何关于这个的信息。)

作者使用enums的自动编号属性自动更新NumVAOsNumBuffers值的定义。例如,当新的VAO ID被添加到enum时,只要NumVAOs的值在enum中最后列出,它仍然是正确的。

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

很可能你的编译器不支持这个技巧。

相关内容

  • 没有找到相关文章