Для тех, кто видел мои предыдущие вопросы, после работы с RedBook для Версии 2.1 я перехожу к Версии 4.3. (Сказал вы, потому что многие из вас говорили мне делать это целую вечность.)
Итак, я глубоко в 3 главе, но до сих пор не работает примерная программа 1 главы.
У меня две проблемы. (На самом деле 3.) Во-первых, он не компилируется. Ладно, это проблема, но неважно, учитывая следующие два. Во-вторых, я не совсем понимаю, как это работает или что он пытается сделать, но мы перейдем к этому.
В-третьих, мне кажется, что автором этого кода является полный маг. Я бы предположил, что здесь происходят всякие хитрости. Скорее всего, это связано с проблемой № 2, с тем, что я не понимаю, что он пытается сделать. Ребята, которые написали эту книгу, конечно, не идиоты, но потерпите меня, я приведу пример.
Вот фрагмент кода, взятый из верхней части main.cpp
файл. Я включу остальную часть файла позже, но сейчас:
enum VAO_IDs {
Triangles,
NumVAOs
};
Если я правильно понимаю, это дает VAO_IDs::Triangles
значение 1
, поскольку перечисления основаны на нуле. (Надеюсь, я здесь прав, иначе мне будет стыдно.)
Через некоторое время вы можете увидеть эту строку:
GLuint VAOs[NumVAOs];
Который объявляет массив GLuint
с 1 GLuint из-за того, что NumVAOs равны 1. Теперь, во-первых, не должно быть VAO_IDs::NumVAOs
?
И, во-вторых, почему же так использовался enum? Я бы никогда не использовал подобное перечисление по понятным причинам — не может иметь более одного данных с одинаковым значением, значения не указаны явно и т. Д.
Я лаю здесь правильное дерево? Просто не имеет смысла делать это … ВАО должны были быть глобальными, как это, конечно? 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: %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);
}
Я понимаю очень многословный вопрос, но я подумал, что важно объяснить, почему я считаю его сумасшедшим кодом, а не просто сказать «я не понимаю», как это легко сделать. Может кто-нибудь объяснить, почему эти очень умные люди решили сделать это таким образом и почему есть ошибки. (Я ничего не могу найти об этом онлайн.)
Автор использует свойство автоматической нумерации enums
автоматически обновить определение для NumVAOs
а также NumBuffers
ценности. Например, когда новые идентификаторы VAO добавляются к enum
NumVAOs
значение будет по-прежнему правильным, если оно указано последним в enum
,
enum VAO_IDs {
Triangles,
Polygons,
Circles,
NumVAOs
};
Скорее всего, ваш компилятор не поддерживает этот трюк.
Других решений пока нет …