openGL crashing when calling glGenBuffers - c++

I'm learning OpenGL via http://learnopengl.com/ however I am crashing when I am trying to bind the buffers in the 'hello triangle' part of the tutorial. I have prior coding experience in C++ but I can't work out what is wrong.
My Code:
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glfw3.h>
#include <GL/gl.h>
using namespace std;
const GLuint WIDTH = 800, HEIGHT = 600;
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
int initializeWindow(GLFWwindow* window);
int main() {
GLFWwindow* window;
cout << "Creating Triangles" << endl;
GLfloat triangles[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f
};
cout << "Initialising GLFW" << endl;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
cout << "Initialising Window..." << endl;
window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", NULL, NULL);
cout << "Setting Callback Functions..." << endl;
glfwSetKeyCallback(window, key_callback);
cout << "Binding Buffers" << endl;
GLuint VBO;
glGenBuffers(1, &VBO); // <--- Crashing here
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangles), triangles, GL_STATIC_DRAW);
if (initializeWindow(window) == -1) {
return -1;
}
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
cout << "Terminating..." << endl;
glfwTerminate();
return 0;
}
int initializeWindow(GLFWwindow* window) {
if (window == NULL) {
cout << "Failed to create GLFW window... exiting" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
cout << "Failed to initialize GLEW... exiting" << endl;
return -1;
}
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
return 0;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
I am getting just a generic 'not responding' crash, no errors in the console. Any help will be greatly appreciated, thanks.

You need to call initializeWindow just after the window creation and before any call to gl functions. This is necessary in order to make current windows active and initialize glew (these operations are done inside initializewindow)

Related

How to render from multithreaded context

In my following code.
class RenderOpengl
{
private:
GLFWwindow* window = NULL;
public:
RenderOpengl() { InitGLFW(); }
void InitGLFW()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(1920, 1080, "Test", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
// return -1;
}
else
std::cout << "Window Created";
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
GLenum GlewInitResult;
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult) // Check if glew is initialized properly
{
std::cout << "Not able to initialize glew";
// return -1;
}
}
void Render()
{
while (!glfwWindowShouldClose(window)) {
std::cout << "I am function number 555" << std::endl;
glfwMakeContextCurrent(window);
std::cout << glGetError() << std::endl;
glfwSwapBuffers(window);
glfwPollEvents();
}
}
};
class ThreadClass
{
public:
explicit ThreadClass(RenderOpengl* _gl) { gl = _gl; };
RenderOpengl* gl;
void RenderGL()
{
gl->Render();
}
};
int main()
{
RenderOpengl renderGL;
std::thread t(&ThreadClass::RenderGL, ThreadClass(&renderGL));
t.join();
// renderGL.Render();
std::cout << "Hello World!\n";
}
The rendering call in the Main function does not give any error.(renderGL.Render())
But if I comment this line and call the same function in a separate thread it gives error 1282 , despite calling the glfwMakeContextCurrent(window).

OpenGL glDrawArrays for GL_POINTS and GL_LINES are on different pixels for same points

