When to delete buffer object? - c++

I understand from this question that shader objects can be detached and deleted as soon as the program is linked.
Do buffer objects behave similarly with respect to the VAO? Can I delete them after the VAO been initialized (at the end of Scene::Scene() below) or should I leave my code as is, binding them every time I want to use them?
Scene.h:
class Scene
{
public:
void render();
Scene();
~Scene();
private:
GLuint vertexArray;
GLuint vertexBuffer;
GLuint indexBuffer;
GLuint program;
};
Scene.cpp:
#include <GL/glew.h>
#include <stdio.h>
#include "Scene.h"
namespace
{
void printProgramInfoLog(GLuint program);
void printShaderInfoLog(GLuint shader);
}
void Scene::render()
{
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glUseProgram(program);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glUseProgram(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
Scene::Scene()
{
const float vertices[] =
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
};
const unsigned short indices[] =
{
0,
1,
2,
0,
2,
3,
};
const char* vertexShaderSource[] =
{
"#version 330\n",
"\n",
"in vec3 position;\n",
"\n",
"out vec2 fspos;",
"\n",
"void main()\n",
"{\n",
" gl_Position = vec4(position, 1.0);\n",
"fspos = vec2(position.x, position.y);\n",
"}\n",
};
const char* fragmentShaderSource[] =
{
"#version 330\n",
"\n",
"precision highp float;\n",
"\n",
"in vec2 fspos;",
"\n",
"out vec4 color;\n",
"\n",
"void main()\n",
"{\n",
" color = vec4(abs(fspos.x), abs(fspos.y), 0.0, 1.0);\n",
"}\n",
};
//-------------------------------
// Create and bind vertex array.
//-------------------------------
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
//--------------------------------------
// Create, bind and fill vertex buffer.
//--------------------------------------
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//-------------------------------------
// Create, bind and fill index buffer.
//-------------------------------------
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//-----------------
// Create program.
//-----------------
program = glCreateProgram();
//----------------------------------
// Create and attach vertex shader.
//----------------------------------
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, sizeof(vertexShaderSource) / sizeof(vertexShaderSource[0]), vertexShaderSource, 0);
glCompileShader(vertexShader);
printShaderInfoLog(vertexShader);
glAttachShader(program, vertexShader);
//------------------------------------
// Create and attach fragment shader.
//------------------------------------
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, sizeof(fragmentShaderSource) / sizeof(fragmentShaderSource[0]), fragmentShaderSource, 0);
glCompileShader(fragmentShader);
printShaderInfoLog(fragmentShader);
glAttachShader(program, fragmentShader);
//---------------
// Link program.
//---------------
glLinkProgram(program);
printProgramInfoLog(program);
//-----------------------
// Set up shader inputs.
//-----------------------
GLint position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 0, 0);
//------------------------------------
// Detach and delete fragment shader.
//------------------------------------
glDetachShader(program, fragmentShader);
glDeleteShader(fragmentShader);
//----------------------------------
// Detach and delete vertex shader.
//----------------------------------
glDetachShader(program, vertexShader);
glDeleteShader(vertexShader);
//----------------------
// Unbind vertex array.
//----------------------
glBindVertexArray(0);
//!!!!!!!!!!!!!!!!!!!
// Unbinding and deleting the buffers here and only binding the VAO in
// render() works just fine, but is it okay to do this or should I leave
// it as is?
//!!!!!!!!!!!!!!!!!!!
}
Scene::~Scene()
{
glDeleteProgram(program);
glDeleteBuffers(1, &indexBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
}
namespace
{
void printProgramInfoLog(GLuint program)
{
int logLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetProgramInfoLog(program, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
void printShaderInfoLog(GLuint shader)
{
int logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
char* log = new char[logLength];
glGetShaderInfoLog(shader, logLength, 0, log);
fprintf(stderr, "%s", log);
delete[] log;
}
}
}

VAOs do not store the data. They store the buffer object bindings and vertex formats. The buffer objects are still the holders of the data storage.
So no, don't do that.

Related

opengl and GLFW3 simple triangle draw , cant see triangle

i try to paint simple triangle but i somehow can see the triangle
Here is my files
the window do created but no triangals in it dont know why
#include <iostream>
#include "GLFWManager.h"
#include <stdio.h>
#include <stdlib.h>
int main()
{
std::cout << "Hello World!\n";
GLFWManager gLFWManager;
gLFWManager.Init();
GLuint vbo;
GLuint vao;
GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
// second triangle
0.0f, -0.5f, 0.0f, // left
0.9f, -0.5f, 0.0f, // right
0.45f, 0.5f, 0.0f // top
};
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
// glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
// glBindVertexArray(0);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
int shaderProgram = gLFWManager.createShader();
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
while (!glfwWindowShouldClose(gLFWManager.window))
{
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(vao); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0,6); // set the count to 3 since we're drawing 3 vertices
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(gLFWManager.window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
}
and this one :
#include "GLFWManager.h"
#include "stdio.h"
#include "stdlib.h"
int GLFWManager::windowHight = 300;
int GLFWManager::windowWidth = 300;
void GLFWManager::errorCallback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
void GLFWManager::windowSizeCallbackcallback(GLFWwindow* window, int width, int height)
{
if (width > 0 && height > 0) {
windowHight = height;
windowWidth = width;
}
}
static void KeyCallback(GLFWwindow* window, int key, int, int action, int mods)
{
switch (key)
{
case GLFW_KEY_ESCAPE:
{
if (action == GLFW_RELEASE)
{
glfwSetWindowShouldClose(window, GLFW_PRESS);
}
}
}
}
GLFWManager::GLFWManager()
{
window = nullptr;
}
GLFWManager::~GLFWManager()
{
}
void GLFWManager::Init()
{
glfwSetErrorCallback(GLFWManager::errorCallback);
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
setWindowsHints();
createWindow();
glfwSetKeyCallback(window, KeyCallback);
glfwSetWindowSizeCallback(window, GLFWManager::windowSizeCallbackcallback);
const GLFWvidmode *vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (vidmode->width - windowWidth) /2 , (vidmode->height - windowHight) /2);
glfwGetFramebufferSize(window, &windowWidth, &windowHight);
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
loadGlad();
}
void GLFWManager::setWindowsHints()
{
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
}
void GLFWManager::createWindow()
{
window = glfwCreateWindow(windowWidth,windowHight, "Test", NULL, NULL);
if (!window)
{
exit(EXIT_FAILURE);
}
}
void GLFWManager::loadGlad()
{
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
fprintf(stderr, "Failed to initialize GLAD");
exit(EXIT_FAILURE);
}
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("Renderer: %s\n", renderer);
printf("OpenGL version supported %s\n", version);
}
int GLFWManager::createShader()
{
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
// build and compile our shader program
// ------------------------------------
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n %s\n ",infoLog);
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n %s \n",infoLog);
}
// link shaders
int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n %s \n",infoLog);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return shaderProgram;
}
glVertexAttribPointer and glEnableVertexAttribArray specify and enable an array of vertex attribute data and sets states in the state vector of the currently bound Vertex Array Object.
You have to bind the vertex array object (glBindVertexArray) before you can specify the vertex arrays:
// Create vertex buffer object
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Create Vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// specify array of generic vertex array data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
Note, before you call glVertexAttribPointer, the Vertex Array Object and the Vertex Buffer Object have to be bound, because glVertexAttribPointer associates the buffer which is currently bound to the ARRAY_BUFFER target, to the attribute with the specified index, in the state vector of the currently bound VAO.

