Why is OpenGL telling me that terminate called after throwing an instance of 'int' after running it? - opengl

So I tried to make an OpenGL project with GLFW and glad in visual studio code, but it would throw and error when I would compile and run the program.
I tried to make 3 triangles in a window, it worked so I tried organizing the VBO, VAO, EBO, shaderProgram, vertexShaderSource, and fragmentShaderSource into individual files, and compiled and ran it, I expected the usual result but would give me a window that is not responding, then it would terminate and give out an error. I'm not sure witch of the files are causing this, but my guess is the main.cpp file:
#include"header/shaderClass.h"
#include"header/VAO.h"
#include"header/VBO.h"
#include"header/EBO.h"
//some vertex and indices arrays here
int main()
{
// Initialize GLFW
glfwInit();
// Tell GLFW what version of OpenGL we are using
// In this case we are using OpenGL 3.3
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
// Tell GLFW we are using the CORE profile
// So that means we only have the modern functions
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create a GLFWwindow object of 800 by 800 pixels, naming it "YoutubeOpenGL"
GLFWwindow* window = glfwCreateWindow(800, 800, "YoutubeOpenGL", NULL, NULL);
// Error check if the window fails to create
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
// Introduce the window into the current context
glfwMakeContextCurrent(window);
//Load GLAD so it configures OpenGL
gladLoadGL();
// Specify the viewport of OpenGL in the Window
// In this case the viewport goes from x = 0, y = 0, to x = 800, y = 800
glViewport(0, 0, 800, 800);
// Generates Shader object using shaders defualt.vert and default.frag
Shader shaderProgram("default.vert", "default.frag");
// Generates Vertex Array Object and binds it
VAO VAO1;
VAO1.Bind();
// Generates Vertex Buffer Object and links it to vertices
VBO VBO1(vertices, sizeof(vertices));
// Generates Element Buffer Object and links it to indices
EBO EBO1(indices, sizeof(indices));
// Links VBO to VAO
VAO1.LinkVBO(VBO1, 0);
// Unbind all to prevent accidentally modifying them
VAO1.Unbind();
VBO1.Unbind();
EBO1.Unbind();
// Main while loop
while (!glfwWindowShouldClose(window))
{
// Specify the color of the background
glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
// Clean the back buffer and assign the new color to it
glClear(GL_COLOR_BUFFER_BIT);
// Tell OpenGL which Shader Program we want to use
shaderProgram.Activate();
// Bind the VAO so OpenGL knows to use it
VAO1.Bind();
// Draw primitives, number of indices, datatype of indices, index of indices
glDrawElements(GL_TRIANGLES, 9, GL_UNSIGNED_INT, 0);
// Swap the back buffer with the front buffer
glfwSwapBuffers(window);
// Take care of all GLFW events
glfwPollEvents();
}
// Delete all the objects we've created
VAO1.Delete();
VBO1.Delete();
EBO1.Delete();
shaderProgram.Delete();
// Delete window before ending the program
glfwDestroyWindow(window);
// Terminate GLFW before ending the program
glfwTerminate();
return 0;
}

Related

OpenGL 3 Rendering Problems Linux (Ubuntu Mate)