Using the normalized [-1,1] points A = (0.5, 0.5), B = (0.5, -0.5), C = (-0.5, -0.5), and D = (-0.5, 0.5), I'm drawing these points as pixels with glDrawArrays(GL_POINTS, 0, 4). I found that when I also call glDrawArrays(GL_LINES, 0, 4) to draw the 2 lines AB and CD there's a 1 pixel difference in the x-direction between the points and the endpoints of the 2 lines. Here's a screenshot of what I'm seeing:
I was also able to get this problem to go away if I changed the window size from 800x600 to 850x600. I'm thinking this might have to do with odd or even size window width, but I'm not sure. In my code, you can comment out #define SHOW_PROBLEM to change the window size where the problem doesn't occur. Any ideas would be greatly appreciated!
Here's my complete code for reference:
#include <bits/stdc++.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
void framebuffer_size_callback(GLFWwindow * window, int width, int height);
void processInput(GLFWwindow * window);
#define SHOW_PROBLEM
#ifdef SHOW_PROBLEM
// These dimensions show the problem
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#else
// These dimensions DO NOT show the problem
#define WINDOW_WIDTH 850
#define WINDOW_HEIGHT 600
#endif
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow * window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "OpenGLDemo", nullptr, nullptr);
if (!window)
{
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Failed to create GLFW window!"
<< std::nounitbuf << std::endl;
glfwTerminate();
std::abort();
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)))
{
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Failed to initialize GLAD!"
<< std::nounitbuf << std::endl;
std::abort();
}
// vertex shader
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";
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Vertex shader compilation failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
// fragment shader
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"
"}\0";
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Fragment shader compilation failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cout << std::unitbuf
<< "[ERROR] " << __FILE__ << ':' << __LINE__ << ' ' << __PRETTY_FUNCTION__
<< "\n[ERROR] " << "Shader program linking failed!"
<< "\n[ERROR] " << infoLog
<< std::nounitbuf << std::endl;
std::abort();
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float 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
};
unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
unsigned int VBO;
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), reinterpret_cast<void *>(0));
glEnableVertexAttribArray(0);
// 6. render loop
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
while (!glfwWindowShouldClose(window))
{
processInput(window);
// background
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glDrawArrays(GL_POINTS, 0, 4);
glDrawArrays(GL_LINES, 0, 4);
// check and call events and swap the buffers
glfwPollEvents();
glfwSwapBuffers(window);
}
// de-allocate all resources once they've outlived their purpose:
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow * window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow * window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
}
This may also be useful:
OpenGL vendor string: Intel
OpenGL renderer string: Mesa Intel(R) UHD Graphics 620 (KBL GT2)
OpenGL core profile version string: 4.6 (Core Profile) Mesa 20.0.8
OpenGL core profile shading language version string: 4.60
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6 (Compatibility Profile) Mesa 20.0.8
OpenGL shading language version string: 4.60
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 Mesa 20.0.8
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:
for GL_LINES the rasterizer would have to interpolate across two vertices, and with any other interpolated values from the vertex to fragment shaders, you should not rely on some kind of equality between hardcoded values and the interpolated. The resizing of windows tells you that the difference is just due to this interpolation/float error. If you goal is to color the vertices, try adding logic in your shader to check whether the current pixel fragment is very close to the 2 vertices it's interpolated from and color accordingly.

OpenGL not rendering anything after following tutorial