OPENGL_INVALID_OPERATION when calling glDrawElements

#include <iostream>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#include <SDL2/SDL.h>
SDL_Window * window = NULL;
SDL_GLContext context = NULL;
const GLfloat vertices[3][4] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
const GLuint indices[3][2]= { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
const GLchar* vertexShaderSource = {"#version 330 core\n"
"layout (location = 0) in vec3 position;"
"void main(void)\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\n\0"};
//fragment
const GLchar* fragmentShaderSource = {"#version 330 core\n"
"out vec4 color;\n"
"void main(void)\n"
"{\n"
"color = vec4(1.0, 0.5, 0.2, 1.0);\n"
"}\n\0"};
bool init ();
bool init(){
if (SDL_Init(SDL_INIT_VIDEO)<0){
std::cout << "Can't make SDL" << std::endl;
}
//what version we are using
SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
window = SDL_CreateWindow("Rectangle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_OPENGL);
if (!window){
std::cout << "No window created" << std::endl;
window = NULL;
return false;
}
context = SDL_GL_CreateContext(window);
//double buffering - 24bit z buffer (might need changing for different systems)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Makes buffer swap sync with VBLANK
SDL_GL_SetSwapInterval(1);
glViewport(0, 0, 512, 512);
return true;
};
int main(int argc, const char * argv[]) {
if (!init()) std::cout << "Failed to start up!" << std::endl;
//compiling the shaders
GLuint shaderProgram, fragmentShader, vertexShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//error checking
GLchar info [512];
GLint success;
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if(!success){
glGetShaderInfoLog(fragmentShader, 512, NULL, info);
std::cout << "Did not compile fragment shader\n"<< info;
}
std::cout<< "vertex shader made" << std::endl;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//error checking
GLchar infoLog [512];
GLint success2;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success2);
if(!success){
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "Did not compile vertex shader\n" << info;
}
std::cout << "fragment shader made" << std::endl;
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
//error checking
GLchar info3 [512];
GLint success3;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success3);
if(!success){
glGetProgramInfoLog(shaderProgram, 512, NULL, info3);
std::cout << "Did not link shaders\n" << info;
}
std::cout << "shaders linked" << std::endl;
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//sets all the VAOs, VBOs, etcs
GLuint VAO;
glGenVertexArrays(1, &VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
bool loop = true;
while (loop) {
SDL_Event e;
while(SDL_PollEvent(&e)){
if (e.type == SDL_QUIT) loop = false;
if (e.type == SDL_KEYDOWN){
switch(e.key.keysym.sym){
case SDLK_ESCAPE:
loop = false;
break;
case SDLK_q:
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
SDL_GL_SwapWindow(window);
break;
case SDLK_y:
std::cout << glGetString(GL_VERSION) << std::endl;
}
std::cout << glGetError() << std::endl;
}
}
}
}
//generates error 1282 for some reason
I used glGetError to see what the error was and it returned 1282, or GL_INVALID_OPERATION. Whenever I try to draw, it causes a glitchy image (will upload pic later).
The problem is definitely not the shaders, because they compile just fine.
I think it's probably how I set up the VBOs and VAO:
//sets all the VAOs, VBOs, etcs
GLuint VAO;
glGenVertexArrays(1, &VAO);
GLuint VBO;
glGenBuffers(1, &VBO);
GLuint EBO;
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GL_FLOAT), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
I copied all of those straight from this tutorial https://learnopengl.com/#!Getting-started/Hello-Triangle
and the source code for the tutorial can be found here https://learnopengl.com/code_viewer.php?code=getting-started/hellotriangle2
I compared my code to the tutorial's several times, checking if I had all the right calls and parameters, but I couldn't find anything wrong. I'm pretty sure I set it all up correctly. Does anyone more experienced than me see what I've done wrong?
Edit: Ok, so I got the line 440 as where the error is thrown. I don't know if I'm reading it wrong, but my code doesn't have 440 lines in it. Does it mean line 4, character 40? I also moved SetSwapInterval() and SDL_GL_Doublebuffer functions to after the context was made.
Edit 2: Ok, so after some more digging, the line the error was thrown at was 439, (I had a load of commented out stuff which is why the number is so big), right after glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0). The complaint is INVALID_OPERATION. It also said INVALID_VALUE at line 405 - the line afterglGenBuffers(1, &EBO); when I started up the program, but didn't say it again.
Edit 3: After some more checking, it's definitely glDrawElements() that's causing this, not anything else.