I'm unable to get OpenGL (with GLFW) to render content to the screen. I'm not even able set a clear color and have that be displayed when I run my application, I'm just consistently presented with a black screen.
I have installed requisite dependencies on my system and set up the build environment such that I'm able to successfully compile my applications (and dependencies) without error. Here is a snippet of the problematic code... You will note much of the rendering code has actually been commented out. For now it will be sufficient to just have the Clear Color I chose displayed to verify that everything is set up correctly:
// Include standard headers
#include <stdio.h>
#include <stdlib.h>
//Include GLEW. Always include it before gl.h and glfw3.h, since it's a bit magic.
#include <GL/glew.h>
// Include GLFW
#include <GLFW/glfw3.h>
// Include GLM
#include <glm/glm.hpp>
#include <GL/glu.h>
#include<common/shader.h>
#include <iostream>
using namespace glm;
int main()
{
// Initialise GLFW
glewExperimental = true; // Needed for core profile
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
// Open a window and create its OpenGL context
GLFWwindow* window; // (In the accompanying source code, this variable is global for simplicity)
window = glfwCreateWindow( 1024, 768, "Tutorial 02", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window); // Initialize GLEW
//glewExperimental=true; // Needed in core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
//INIT VERTEX ARRAY OBJECT (VAO)...
//create Vertex Array Object (VAO)
GLuint VertexArrayID;
//Generate 1 buffer, put the resulting identifier in our Vertex array identifier.
glGenVertexArrays(1, &VertexArrayID);
//Bind the Vertex Array Object (VAO) associated with the specified identifier.
glBindVertexArray(VertexArrayID);
// Create an array of 3 vectors which represents 3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
//INIT VERTEX BUFFER OBJECT (VBO)...
// This will identify our vertex buffer
GLuint VertexBufferId;
// Generate 1 buffer, put the resulting identifier in VertexBufferId
glGenBuffers(1, &VertexBufferId);
//Bind the Vertex Buffer Object (VBO) associated with the specified identifier.
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
//Compile our Vertex and Fragment shaders into a shader program.
/**
GLuint programId = LoadShaders("../tutorial2-drawing-triangles/SimpleVertexShader.glsl","../tutorial2-drawing-triangles/SimpleFragmentShader.glsl");
if(programId == -1){
printf("An error occured whilst attempting to load one or more shaders. Exiting....");
exit(-1);
}
//glUseProgram(programId); //use our shader program
*/
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
do{
// Clear the screen. It's not mentioned before Tutorial 02, but it can cause flickering, so it's there nonetheless.
glClearColor(8.0f, 0.0f, 0.0f, 0.3f);
//glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// DRAW OUR TRIANGE...
/**
glBindBuffer(GL_ARRAY_BUFFER, VertexBufferId);
glEnableVertexAttribArray(0); // 1st attribute buffer : vertices
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// plot the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0); //clean up attribute array
*/
// Swap buffers
glfwSwapBuffers(window);
//poll for and process events.
glfwPollEvents();
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
}
Again, pretty straight forward as far as OpenGL goes, all rendering logic, loading of shaders,etc has been commented out I'm just trying to set a clear color and have it displayed to be sure my environment is configured correctly. To build the application I'm using QTCreator with a custom CMAKE file. I can post the make file if you think it may help determine the problem.
So I managed to solve the problem. I'll attempt to succinctly outline the source of the problem and how I arrived at a resolution in the hope that it may be useful to others that encounter the same issue:
In a nutshell, the source of the problem was a driver issue, I neglected to mention that I was actually running OpenGL inside an Ubuntu Mate 18.0 VM (via Parallels 16) on a MacBook Pro (with dedicated graphics) Therein, lies the problem; up until very recently both Parallels and Ubuntu simply did not support more modern, OpenGL 3.3 and upwards. I discovered this by adding the following lines to the posted code in order to force a specific OpenGL version:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
On doing this the application immediately begin to crash and glGetError() reported that I needed to downgrade to an earlier version of OpenGL as 3.3 was not compatible with my system.
The solution was two-fold:
Update Parallels to version 17 which now includes a dedicated, third-party virtual GPU (virGL) that is capable of running OpenGL 3.3 code.
Update Ubuntu or at the very least the kernel as virGL only works with linux kernel versions 5.10 and above. (Ubuntu Mate 18 only ships with kernel version 5.04.)
Thats it, making the changes, as described, enabled me to run the code exactly as posted and successfully render a basic triangle to the screen.

Opengl Triangles Benchmark

I am trying to test how may triangles I can draw on my laptop, so I am doing the following on my system:
OS: Windows 10
CPU: Intel Core i5 5200U
GPU: NVIDIA Geforce 820M
Code:
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Open a window and create its OpenGL context
window = glfwCreateWindow( 1024, 768, "Tutorial 02 - Red triangle", NULL, NULL);
if( window == NULL ){
fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
getchar();
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
getchar();
glfwTerminate();
return -1;
}
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
// Dark blue background
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
// Number of triangles
const int v = 200;
static GLfloat g_vertex_buffer_data[v*9] = {
-1.0f, -1.0f, 1.0f,
0.8f, 0.f, 0.0f,
0.5f, 1.0f, 0.0f,
};
// fill buffer of triangles
for (int i = 9; i < v * 9; i += 9)
{
g_vertex_buffer_data[i] = g_vertex_buffer_data[0];
g_vertex_buffer_data[i+1] = g_vertex_buffer_data[1];
g_vertex_buffer_data[i+2] = g_vertex_buffer_data[2];
g_vertex_buffer_data[i+3] = g_vertex_buffer_data[3];
g_vertex_buffer_data[i+4] = g_vertex_buffer_data[4];
g_vertex_buffer_data[i+5] = g_vertex_buffer_data[5];
g_vertex_buffer_data[i+6] = g_vertex_buffer_data[6];
g_vertex_buffer_data[i+7] = g_vertex_buffer_data[7];
g_vertex_buffer_data[i+8] = g_vertex_buffer_data[8];
}
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
int frameNr = 0;
char text[100];
do{
// Clear the screen
glClear( GL_COLOR_BUFFER_BIT );
// Use our shader
glUseProgram(programID);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, v*3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
//glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
frameNr++;
sprintf_s(text, "%d %d %d", frameNr, clock() / 1000, (frameNr * 1000) / (clock() + 1));
glfwSetWindowTitle(window, text);
} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
glfwWindowShouldClose(window) == 0 );
// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteVertexArrays(1, &VertexArrayID);
glDeleteProgram(programID);
// Close OpenGL window and terminate GLFW
glfwTerminate();
return 0;
What wonders me there is that I only get about 80 fps with v = 200 Triangles.
This would be about 16000 Triangles per second what is pretty bad isnt it?
What am I doing wrong here in the code, or can my graphics card really just handle such a low amount of triangles?
How many triangles can a modern gpu like a 1080ti handle (I heard in theory 11 billion ones -although I know in reality it's much lower).
Since I don't yet have enough reputation to comment, let me ask here: How large are your triangles? It's hard to tell without having seen the vertex shader, but assuming those coordinates in your code are directly mapped to normalized device coordinates, your triangle covers a significant part of the screen. If I'm not mistaken, you basically draw the same triangle over and over on top of itself. Thus, you will most likely be fillrate limited. To get more meaningful results, you might rather want to just draw a grid of non-overlapping triangles or at least a random triangle soup instead. To further minimize fillrate and framebuffer bandwidth requirements, you might wanna make sure that depth buffering and blending are turned off.
If you're interested in raw triangles per second, why do you enable MSAA? Doing so just artificially amplifies rasterizer load. As others have noted too, V-Sync is likely switched off as 80 Hz would be a rather weird refresh rate, but better make sure and explicitly switch it off via glfwSwapInterval(0). Rather than estimating total frame time like you do, you might want to consider measuring the actual drawing time on the GPU using a GL_TIME_ELAPSED query.

OpenGL glClearColor always make a black screen

I'm trying to run my first opengl program in C++, which opens a window, sets a background color, and gives a title, from Terminal on Mac OS X.
The code compiles and links fine. When I run the program the window and title open fine but the background color is always black.
It is my understanding that the function glClearColor sets the background color. However, no matter what parameters I pass to the function, the background color of the window is always black.
If anyone can explain to me what errors I'm making, I would very much appreciate it. Thanks and below is the code:
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
const GLint WIDTH = 800, HEIGHT = 600;
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Learn OpenGL", nullptr, nullptr);
int screenWidth, screenHeight;
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
if(nullptr == window)
{
std::cout << "Failed to create GLFW window" << '\n';
glfwTerminate();
return -1;
}
glewExperimental = GL_TRUE;
GLenum err=glewInit();
if(err != glewInit())
{
std::cout << "Failed to initialize GLEW" << '\n';
return -1;
}
glViewport(0, 0, screenWidth, screenHeight);
while(!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.2f, 0.2f, 0.9f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
glClearColor, like all OpenGL functions, works on the current OpenGL context.
You're not setting your window's context as current for your calling thread, so your call to glClearColor does nothing here. Add:
glfwMakeContextCurrent(window);
before your loop.
From glfwMakeContextCurrent docs:
This function makes the OpenGL or OpenGL ES context of the specified window current on the calling thread. A context can only be made current on a single thread at a time and each thread can have only a single current context at a time.
For those of you crazy enough to use pure WIN32 programming:
If your PIXELFORMATDESCRIPTOR has the flag:
PFD_DOUBLEBUFFER
Then all draw calls target the back buffer.
You need to use the windows GDI32 call "SwapBuffers( HDC )" to show the results of your OpenGL calls.
wlgMakeCurrent()
glClearColor( R, G, B, 1.0 ); //: <--Make sure alpha isn't transparent.
glClear( GL_COLOR_BUFFER_BIT )
SwapBuffers( your_window_HDC ); //: from GDI32.dll
To get access to SwapBuffers I use LoadLibrary and GetProcAddress and
put the function pointer in my Win32 functions library.
Also notworthy:
Call SwapBuffers on the same thread as your OpenGL calls.
One more thing. I used multiple threads. So this might be helpful to know:
My window was created in thread "B"
My Context was created in thread "A" using HDC from thread "B"
My openGL draw calls are in thread "A".
I mention this because before I found out about SwapBuffers I thought the problem was because of my multi threading. OpenGL wasn't giving me any errors though, so I had to guess around and experiment and read.

OpenGL glfw black window

I have a small problem with glfw.
My code is really simple, I juste want to create an empty window.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
int main(void) {
// initialise the windows
GLFWwindow *window;
if (!glfwInit()) {
return -1;
}
// create a windows
window = glfwCreateWindow(640, 480, "Test", NULL, NULL);
if (!window) {
fprintf(stderr, "Failed to initialize GLFW\n");
glfwTerminate();
return -1;
}
// make the window's current context
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// loop until the window close
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// swap back and front buffers
glfwSwapBuffers(window);
// poll the events
glfwPollEvents();
}
std::cout << "finished ";
glfwTerminate();
return 0;
}
This code compile but when I run it, I only have a white window. The title of the window is correct but everything inside is white...
I try to use glClearColor like that
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1, 1, 0, 0);
but my window still white....
I use visual studio 2015.
How to get a black window ?
Edit :
I forgot to add this:
glfwMakeContextCurrent(window);
For future visitors I'm posting the edit as a formal answer.
The thing missing here is to set the newly created window as the current OpenGL context by calling glfwMakeContextCurrent(window);
Interestingly the comments in the code say you are doing this
// make the window's current context
But then you do not call the method above but instead set the background colour immediately after. If you add the above method call after this comment and before you set the background colour then when I run your code it works fine.

incorporating "tinyobjloader" in my OpenGL project

So that i can load OBJ files and have them rendered in my openGL window. So far i've managed to:
create an OpenGL context and window using glfw3
created an executable (of test.cc, and its associated libraries and headers) which just outputs OBJ vertices as text in the terminal
I would like to visually render these vertices in my openGL window, so i guess this involves combining the two, but how is the question? I assuming my openGL context assimilates the obj importer, not the other way round, but where in the code would it go:
#include <GLFW/glfw3.h>
#include <GLUT/glut.h>
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
/* clearing */
glClear(GL_COLOR_BUFFER_BIT);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
or do I have to link to it externally?
between glfwMakeContextCurrent and the while loop you should read the obj and put the values into VBOs.
It would be of the form
std::string err = tinyobj::LoadObj(shapes, materials, objStream, matSSReader);
if (!err.empty()) {
glfwTerminate();
return 1;
}
then for each mesh in each shape create a VAO and VBO put in the data, setup the vertexAttributePointers and keep how many vertices are in the mesh.
Then during rendering you bind the VAO and bind the correct material and draw.