I recently started following an OpenGL tutorial series by TheCherno on youtube.
Here is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
struct ShaderProgramSource {
std::string VertexSource;
std::string FragmentSource;
};
static ShaderProgramSource ParseShader(const std::string& filepath) {
std::ifstream stream(filepath);
enum class ShaderType {
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line)) {
if (line.find("#shader") != std::string::npos) {
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
} else {
ss[(int)type] << line << '\n';
}
}
return { ss[0].str(), ss[1].str() };
}
static unsigned int CompileShader(unsigned int type, const std::string& source) {
std::cout << "Compiling " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader..." << std::endl;
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
std::cout << glGetError() << std::endl;
glCompileShader(id);
std::cout << glGetError() << std::endl;
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
std::cout << glGetError() << std::endl;
if (result == GL_FALSE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
std::cout << glGetError() << std::endl;
char* message = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << glGetError() << std::endl;
std::cout << "Failed to compile" << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl;
std::cout << message << std::endl;
glDeleteShader(id);
std::cout << glGetError() << std::endl;
return 0;
}
std::cout << "Successfully compiled " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader!" << std::endl << std::endl;
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader) {
std::cout << "Creating shader..." << std::endl << std::endl;
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
std::cout << glGetError() << std::endl;
std::cout << "Attached vertex shader" << std::endl;
glAttachShader(program, fs);
std::cout << glGetError() << std::endl;
std::cout << "Attached fragment shader" << std::endl;
glLinkProgram(program);
std::cout << glGetError() << std::endl;
glValidateProgram(program);
std::cout << glGetError() << std::endl;
std::cout << "Linked and validated program" << std::endl;
glDeleteShader(vs);
std::cout << glGetError() << std::endl;
std::cout << "Deleted vertex shader" << std::endl;
glDeleteShader(fs);
std::cout << glGetError() << std::endl;
std::cout << "Deleted fragment shader" << std::endl;
std::cout << "Succesfully created shader!" << std::endl << std::endl;
return program;
}
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);
if (glewInit() != GLEW_OK) {
std::cout << "Error!" << std::endl;
}
std::cout << glGetString(GL_VERSION) << std::endl;
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
std::cout << glGetError() << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
std::cout << glGetError() << std::endl;
glBufferData(GL_ARRAY_BUFFER, 6*sizeof(float), positions, GL_STATIC_DRAW);
std::cout << glGetError() << std::endl;
glDisableVertexAttribArray(0);
std::cout << glGetError() << std::endl;
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*2, 0);
std::cout << glGetError() << std::endl;
glBindBuffer(GL_ARRAY_BUFFER, 0);
std::cout << glGetError() << std::endl;
ShaderProgramSource source = ParseShader("res/shaders/Basic.shader");
std::cout << "VERTEX" << std::endl;
std::cout << source.VertexSource << std::endl;
std::cout << "FRAGMENT" << std::endl;
std::cout << source.FragmentSource << std::endl;
//unsigned int shader = CreateShader(vertexShader, fragmentShader);
///glUseProgram(shader);
// render loop
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
//glDeleteProgram(shader);
glfwTerminate();
return 0;
}
Here's the Basic.shader file:
#shader vertex
#version 330 core
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
#shader fragment
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
I have tried using glGetError and it doesn't output any errors.
You need to enable the generic vertex attribute array instead of disabling it (see glEnableVertexAttribArray):
glDisableVertexAttribArray(0);
glEnableVertexAttribArray(0);
Furthermore, the code which compiles, linkes and installs the sahder is commented out:
//unsigned int shader = CreateShader(vertexShader, fragmentShader);
///glUseProgram(shader);
unsigned int shader = CreateShader(source.VertexSource, source.FragmentSource);
glUseProgram(shader);
I believe #Rabbid76's answer is correct. If it still does not work, make sure you are using compatible OpenGL context or create a VAO to hold the state.
Compatible OpenGL context can be set with:
//Before glfwCreateWindow call, after glfwInit
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
The default value is GLFW_OPENGL_ANY_PROFILE and this could mean CORE if COMPAT is not available. This ensures that a default VAObject always exist and is bound. Meaning that your glVertexAttribPointer calls actually have a place to store that information. I did not see these Cherno's tutorials, it's quite possible that VAOs are covered in the future tutorials. In CORE there will not be one and it might not draw anything.
While we are here, it is not a bad idea to set minimal OpenGL version required precisely. If for some reason it is not available on the target machine, the window creation will fail. This is more preferable than getting "random" seg faults when calling unsupported functions.
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
My preferred way would be to create an actual VAO and go with GLFW_OPENGL_CORE_PROFILE. But feel free to go with tutorials, the ones I've seen from him are really high-quality.
//Put these before the vertex buffer initialization
int VAO;
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);

glTexImage3D throws error 1282 (invalid operation)