OpenGL 3+ BlackScreen - C++

I get a black screen after trying to get a simple triangle on OpenGL with the SDL2...
I actually initialize the window with OpenGL and start GLEW with an object name as "EngineOpenGL" : http://pastebin.com/S4YDgY45
Then I start a scene which supposed to rendering the triangle :
"SceneOpenGL" : http://pastebin.com/GD4f5UDj
The main file :
#include <SDL.h>
#include <iostream>
#include <GL\glew.h>
#include "EngineOpenGl.h"
// DEBUG_MemoryLeaks
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
// _DEBUG
#include "SDLInitVideoException.h"
int main(int argc, char **argv) {
_CrtDumpMemoryLeaks();
EngineOpenGL * scene = new EngineOpenGL("OpenGL", 720, 1280);
try {
scene->init();
} catch (const SDLInitVideoException &e) {
delete scene;
std::cout << "Error while initialising SDL" << std::endl;
} catch (const SDLCreateWindowException &e) {
delete scene;
std::cout << "Error while initialising the window" << std::endl;
} catch (const SDLCreateContextGLException &e) {
delete scene;
std::cout << "Error while creating the contextGL" << std::endl;
} catch (const GLEWInitException &e) {
delete scene;
std::cout << "Error while initialising " << std::endl;
} catch (const SceneOpenGLException &e) {
delete scene;
std::cout << "Error while starting the scene" << std::endl;
}
scene->start();
delete scene;
// DEBUG_MemoryLeaks
_CrtDumpMemoryLeaks();
// _DEBUG
return 0;
}
FPS show the fps in the console and Input gets the user input.
Edit : I actually just tried to copy/past a code for rendering triangle and it keep doesn't work...
#include "SceneOpenGl.h"
// Shader temporaire :
#include "Shader.h"
SceneOpenGL::SceneOpenGL(SDL_Window* window) {
if (window == NULL) {
throw new SceneOpenGLException();
}
// Engine
this->window = window;
// Tools
this->fps = new FPSCount();
this->input = new Input();
// Scene
this->run = false;
int w, h;
SDL_GetWindowSize(window, &w, &h);
this->projection = glm::perspective(70.0, (double)(w/h), 1.0, 100.0);
this->modelview = glm::mat4(1.0);
}
SceneOpenGL::~SceneOpenGL(){
delete fps;
delete input;
}
void SceneOpenGL::start() {
run = true;
// Test en attendant ObjectGL.show() //
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, -0.5f, 0.0f, // Bottom Left
-0.5f, 0.5f, 0.0f // Top Left
};
GLuint indices[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
// Build and compile our shader program
// Vertex shader
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for compile time errors
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Link shaders
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLuint VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO
// /Test //
while (run) {
// FPS flag
if (fps->flag()) {
std::cout << "FPS : " << fps->getFps() << std::endl;
}
// Input check/actions
input->updateEvents();
if (input->isKeyPush(SDL_SCANCODE_ESCAPE)) {
run = false;
}
// Cleaning last frame
glClear(GL_COLOR_BUFFER_BIT);
// Test //
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
// FPS add frame
fps->addFrame();
// Rendering
SDL_GL_SwapWindow(window);
}
}
At no point are you loading your vertex data into video memory. You have a line which looks like an attempt to load the vertices into video memory:
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
.... But that's not what that function does.
You need to create and bind a Vertex Array and a Vertex Buffer:
GLuint vertex_array_id;
glGenVertexArrays(1, &vertex_array_id);
glBindVertexArray(vertex_array_id);
GLuint vertex_buffer_id;
glGenBuffers(1, &vertex_buffer_id);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
Then, while this Vertex Array and Vertex Buffer is bound, you need to explicitly provide data to the buffer:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
Then you use glVertexAttribPointer to specify how the data is laid out.
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, nullptr);
glEnableVertexAttribArray(0);
All of that code, by the way, should probably be outside the loop. Then inside the draw loop, you simply have to call glDrawArrays.

