Here is some code that's supposed to output the size of the red component of the default framebuffer's left back color attachment:
#include <iostream>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include "vect2.h"
using namespace std;
void outputError() {
GLenum error = glGetError();
switch (error) {
case GL_NO_ERROR:
cout << "GL_NO_ERROR" << endl;
break;
case GL_INVALID_ENUM:
cout << "GL_INVALID_ENUM" << endl;
break;
case GL_INVALID_VALUE:
cout << "GL_INVALID_VALUE" << endl;
break;
case GL_INVALID_OPERATION:
cout << "GL_INVALID_OPERATION" << endl;
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
cout << "GL_INVALID_FRAMEBUFFER_OPERATION" << endl;
break;
case GL_OUT_OF_MEMORY:
cout << "GL_OUT_OF_MEMORY" << endl;
break;
default:
cout << "UNKNOWN ERROR: " << error << endl;
break;
}
}
int main() {
glewExperimental = GL_TRUE;
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(800, 600, "OpenGL", nullptr, nullptr); // Windowed
glfwMakeContextCurrent(window);
glewInit();
GLint size = 0;
outputError();
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size);
outputError();
return 0;
}
The console output is:
GL_NO_ERROR
GL_INVALID_ENUM
Meaning there is a GL_INVALID_ENUM error state set from my call to glGetFramebufferAttachmentParameteriv. What parameter is wrong here?
EDIT: If I run this code in the main function, requesting the same (red) component from a custom FBO instead of the default framebuffer, then there is no error and I get the expected 32 in the size variable. This means that not only are the attachments different when the default framebuffer is bound vs when an FBO is bound, but the parameters that can be queried for are also different. So basically the question is: what parameters can be queried for using this function when the default framebuffer is bound?
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenRenderbuffers(1, &rboColor);
glBindRenderbuffer(GL_RENDERBUFFER, rboColor);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA32F, 800, 600);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColor);
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size);
Related
I use the Eclipse IDE and the glfw, glew, and glm libraries. I want to create a window, but when I run the code nothing happens. Earlier, when I tried to launch it, it was written in the console "Info: Do not build anything", but now this phrase appears for a moment and disappears. And if I erase the contents of int main(), and write for example: cout << "hello world<<endl;, then the text will be output to the console, but for some reason, the code for creating the window does not work.
I tried reinstalling Eclipse, but nothing changes. I am new to programming in Eclipse, I had to spend about 10 hours fixing other errors that did not even allow me to run the code.
#include <iostream>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using namespace std;
int WIDTH = 1280;
int HEIGHT = 720;
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_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Window", nullptr, nullptr);
if(window == nullptr) {
cerr << "Failed to create GLFW Window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK) {
cerr << "Failed to initialize GLEW" << endl;
return -1;
}
glViewport(0,0, WIDTH, HEIGHT);
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
glfwSwapBuffers(window);
}
return 0;
}
I'm having a problem where the following lines of code always print "Failed to initialize glad" and then exits the program:
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
I have been using https://learnopengl.com/ as a guide and have been following the steps in the getting started section. I am writing this using Visual Studio, I have moved the glad.c source file into the build to get this working and added the header files to the same location where I specified the glfw header would be, but I haven't been able to find anyone with a problem similar to mine.
Commenting out return -1; line results in an access violation exception, so it is definitely here that the program is having trouble.
Here is the entire program in case there is something else I am missing:
#include "stdafx.h"
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <iostream>
using namespace std;
void init_glfw();
void framebuffer_size_callback(GLFWwindow*, int, int);
int main(int argc, char **argv)
{
init_glfw();
GLFWwindow* window = glfwCreateWindow(800, 600, "Lab3", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void init_glfw()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
You never made your GL context current via glfwMakeContextCurrent(). Unlike other GL windowing frameworks GLFW doesn't leave the GL context current when glfwCreateWindow() succeeds.
Call glfwMakeContextCurrent() after glfwCreateWindow() succeeds:
GLFWwindow* window = glfwCreateWindow(800, 600, "Lab3", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent( window );
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
I'm having a problem where the following lines of code always print "Failed to initialize glad" and then exits the program:
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
I have been using https://learnopengl.com/ as a guide and have been following the steps in the getting started section. I am writing this using Visual Studio, I have moved the glad.c source file into the build to get this working and added the header files to the same location where I specified the glfw header would be, but I haven't been able to find anyone with a problem similar to mine.
Commenting out return -1; line results in an access violation exception, so it is definitely here that the program is having trouble.
Here is the entire program in case there is something else I am missing:
#include "stdafx.h"
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <iostream>
using namespace std;
void init_glfw();
void framebuffer_size_callback(GLFWwindow*, int, int);
int main(int argc, char **argv)
{
init_glfw();
GLFWwindow* window = glfwCreateWindow(800, 600, "Lab3", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, 800, 600);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void init_glfw()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
You never made your GL context current via glfwMakeContextCurrent(). Unlike other GL windowing frameworks GLFW doesn't leave the GL context current when glfwCreateWindow() succeeds.
Call glfwMakeContextCurrent() after glfwCreateWindow() succeeds:
GLFWwindow* window = glfwCreateWindow(800, 600, "Lab3", NULL, NULL);
if (window == NULL)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent( window );
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
I am trying to use a combination of SFML and OpenGL for a project, but I am having trouble rendering to a sf::RenderTexture. Specifically, if I try to draw while the RenderTexture is active, I crash. (Looks like a null pointer dereference inside glDrawElements.)
Rendering directly to the window works fine. And if I manually create a framebuffer through OpenGL myself, that also works fine. But I'd like to be able to use RenderTexture if possible to simplify a lot of the code.
I may be doing something stupid, but I'm still new to OpenGL so I'm not sure. (Especially with the mixture of SFML and OpenGL, it seems like a lot of stuff can break if you don't manage the context switching correctly.) I'm not seeing any warnings from OpenGL or SFML.
The following reproduces the issue I'm seeing (Windows 10, Visual Studio 2017, OpenGL 4.5, GLEW 2.1.0, SFML 2.4.0):
#include <iostream>
#include <string>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#define GL_GLEXT_PROTOTYPES
#include <GL/glew.h>
#include <SFML/OpenGL.hpp>
GLenum glCheckError_(const char *file, int line)
{
GLenum errorCode;
while ((errorCode = glGetError()) != GL_NO_ERROR)
{
std::string error;
switch (errorCode)
{
case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
case GL_STACK_UNDERFLOW: error = "STACK_UNDERFLOW"; break;
case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
}
std::cerr << error << " | " << file << " (" << line << ")" << std::endl;
}
return errorCode;
}
#define glCheckError() glCheckError_(__FILE__, __LINE__)
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "test");
glewInit();
std::cout << "Using OpenGL " << window.getSettings().majorVersion << "." << window.getSettings().minorVersion << std::endl;
//std::cout << "Available GL extensions: " << glGetString(GL_EXTENSIONS) << std::endl;
sf::Shader shader;
{ // Shader
const char* vs = R"(
#version 330 core
layout (location = 0) in vec3 pos;
void main()
{
gl_Position = vec4(pos, 1.0);
}
)";
const char* fs = R"(
#version 330 core
out vec4 color;
void main()
{
color = vec4(0.3, 0.8, 0.2, 1.0);
}
)";
shader.loadFromMemory(vs, fs);
}
unsigned int vao;
{ // Mesh
float vertices[] = {
0.3f, 0.5f, 1.0f, // top right
0.5f, -0.5f, -0.5f, // bottom right
-0.5f, -0.5f, -1.0f, // bottom left
-0.3f, 0.5f, 0.5f, // top left
};
unsigned int indices[] = {
0, 3, 1, // first triangle
1, 3, 2, // second triangle
};
unsigned int vbo, ebo;
glGenVertexArrays(1, &vao);
glCheckError();
glGenBuffers(1, &vbo);
glCheckError();
glGenBuffers(1, &ebo);
glCheckError();
glBindVertexArray(vao);
glCheckError();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glCheckError();
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glCheckError();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glCheckError();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glCheckError();
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glCheckError();
glEnableVertexAttribArray(0);
glCheckError();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glCheckError();
glBindVertexArray(0);
glCheckError();
}
sf::RenderTexture texture;
sf::Sprite sprite;
{ // Render Texture
if (!texture.create(800, 600, true)) {
std::cerr << "Failed to create RenderTexture" << std::endl;
}
sprite.setTexture(texture.getTexture());
}
int frame = 0;
while (window.isOpen())
{
++frame;
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
}
window.clear();
if (frame > 1)
{
window.popGLStates();
}
{ // Render to screen
sf::Shader::bind(&shader);
glBindVertexArray(vao);
glCheckError();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glCheckError();
glBindVertexArray(0);
glCheckError();
sf::Shader::bind(nullptr);
}
window.pushGLStates();
window.display();
// Press space to continue...
bool waiting = true;
while (waiting) {
while (window.pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Space)
{
waiting = false;
break;
}
}
}
window.clear();
if (frame > 1)
{
window.popGLStates();
}
{ // Render to texture
sf::Shader::bind(&shader);
glBindVertexArray(vao);
glCheckError();
texture.pushGLStates();
if (!texture.setActive(true)) { // TODO Setting the texture as active is causing me to segfault, messing up my state somehow
std::cerr << "Failed to activate RenderTexture" << std::endl;
}
texture.clear();
texture.popGLStates();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // <-- Crashes here!
glCheckError();
texture.pushGLStates();
texture.display();
if (!texture.setActive(false)) {
std::cerr << "Failed to deactivate RenderTexture" << std::endl;
}
texture.popGLStates();
glBindVertexArray(0);
glCheckError();
sf::Shader::bind(nullptr);
}
window.pushGLStates();
window.draw(sprite);
window.display();
}
};
Does anyone have any ideas?
EDIT: Well I've solved the crashing part. sf::RenderTextures have their own GL context, and I guess you can't reuse data between contexts. So I had to generate the texture first and use texture.setActive() before generating the shader and mesh. That way the context has those objects available.
Now I am just getting a black screen. I am able to draw a new sf::RectangleShape to the same RenderTexture, but my GL mesh doesn't seem to be drawing. Still investigating...
In case anyone has the same issue, here are snippets of what I had to change:
// --- initialization ---
// Generate the texture first so its context is available
sf::RenderTexture texture;
sf::Sprite sprite;
{ // Render Texture
if (!texture.create(800, 600, true)) {
std::cerr << "Failed to create RenderTexture" << std::endl;
}
sprite.setTexture(texture.getTexture());
}
// Generate the rest of the data within the texture's context
sf::Shader shader;
{ // Shader
if (!texture.setActive(true)) {
std::cerr << "Failed to activate RenderTexture" << std::endl;
}
shader.loadFromMemory(vs, fs);
if (!texture.setActive(false)) {
std::cerr << "Failed to deactivate RenderTexture" << std::endl;
}
}
unsigned int vao;
{ // Mesh
if (!texture.setActive(true)) {
std::cerr << "Failed to activate RenderTexture" << std::endl;
}
unsigned int vbo, ebo;
glGenVertexArrays(1, &vao);
glCheckError();
glGenBuffers(1, &vbo);
glCheckError();
// ...
glBindBuffer(GL_ARRAY_BUFFER, 0);
glCheckError();
glBindVertexArray(0);
glCheckError();
if (!texture.setActive(false)) {
std::cerr << "Failed to deactivate RenderTexture" << std::endl;
}
}
// --- drawing ---
{ // Render to texture
// Make sure we use the appropriate context for all drawing to texture
if (!texture.setActive(true)) {
std::cerr << "Failed to activate RenderTexture" << std::endl;
}
texture.clear();
sf::Shader::bind(&shader);
glBindVertexArray(vao);
glCheckError();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // TODO rendering nothing here...
glCheckError();
glBindVertexArray(0);
glCheckError();
sf::Shader::bind(nullptr);
// Drawing to the texture through SFML works fine
texture.pushGLStates();
sf::RectangleShape rect(sf::Vector2f(20, 20));
rect.setFillColor(sf::Color::Cyan);
texture.draw(rect);
texture.popGLStates();
texture.display();
if (!texture.setActive(false)) {
std::cerr << "Failed to deactivate RenderTexture" << std::endl;
}
}
if (!window.setActive(true)) {
std::cerr << "Failed to activate window" << std::endl;
}
window.pushGLStates();
window.draw(sprite);
window.display();
EDIT 2: Drawing problems solved, see my answer.
I found the answer! All thanks to "Groogy" in this thread: https://en.sfml-dev.org/forums/index.php?topic=7446.0
I had skimmed that thread earlier, which prompted me to add texture.setView(texture.getDefaultView()); when creating the RenderTexture. However that was not enough, I instead had to call glViewport with the texture bound. (I assumed that is what sf::View would do under the covers, but apparently that is not the case.)
So my RenderTexture creation now looks like this:
sf::RenderTexture texture;
sf::Sprite sprite;
{ // Render Texture
if (!texture.create(800, 600, true)) {
std::cerr << "Failed to create RenderTexture" << std::endl;
}
if (!texture.setActive(true)) {
std::cerr << "Failed to activate texture" << std::endl;
}
sprite.setTexture(texture.getTexture());
glViewport(0, 0, 800, 600); // <-- Required
glCheckError();
if (!texture.setActive(false)) {
std::cerr << "Failed to deactivate texture" << std::endl;
}
}
And now things are working.
I've been trying some modern OpenGL tutorials, and I came across what seems to be strange behaviour. Here is the code, reduced to its (almost) bare essentials.
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using std::cout;
using std::endl;
int main(){
std::cout << "Begin program" << std::endl;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", 0, 0); // Windowed
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
glewInit();
while(!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
}
cout << "before glfwTerminate()" << endl;
glfwTerminate();
cout << "after glfwTerminate()" << endl; cout.flush();
std::cout << "End program" << std::endl;
return 0;
}
Looking at the GLFW docs, the call to glfwTerminate() should not exit the program, but nothing is output to the console after "before glfwTerminate()" and the program ends.
I'm on ArchLinux (freshly updated) and I tried with both xfce4 and KDE (minimal install for the latter, just to make sure it wasn't an xfce4 issue).
Would someone have a hint as to what is going on?
It is not finishing the program. Indeed it is processing the lines after glfwTerminate(), but somehow glfw is changing how stdout is bound to output stream.
It is a bug. You can confirm this by changing cout to cerr