I am trying to upload volumetric data as a 3D texture via OpenGL. However, when specifying the formats and data itself through glTexImage3D, an GL_INVALID_OPERATION error is thrown.
The code (including the debugging code I added to find out where the error was comming from) is the following:
void Texture3D::upload()
{
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenTextures(1, &_textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glBindTexture(GL_TEXTURE_3D, _textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexStorage3D(GL_TEXTURE_3D, 6, GL_R8, _width, _height, _depth);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, _width, _height, _depth, 0, GL_RED, GL_UNSIGNED_BYTE, _data);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenerateMipmap(GL_TEXTURE_3D);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
}
I thought it might be an GL_INVALID_VALUE for any of the format, internal format, or pixel format I am specifying in the glTexImage3D, however I have checked with the documentation of glTexImage3D and everything seems correct.
I have created a minimal, verifiable example (using GLFW and GLEW)
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLFWwindow * _window = nullptr;
unsigned int _textureId = GL_INVALID_VALUE;
void initGLFWContext()
{
if (!glfwInit())
{
std::cerr << "GLFW: Couldnt initialize" << std::endl;
exit(-1);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
_window = glfwCreateWindow(1024, 1024, "Test Window", NULL, NULL);
if (!_window)
{
std::cerr << "GLFW Error: Couldnt create window" << std::endl;
glfwTerminate();
exit(-1);
}
//glfwSetKeyCallback(_window, kbCb);
//glfwSetCursorPosCallback(_window, mmCb);
//glfwSetMouseButtonCallback(_window, mCb);
//glfwSetFramebufferSizeCallback(_window, resizeCb);
glfwMakeContextCurrent(_window);
glfwSetWindowPos(_window, 0, 0);
glfwSwapInterval(1);
// Initializes glew
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
std::cerr << "GLEW Error: " << glewGetErrorString(err) << std::endl;
exit(-1);
}
}
void initOpenGL()
{
glEnable(GL_DEPTH_TEST);
//glEnable(GL_BLEND);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glFrontFace(GL_CCW);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_CULL_FACE);
}
void minimalVerifiableExample()
{
initGLFWContext();
initOpenGL();
const unsigned int volSide = 256;
const unsigned int volumeSize = volSide * volSide * volSide;
unsigned char * volumeData = new unsigned char[volumeSize]();
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenTextures(1, &_textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glBindTexture(GL_TEXTURE_3D, _textureId);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexStorage3D(GL_TEXTURE_3D,
6,
GL_R8,
volSide,
volSide,
volSide);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glTexImage3D(GL_TEXTURE_3D,
0,
GL_R8,
volSide,
volSide,
volSide,
0,
GL_RED,
GL_UNSIGNED_BYTE,
volumeData);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
glGenerateMipmap(GL_TEXTURE_3D);
std::cout << "TEX GL ERROR: " << glGetError() << std::endl;
while(!glfwWindowShouldClose(_window))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwPollEvents();
glfwSwapBuffers(_window);
}
glfwDestroyWindow(_window);
glfwTerminate();
delete[] volumeData;
}
int main(int argc, char ** argv)
{
(void) argc;
(void) argv;
minimalVerifiableExample();
return 0;
}
And this is the output I get:
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 0
TEX GL ERROR: 1282
TEX GL ERROR: 0
Am I doing something wrong when uploading the texture or anywhere else?
1282 is a GL_INVALID_OPERATION and is caused by the combination of
glTexStorage3D
glTexImage3D
It is not allowed to recreate the storage for an immutable storage texture object. After calling glTexStorage3D, the texture uses immutable storage. glTexImage3D requests a new storage which is not allowed anymore.
If you try to upload data to the immutable storage texture object, you'll have to use glTexSubImage3D instead which will upload data but not request new storage.

GLSL uniform mat4 is always 0

I am trying to load a orthographic projection matrix into a shader, but when I go to run the code and I click around in the window I end up with all the points going to (0,0,0) which I'm guessing is being caused by the uniform matrix never being setup and as a result everything is being multiplied by 0. I am using Qt, OpenGL and GLM for this. Any ideas why this would be happening?
I have been debugging it a little and it seems to be having issues at the point where I'm loading the matrix into the shader in resizeGL and initializeGL, not sure of the cause though.
Thanks in advance!
My Class handling all of the OpenGL Stuff:
GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent), outline(false), drawMode(0) {
num_pts = 0;
drawMode = GL_POINTS;
next = 1;
ortho = glm::ortho(0.0f, 640.0f, 480.0f, 0.0f);
}
GLWidget::~GLWidget() {
}
void GLWidget::keyPressEvent(QKeyEvent *event) {
switch (event->key()) {
case Qt::Key_C:
cout << "Cleared all the points." << endl;
num_pts = 0;
pts.clear();
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
break;
case Qt::Key_W:
outline = !outline;
if (outline) {
cout << "Displaying outlines." << endl;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
else {
cout << "Displaying filled polygons." << endl;
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
break;
case Qt::Key_Space:
switch (next) {
case(0):
drawMode = GL_POINTS;
cout << "drawMode is GL_POINTS" << endl;
next = 1;
break;
case(1):
drawMode = GL_LINES;
cout << "drawMode is GL_LINES" << endl;
next = 2;
break;
case(2):
drawMode = GL_LINE_STRIP;
cout << "drawMode is GL_LINE_STRIP" << endl;
next = 3;
break;
case(3):
drawMode = GL_LINE_LOOP;
cout << "drawMode is GL_LINE_LOOP" << endl;
next = 4;
break;
case(4):
drawMode = GL_TRIANGLES;
cout << "drawMode is GL_TRIANGLES" << endl;
next = 5;
break;
case(5):
drawMode = GL_TRIANGLE_STRIP;
cout << "drawMode is GL_TRIANGLE_STRIP" << endl;
next = 6;
break;
case(6):
drawMode = GL_TRIANGLE_FAN;
cout << "drawMode is GL_TRIANGLE_FAN" << endl;
next = 0;
break;
}
break;
case Qt::Key_P:
cout << "Projection Location: " << projectionMatrixLoc << endl << endl;
cout << "Projection Matrix:" << endl << endl;
cout << "------------" << endl;
cout << ortho[0][0] << " ";
cout << ortho[1][0] << " ";
cout << ortho[2][0] << " ";
cout << ortho[3][0] << endl;
cout << "------------" << endl;
cout << ortho[0][1] << " ";
cout << ortho[1][1] << " ";
cout << ortho[2][1] << " ";
cout << ortho[3][1] << endl;
cout << "------------" << endl;
cout << ortho[0][2] << " ";
cout << ortho[1][2] << " ";
cout << ortho[2][2] << " ";
cout << ortho[3][2] << endl;
cout << "------------" << endl;
cout << ortho[0][3] << " ";
cout << ortho[1][3] << " ";
cout << ortho[2][3] << " ";
cout << ortho[3][3] << endl;
cout << "------------" << endl << endl << endl;
break;
}
update();
}
void GLWidget::mousePressEvent(QMouseEvent *event) {
glm::vec2 temp = glm::vec2(0.0);
temp.x = event->x();
temp.y = event->y();
pts.push_back(temp);
cout << "Added point (" << pts.back().x << ", " << pts.back().y << ") " << endl;
cout << "Number of points: " << pts.size() << endl;
num_pts++;
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, pts.size(), &pts, GL_DYNAMIC_DRAW);
update();
}
void GLWidget::initializeGL() {
initializeOpenGLFunctions();
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glPointSize(4.0f);
// Create a new Vertex Array Object on the GPU which
// saves the attribute layout of our vertices.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a buffer on the GPU for position data
glGenBuffers(1, &positionBuffer);
// Upload the position data to the GPU, storing
// it in the buffer we just allocated.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_DYNAMIC_DRAW);
// Load our vertex and fragment shaders into a program object
// on the GPU
program = loadShaders(":/vert.glsl", ":/frag.glsl");
// Bind the attribute "position" (defined in our vertex shader)
// to the currently bound buffer object, which contains our
// position data for a single triangle. This information
// is stored in our vertex array object.
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
GLint positionIndex = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(positionIndex);
glVertexAttribPointer(positionIndex, 2, GL_FLOAT, GL_FALSE, 0, 0);
glUseProgram(program);
projectionMatrixLoc = glGetUniformLocation(program, "ProjectionMatrix");
glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}
void GLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
ortho = glm::ortho(0.0f, (float)w, (float)h, 0.0f);
glUseProgram(program);
// problem area?
glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, glm::value_ptr(ortho));
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
// draw primitives based on the current draw mode
glDrawArrays(drawMode, 0, num_pts);
// draw points so we can always see them
// glPointSize adjusts the size of point
// primitives
glDrawArrays(GL_POINTS, 0, num_pts);
}
// Copied from LoadShaders.cpp in the the oglpg-8th-edition.zip
// file provided by the OpenGL Programming Guide, 8th edition.
const GLchar* GLWidget::readShader(const char* filename) {
#ifdef WIN32
FILE* infile;
fopen_s(&infile, filename, "rb");
#else
FILE* infile = fopen(filename, "rb");
#endif // WIN32
if (!infile) {
#ifdef _DEBUG
std::cerr << "Unable to open file '" << filename << "'" << std::endl;
#endif /* DEBUG */
return NULL;
}
fseek(infile, 0, SEEK_END);
int len = ftell(infile);
fseek(infile, 0, SEEK_SET);
GLchar* source = new GLchar[len + 1];
fread(source, 1, len, infile);
fclose(infile);
source[len] = 0;
return const_cast<const GLchar*>(source);
}
GLuint GLWidget::loadShaders(const char* vertf, const char* fragf) {
GLuint program = glCreateProgram();
// read vertex shader from Qt resource file
QFile vertFile(vertf);
vertFile.open(QFile::ReadOnly | QFile::Text);
QString vertString;
QTextStream vertStream(&vertFile);
vertString.append(vertStream.readAll());
std::string vertSTLString = vertString.toStdString();
const GLchar* vertSource = vertSTLString.c_str();
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertShader, 1, &vertSource, NULL);
glCompileShader(vertShader);
{
GLint compiled;
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei len;
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetShaderInfoLog(vertShader, len, &len, log);
std::cout << "Shader compilation failed: " << log << std::endl;
delete[] log;
}
}
glAttachShader(program, vertShader);
// read fragment shader from Qt resource file
QFile fragFile(fragf);
fragFile.open(QFile::ReadOnly | QFile::Text);
QString fragString;
QTextStream fragStream(&fragFile);
fragString.append(fragStream.readAll());
std::string fragSTLString = fragString.toStdString();
const GLchar* fragSource = fragSTLString.c_str();
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragShader, 1, &fragSource, NULL);
glCompileShader(fragShader);
{
GLint compiled;
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei len;
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetShaderInfoLog(fragShader, len, &len, log);
std::cerr << "Shader compilation failed: " << log << std::endl;
delete[] log;
}
}
glAttachShader(program, fragShader);
glLinkProgram(program);
{
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked) {
GLsizei len;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
GLchar* log = new GLchar[len + 1];
glGetProgramInfoLog(program, len, &len, log);
std::cout << "Shader linker failed: " << log << std::endl;
delete[] log;
}
}
return program;
}
The Header File:
#ifndef __GLWIDGET__INCLUDE__
#define __GLWIDGET__INCLUDE__
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QMouseEvent>
#include <glm/glm.hpp>
#include <vector>
// glm by default uses degrees, but that functionality
// is deprecated so GLM_FORCE_RADIANS turns off some
// glm warnings
#define GLM_FORCE_RADIANS
using glm::vec2;
class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core {
Q_OBJECT
public:
GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void mousePressEvent(QMouseEvent *event);
void keyPressEvent(QKeyEvent *event);
private:
GLuint loadShaders(const char* vertf, const char* fragf);
static const GLchar* readShader(const char* filename);
GLuint vao;
GLuint program;
GLuint positionBuffer;
GLint projectionMatrixLoc;
bool outline;
GLenum drawMode;
glm::mat4 ortho;
int next;
std::vector<vec2> pts;
int num_pts;
};
#endif
My Vertex Shader:
#version 330
in vec2 position;
uniform mat4 ProjectionMatrix;
void main() {
gl_Position = vec4(position.x, position.y, 0, 1)*ProjectionMatrix;
}
My Fragment Shader:
#version 330
out vec4 color_out;
void main() {
color_out = vec4(1.0,1.0,1.0,1.0);
}