#c #opengl #glfw #glew
#c #opengl #glfw #glew
Вопрос:
Я пытаюсь написать свой первый игровой движок на C (хотя я уже сделал это на Java), я создал базовый класс mesh, который содержит целое число GLuint для массивов vao / Vertex и массив (на данный момент размером всего 2) для буферов / vbo, когда я пытаюсь вызвать свой конструктор в классе mesh, и я вызываю функцию glGenVertexArrays(1, amp; vaoId). ; Программа выходит из строя, в Visual Studio появляется окно с надписью
доступ нарушен во время выполнения пути на 0x00000000
Mesh.cpp:
#include "Mesh.h"
Mesh::Mesh(GLuint vaoid, int verticeslength) : vaoId(vaoid),
verticesLength(verticeslength) {}
Mesh::Mesh(float vertices[]) {
this->verticesLength = sizeof(vertices) / sizeof(float); // set the length of the vertices
glGenVertexArrays(1, amp;vaoId); // create VAO
glBindVertexArray(vaoId); // bind VAO
glGenBuffers(1, amp;vboIds[0]); // allocate memory to VBO
glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); // bind vbo
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) / sizeof(float),
vertices, GL_STATIC_DRAW); // store data in vbo
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // store vbo in vao
}
Mesh::~Mesh() {
glDisableVertexAttribArray(0); // disable the position vbo
glDeleteBuffers(2, vboIds); // delete the vbos
glDeleteVertexArrays(1, amp;vaoId); // delete the vbos
delete amp;vaoId;
delete amp;vboIds;
}
GLuint Mesh::getVaoId() { return vaoId; }
int Mesh::getVerticesLength() { return verticesLength; }
void Mesh::render() {
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, verticesLength);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
}
Mesh.h:
#ifndef Mesh_H
#define Mesh_H
#include <GL/glew.h>
class Mesh {
private:
int verticesLength;
GLuint vboIds[2]; // 0 = position, 1 = textureCoords
GLuint vaoId;
public:
Mesh(GLuint vaoId, int verticesLength);
Mesh(float vertices[]);
~Mesh();
int getVerticesLength();
GLuint getVaoId();
void render();
};
#endif Mesh
Main.cpp:
#include <iostream>
#include "Mesh.h"
#include <GLFW/glfw3.h>
#include "GlfwUtils.h"
#include "InputManager.h"
#define WIDTH 800
#define HEIGHT 600
bool initializeGLFW();
int main() {
if (!initializeGLFW()) return EXIT_FAILURE;
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Scope Engine",
NULL, NULL);
glfwMakeContextCurrent(window);
if (!window) {
std::cout << "Window creation failed" << std::endl;
return EXIT_FAILURE;
}
glfwSetKeyCallback(window, InputManager::key_callback);
float vertices[] = {
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
0.5f, 0.5f, 0,
-0.5f, 0.5f, 0
};
Mesh* mesh = new Mesh(vertices); // gotta initalize the mesh!
while (!glfwWindowShouldClose(window)) {
mesh->render();
std::cout << "Game Loop!" << std::endl;
GlfwUtils::UpdateDisplay(window);
}
delete mesh;
glfwDestroyWindow(window);
return EXIT_SUCCESS;
}
bool initializeGLFW() {
glewExperimental = GL_TRUE;
if (!glewInit()) {
std::cout << "Couldn't initalize OpenGL" << std::endl;
return false;
}
GLenum error = glGetError();
if (error != GL_NO_ERROR) { std::cout << "OpenGL error: " << error << std::endl; }
if (!glfwInit()) {
std::cout << "Couldn't initalize GLFW" << std::endl;
return false;
}
glfwSetErrorCallback(GlfwUtils::error_callBack);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
return true;
}
это как-то связано с драйвером, компоновщиком или я допустил ошибку в своем коде?
Комментарии:
1. Возможно, это не связано, но…
sizeof(vertices)
в вашемMesh
конструкторе, вероятно, не выполняется то, что вы думаете.2. Большое спасибо Rabbid76, теперь это работает!
Ответ №1:
Библиотека GLEW должна быть инициализирована glewInit
после того, как контекст OpenGL станет текущим glfwMakeContextCurrent
. С помощью.
Смотрите Инициализацию GLEW.
Сначала сделайте контекст OpenGL текущим, а затем инициализируйте GLEW:
glfwMakeContextCurrent(window);
if (!window) {
std::cout << "Window creation failed" << std::endl;
return EXIT_FAILURE;
}
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cout << "Couldn't initalize OpenGL" << std::endl;
return false;
}
Не имеет смысла вызывать какую-либо инструкцию OpenGL до того, как константа OpenGL станет текущей.
Удалить GLenum error = glGetError();
из initializeGLFW
.
В конструкторе не указан размер массива Mesh::Mesh(float vertices[])
, sizeof(vertices)
(это не java). Это размер указателя на массив, который равен 8 в 64-разрядной системе.
Использовать std::vector
:
#include <vector>
std::vector<float> vertices{
-0.5f, 0.5f, 0,
-0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
0.5f, -0.5f, 0,
0.5f, 0.5f, 0,
-0.5f, 0.5f, 0
};
Mesh *mesh = new Mesh(vertices);
class Mesh {
private:
int noOfVertices;
// [...]
public:
Mesh::Mesh(const std::vector<float> amp;vertices);
// [...]
};
Mesh::Mesh(const std::vector<float> amp;vertices) {
// [...]
noOfVertices = (int)vertices.size() / 3;
glBufferData(GL_ARRAY_BUFFER,
vertices.size()*sizeof(float), vertices.data(), GL_STATIC_DRAW);
}
Количество элементов в std::vector
фургоне, которое можно получить с помощью std::vector::size
указателя на содержимое, может быть получено с помощью std::vector::data
.
В вашем случае координата каждой вершины состоит из 3 компонентов (x, y и z), поэтому количество координат равно vertices.size() / 3
.
Вторым параметром для glBufferData
должен быть размер буфера в байтах, который является vertices.size() * sizeof(float)
.
Комментарии:
1. Вы должны проверить возвращаемое значение
glewInit
наGLEW_OK
соответствие (=0). В настоящее время код возвращает false, когда glew удовлетворен, что прямо противоположно тому, что вы хотите.