Shape not being drawn in OpenGL when unbinding vertex array

I'm learning OpenGL and I set up a Mesh class to render my shapes. Drawing only works without
glBindVertexArray(0);
at the end so I'm guessing I messed up something but I can't figure it out.
Here is the code: main.cpp
#include <GL/glew.h>
#include <SDL2/SDL.h>
#include <iostream>
#include "mesh.h"
#define WIDTH 1280
#define HEIGHT 720
// Vertex shader
const char* vs = "\n\
#version 330 \n\
layout (location = 0) in vec2 position; \n\
layout (location = 1) in vec3 color; \n\
out vec3 Color; \n\
\n\
void main() { \n\
Color = color; \n\
gl_Position = vec4(position, 0.0, 1.0); \n\
} \n\
\n\
";
// Fragment shader
const char* fs = "\n\
#version 330 \n\
in vec3 Color; \n\
out vec4 fragColor; \n\
\n\
void main() { \n\
fragColor = vec4(Color, 1.0); \n\
} \n\
";
bool checkShader(GLuint shader) {
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
char buffer[512];
glGetShaderInfoLog(shader, 512, NULL, buffer);
std::cout << "Error compiling shader:" << buffer << std::endl;
return false;
}
return true;
}
bool compileShaders() {
// compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vs, NULL);
glCompileShader(vertexShader);
if (!checkShader(vertexShader))
return false;
// compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fs, NULL);
glCompileShader(fragmentShader);
if (!checkShader(fragmentShader))
return false;
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
return true;
}
int main() {
bool success = true;
bool running = true;
SDL_Window* window;
SDL_GLContext context;
// Initialize SDL/Glew
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "Video initialization failed:" << SDL_GetError() << std::endl;
success = false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
window = SDL_CreateWindow("Game Title", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN |
SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
context = SDL_GL_CreateContext(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cerr << "Problem initializing GLEW." << std::endl;
success = false;
}
SDL_Event e;
// Mesh setup
float vertices[] = { 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f,-0.5f, 0.0f, 1.0f, 0.0f,
-0.5f,-0.5f, 0.0f, 0.0f, 1.0f };
float vertices2[] = { -1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
GLuint elements[] = { 0, 1, 2 };
Mesh triangle(vertices, elements, sizeof(vertices), sizeof(elements));
Mesh triangle2(vertices2, elements, sizeof(vertices2), sizeof(elements));
if (!compileShaders())
success = false;
if (!success) {
std::cerr << "A problem ocurred during initialization, will exit." << std::endl;
exit(1);
}
while (running) {
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT)
running = false;
if (e.type == SDL_KEYDOWN)
if (e.key.keysym.sym == SDLK_ESCAPE)
running = false;
}
glClearColor(0.0f, 1.0f, 0.5f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
triangle.draw();
triangle2.draw();
SDL_GL_SwapWindow(window);
SDL_Delay(1);
}
SDL_GL_DeleteContext(context);
SDL_Quit();
return 0;
}
mesh.h
#ifndef MESH_H
#define MESH_H
#include <GL/glew.h>
class Mesh {
private:
GLuint IBO;
GLuint VBO;
GLuint VAO;
float* vertices;
GLuint* indices;
int sizeVertices;
int sizeIndices;
public:
Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices);
void draw();
};
#endif //MESH_H
mesh.cpp
#include "mesh.h"
#define POSITION 0
#define COLOR 1
Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
this->vertices = vertices;
this->indices = indices;
this->sizeVertices = sizeVertices;
this->sizeIndices = sizeIndices;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &IBO);
}
void Mesh::draw() {
glEnableVertexAttribArray(POSITION);
glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);
glEnableVertexAttribArray(COLOR);
glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeVertices, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
//glBindVertexArray(0); If I uncomment this, the mesh is not displayed
}
The calls to glVertexAttribPointer pointer refer to the VAO and VBO bound at the time of calling. In your code you're calling glVertexAttribPointer before the VAO and the VBO are bound. So the first iteration round those calls will fail. Without unbinding the VAO/VBO the next iteration the VAO/VBO state will happen (by circumstance) to the more or less right; actually you've swapped the VAO/VBO between the two triangle instances.
Update – fixed code
Mesh::Mesh(float* vertices, GLuint* indices, int sizeVertices, int sizeIndices) {
this->vertices = vertices;
this->indices = indices;
this->sizeVertices = sizeVertices;
this->sizeIndices = sizeIndices;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &IBO);
/* VAOs contain ARRAY_BUFFERS */
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeVertices, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(POSITION);
glVertexAttribPointer(POSITION, 2, GL_FLOAT, GL_FALSE,5*sizeof(float), 0);
glEnableVertexAttribArray(COLOR);
glVertexAttribPointer(COLOR, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)(2*sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(VAO);
/* ELEMENT_ARRAY_BUFFERS are not contained in VAOs */
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeIndices, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void Mesh::draw() {
/* VAOs keep the glVertexAttribPointer bindings,
* so it's sufficient to just bind the VAO;
* no need for binding the VBOs (as long as you don't
want to change the pointers). */
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
/* Need to bind the ELEMENT_ARRAY_BUFFER though */
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

glMapBufferRange gives me an access violation

I just got a laptop with an Intel HD4000 "graphics card" and my code that works on my stationary computer with an HD6950 gives me an access violation. I changed from version 4.4 to 4.0 since the HD4000 only supports up to 4.0.
Looking at the OpenGL wiki for it says it can only guarantee alignment from version 4.2 and up, so I'm thinking that may be the issue but I'm not sure and I don't know how to deal with it
I took this code from open.gl and modified it to use GLFW to test with:
// Link statically with GLEW
#define GLEW_STATIC
// Headers
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <windows.h>
// Shader sources
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"in vec3 color;"
"out vec3 Color;"
"void main() {"
" Color = color;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"in vec3 Color;"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(Color, 1.0);"
"}";
int main()
{
if(!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = nullptr;
window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = GL_TRUE;
int glewRes = glewInit();
if(glewRes != GLEW_OK)
{
glfwTerminate();
OutputDebugStringA(reinterpret_cast<const char*>(glewGetErrorString(glewRes)));
OutputDebugStringA("\n");
return -2;
}
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), NULL, GL_DYNAMIC_DRAW);
GLfloat* mappedData = static_cast<GLfloat*>(glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(vertices), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT));
GLenum error = glGetError();
error = glGetError();
error = glGetError();
if(mappedData == NULL)
{
glfwTerminate();
return -3;
}
for(int i = 0; i < ARRAYSIZE(vertices); i++)
{
mappedData[i] = vertices[i];
}
glUnmapBuffer(GL_ARRAY_BUFFER);
// Create an element array
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw a rectangle from the 2 triangles using 6 indices
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// Swap buffers
glfwSwapBuffers(window);
}
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glfwTerminate();
}
For some reason whenever I use glMapBufferRange it gives me an access violation at mappedData[i] = vertices[i];.
If I simply use glBufferData or glMapBuffer it works fine
Windows just installed 38 updates and now it works