I'm seeing "ERROR 1282 in glViewport" in my terminal whne I call glViewport from inside glfwSetFramebufferSizeCallback. Not sure why, I think it should be firing from the correct context, but I'm not sure. It worked fine before I tried to move my gameloop into a thread.
Here's the code, I tried to trim out the extraneous stuff:
const int winWidth = 800;
const int winHeight = 600;
absl::Status glfwMain() {
gl::setOpenGlVersion(4, 6, GLFW_OPENGL_CORE_PROFILE);
ASSIGN_OR_RETURN(GLFWwindow * window, gl::createWindow(winWidth, winHeight, "mario4ever"))
std::atomic<bool> breakLoop = false;
auto gameLoop = std::async(std::launch::async, [&window, &breakLoop]() {
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
return absl::InternalError("Failed to initialize GLAD");
}
/* snip */
glViewport(0, 0, winWidth, winHeight);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
std::cerr << "glfwSetFramebufferSizeCallback" << std::endl;
glViewport(0, 0, width, height); // <----- error fires here
});
while (!breakLoop) {
draw(window);
}
/* snip */
return absl::OkStatus();
});
while (!glfwWindowShouldClose(window)) {
processInput(window);
glfwPollEvents();
}
breakLoop = true;
return gameLoop.get();
return absl::OkStatus();
}
int main() {
glfwInit();
auto status = glfwMain();
glfwTerminate();
if (!status.ok()) {
std::cerr << status << std::endl;
}
return status.raw_code();
}
Whether I put the glfwSetFramebufferSizeCallback inside the std::async or outside doesn't seem to make a difference.
What's the problem?
This tutorial says error 1282 is GL_INVALID_VALUE and according to these docs that should happen only when "either width or height is negative".
I checked the width and height that the callback is giving me and neither is negative. They're about what I'd expect.
Tried adding a mutex:
std::mutex drawMutex;
void draw(GLFWwindow *window) {
std::lock_guard<std::mutex> lock(drawMutex);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
...
// inside `std::async` callback:
glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
std::lock_guard<std::mutex> lock(drawMutex);
glViewport(0, 0, width, height);
});
Related
First time asking a question on here so if it's not layed out correctly or something is missing I'll try to get everything else up.
I'm trying to learn OpenGl because I'm interested in developing games of my own and I would rather create my own engine than one already out there.
I'm using GLEW also and I know it inits because the code doesn't output an Error
I spend alittle while googling the error code and the OpenGL but none of the problems really match what I'm getting.
I also tried the GLEW_Experimental = true but that did not change anything.
Code: main
#include "src/graphics/window.h"
int main()
{
using namespace FutureGamingEngine;
using namespace graphics;
Window window("Test", 1080, 720);
glClearColor(0, 255, 0, 1.0f); //Red, Green, Blue, No Idea
std::cout << glGetString(GL_VERSION) << std::endl;
std::cout << glGetString(GL_RENDERER) << std::endl;
std::cout << glGetString(GL_RENDER) << std::endl;
while (!window.closed())
{
window.clear();
glBegin(GL_QUADS);
glVertex2f(-0.5f, -0.5f);
glVertex2f(-0.5f, 0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(0.5f,-0.5f);
glEnd();
window.update();
}
//system("PAUSE");
return 0;
}
Window:
#include "window.h"
namespace FutureGamingEngine
{
namespace graphics
{
void windowResize(GLFWwindow *window, int width, int height);
Window::Window(const char *title, int width, int height)
{
c_title = title;
c_height = height;
c_width = width;
if (!init())
{
glfwTerminate();
}
}
Window::~Window()
{
glfwTerminate();
}
bool Window::init()
{
glewExperimental = true;
if (!glfwInit())
{
std::cout << "Error Code: 0" << std::endl;
return false;
}
//Create a windowed mode and it's OpenGl Content
c_window = glfwCreateWindow(c_width, c_height, c_title, NULL, NULL);
//If we fail to make the window Terminate OpenGL
if (!c_window)
{
glfwTerminate();
return false;
}
//std::cout << "Open GL: " << glGetString(GL_VERSION) << std::endl;
glfwMakeContextCurrent(c_window);
glfwSetWindowSizeCallback(c_window, windowResize);
if (glewInit() != GLEW_OK)
{
std::cout << "Error Code: 1" << std::endl;
return false;
}
return true;
}
bool Window::closed() const
{
return glfwWindowShouldClose(c_window);
}
void Window::update()
{
//poll for and process events
glfwPollEvents();
glfwGetFramebufferSize(c_window, &c_width, &c_height);
//swap front and backbuffers
glfwSwapBuffers(c_window);
}
void Window::clear() const
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void windowResize(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
}
}
The Header for window:
#pragma once
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
namespace FutureGamingEngine
{
namespace graphics
{
class Window
{
private:
const char *c_title;
int c_width, c_height;
GLFWwindow *c_window;
bool c_closed;
public:
Window(const char *a_name, int a_width, int a_height);
~Window();
bool closed() const;
void update();
void clear() const;
inline int getHeight() const { return c_height; };
inline int getWidth() const { return c_width; };
private:
bool init();
};
}
}
I'm expecting it to tell me the Render Version. What I'm actually getting is Error Produced on std::cout << glGetString(GL_RENDER) << std::endl; :
Exception thrown at 0x7C50F6E0 (ucrtbased.dll) in FutureGamingEngine-Core.exe: 0xC0000005: Access violation reading location 0x00000000.
(https://i.imgur.com/uKu3hxX.png)
and the doesn't get to rendering the Triangle like it did prior to me asking for Gl_render
GL_RENDERER is valid enum, GL_RENDER is not. See OpenGL doc
Thank you Ripi2! I apperently did not look hard enough :D
For some reason my Window::callback is being called even after the mouse has left the window. I am unable to find a solution or even something that could help. Is it possible that GLFW updated how the mouse cursor callback operates? I wonder if it is an order of invocation problem?
Window
Window::Window(std::string title, int32_t width, int32_t height) {
// TODO: add support for monitor and share for GLFW
m_window = std::unique_ptr<GLFWwindow, GLFWdeleter>(glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr));
glfwMakeContextCurrent(m_window.get());
glfwSetWindowUserPointer(m_window.get(), this);
glfwSetCursorPosCallback(m_window.get(), Window::callback);
}
void Window::mouse_callback(double xpos, double ypos) {
std::cout << "x: " << xpos << " y: " << ypos << std::endl;
}
void Window::callback(GLFWwindow* window, double xpos, double ypos)
{
auto win = static_cast<Window*>(glfwGetWindowUserPointer(window));
win->mouse_callback(xpos, ypos);
}
Engine
void startup() const
{
if (glfwInit() == 0)
{
LOG(kError, "GLFW init failed!");
exit(-1);
}
}
void Engine::run() {
if (m_main_window_registered)
{
glewExperimental = static_cast<GLboolean>(true);
if (glewInit() != GLEW_OK)
{
std::cout << "Failed to initialize glew" << std::endl;
return;
}
}
while(glfwWindowShouldClose(m_main_window->window()) == 0) {
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(m_main_window->window());
glfwPollEvents();
}
}
main.cpp
int main()
{
g_engine.startup();
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
auto window = std::make_unique<Window>("Hello World!", 640, 480);
//window->make_current();
g_engine.registerWindow(std::move(window));
g_engine.run();
glfwTerminate();
return 0;
}
I have figured out what the problem (or better put) issue is. On Windows the callback performs as expected where once the mouse leaves the windows area the callback stops firing. For OSX the window never loses focus and therefore the cursor callback is always being called. To fix the issue you simply have to test the coordinates to ensure that the mouse is in fact inside the window.
So I have been working on a game through C++ with GLFW and GLEW and everything was going fine until I implemented GLEW then I get an error that I have never encountered before and I don't have the foggiest on what to do, I have googled it and done some research but to no avail. I have noticed that in the stack frame section it says something to do with this line of code in my main.cpp
std::cout << glGetString(GL_VERSION) << std::endl;
Also it says something to do with memory. I'll leave the rest of my code down below and if there's any info you need just ask and I will try my best to provide it
So I just discovered if i take out
std::cout << glGetString(GL_VERSION) << std::endl;
then it works however the window isn't created.
Where do I go from here?
Any idea?
#include "src\graphics\window.h"
int main() {
using namespace benji;
using namespace graphics;
Window window("Benji Engine", 1280, 720);
glClearColor(0.2f, 0.3f, 0.8f, 1.0f);
std::cout << glGetString(GL_VERSION) << std::endl;``
while (!window.closed()) {
std::cout << window.getWidth() << ", " << window.getHeight() << std::endl;
window.clear();
glBegin(GL_TRIANGLES);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.0f, 0.5f);
glVertex2f(0.5f, -0.5f);
glEnd();
window.update();
}
return 0;
}
main.h
#pragma once
class main
{
public:
main();
~main();
};
window.cpp
#include "window.h"
namespace benji { namespace graphics {
void windowResize(GLFWwindow *window, int width, int height);
Window::Window(const char *title, int width, int height) {
m_Title = title;
m_Width = width;
m_Height = height;
if (!init()) {
glfwTerminate();
}
}
Window::~Window() {
glfwTerminate();
}
bool Window::init() {
if (!glfwInit()) {
std::cout << "Failed to initialize GLFW!" << std::endl;
return false;
}
m_Window = glfwCreateWindow(m_Width, m_Height, m_Title, NULL, NULL);
if (!m_Window) {
std::cout << "Failed to create GLFW window!" << std::endl;
return false;
}
glfwMakeContextCurrent(m_Window);
glfwSetWindowSizeCallback(m_Window, windowResize);
if (glewInit != GLEW_OK) {
std::cout << "GLEW FAILED!" << std::endl;
return false;
}
return true;
}
void Window::clear() const {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Window::update(){
glfwPollEvents();
glfwSwapBuffers(m_Window);
}
bool Window::closed() const {
return glfwWindowShouldClose(m_Window) == 1;
}
void windowResize(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
}
}}
window.h
#pragma once
#include <iostream>
#include <GL\glew.h>
#include <GLFW\glfw3.h>
namespace benji {
namespace graphics {
class Window {
private:
const char *m_Title;
int m_Width, m_Height;
GLFWwindow *m_Window;
bool m_Closed;
public:
Window(const char *title, int width, int height);
~Window();
bool closed() const;
void update();
void clear() const;
int getWidth() const {
return m_Width;
}
int getHeight() const { return m_Height; }
private:
bool init();
};
}
}
In Window.cpp:
if (glewInit != GLEW_OK) {
std::cout << "GLEW FAILED!" << std::endl;
return false;
}
glewInit() is a function, not a variable. You need to call it as a function. I'm surprised this even compiled.
All other OpenGL functions that come from after version 1.1 will throw errors to the effect of ACCESS_VIOLATION READING ADDRESS 0x00000000 or some similar error, because if glewInit() is not properly called, none of the function macros provided by GLEW will point to valid function pointers.
I'm creating a GLFW window, and I would like the bottom left corner to be the origin. For some reason, the top left corner is the origin.
I should also mention that I'm using OSX.
Here's my window class:
#include "window.h"
namespace graphics {
void window_size_callback(GLFWwindow* window, int width, int height);
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode);
void cursor_position_callback(GLFWwindow* window, double mouse_x, double mouse_y);
Window::Window(const char* title, int width, int height) {
m_title = title;
m_width = width;
m_height = height;
if (!init())
glfwTerminate();
}
Window::~Window() {
glfwTerminate();
}
bool Window::init() {
if (!glfwInit()) {
std::cout << "GLFW failed to initialize!" << std::endl;
return false;
}
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
m_window = glfwCreateWindow(m_width, m_height, m_title, NULL, NULL);
if (!m_window) {
glfwTerminate();
std::cout << "GLFW failed to create a window!" << std::endl;
return false;
}
glfwMakeContextCurrent(m_window);
glfwSetWindowUserPointer(m_window, this);
glfwSetWindowSizeCallback(m_window, window_size_callback);
glfwSetKeyCallback(m_window, key_callback);
glfwSetMouseButtonCallback(m_window, mouse_button_callback);
glfwSetCursorPosCallback(m_window, cursor_position_callback);
if (glewInit() != GLEW_OK) {
std::cout << "GLEW failed to initialize!" << std::endl;
return false;
}
std::cout << "OpenGL Version: " << glGetString(GL_VERSION) << std::endl;
std::cout << "OpenGL Shading Language Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
return true;
}
void Window::update() {
glfwPollEvents();
glfwSwapBuffers(m_window);
}
void Window::clear() const {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
bool Window::isClosed() const {
return glfwWindowShouldClose(m_window);
}
bool Window::isKeyPressed(unsigned int keycode) const {
if (keycode >= MAX_KEYS)
return false;
return m_keys[keycode];
}
bool Window::isMouseButtonPressed(unsigned int button) const {
if (button >= MAX_BUTTONS)
return false;
return m_mouse_buttons[button];
}
void Window::getMousePosition(double& x, double& y) const {
x = m_mouse_x;
y = m_mouse_y;
}
void window_size_callback(GLFWwindow* window, int width, int height) {
Window* win = (Window*)glfwGetWindowUserPointer(window);
win->m_width = width;
win->m_height = height;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) {
Window* win = (Window*)glfwGetWindowUserPointer(window);
win->m_keys[key] = action != GLFW_RELEASE;
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mode) {
Window* win = (Window*)glfwGetWindowUserPointer(window);
win->m_mouse_buttons[button] = action != GLFW_RELEASE;
}
void cursor_position_callback(GLFWwindow* window, double mouse_x, double mouse_y) {
Window* win = (Window*)glfwGetWindowUserPointer(window);
win->m_mouse_x = mouse_x;
win->m_mouse_y = mouse_y;
}
}
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-2-the-first-triangle/
But here is a better way to visualize this : use the Right Hand Rule
X is your thumb
Y is your index
Z is your middle finger. If you put
your thumb to the right and your index to the sky, it will point to
your back, too. Having the Z in this direction is weird, so why is it
so ? Short answer : because 100 years of Right Hand Rule Math will
give you lots of useful tools. The only downside is an unintuitive Z.
This is something you can’t change, it’s built in your graphics card.
So (-1,-1) is the bottom left corner of your screen. (1,-1) is the
bottom right, and (0,1) is the middle top. So this triangle should
take most of the screen.
I'm moving my OpenGL project over from GLUT to GLFW. Currently I am trying to get text to appear on screen using the library FreeType. I am following the tutorials from their site, but I am stuck. I believe I have it all written out, but for some reason it isn't working. What am I missing?
Here is my code:
#include <iostream>
#include <stdlib.h>
// Include GLEW
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "ft2build.h"
#include FT_FREETYPE_H
FT_Library library;
FT_Face face;
static void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
//should only be used for key press or key release
static void key_press(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
void render_text(const std::string &str, FT_Face face, float x, float y, float sx, float sy) {
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
const FT_GlyphSlot glyph = face->glyph;
for (auto c : str) {
if (FT_Load_Char(face, c, FT_LOAD_RENDER) != 0)
continue;
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8,
glyph->bitmap.width, glyph->bitmap.rows,
0, GL_RED, GL_UNSIGNED_BYTE, glyph->bitmap.buffer);
const float vx = x + glyph->bitmap_left * sx;
const float vy = y + glyph->bitmap_top * sy;
const float w = glyph->bitmap.width * sx;
const float h = glyph->bitmap.rows * sy;
struct {
float x, y, s, t;
} data[6] = {
{ vx, vy, 0, 0 },
{ vx, vy - h, 0, 1 },
{ vx + w, vy, 1, 0 },
{ vx + w, vy, 1, 0 },
{ vx, vy - h, 0, 1 },
{ vx + w, vy - h, 1, 1 }
};
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(float), data, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
x += (glyph->advance.x >> 6) * sx;
y += (glyph->advance.y >> 6) * sy;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
void Resize(GLFWwindow* window)
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5.f, 5.f, -5.f, 5.f, 5.f, -5.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void Setup()
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST); // Depth Testing
glDepthFunc(GL_LEQUAL);
glDisable(GL_CULL_FACE);
glCullFace(GL_BACK);
//used for font
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Display(GLFWwindow* window)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
render_text("TEST", face, 0, 0, 100, 100);
glfwSwapBuffers(window);
glfwPollEvents();
}
void Update(GLFWwindow* window)
{
Display(window);
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
//Problem: glewInit failed, something is seriously wrong.
std::cout << "glewInit failed, aborting." << std::endl;
exit(EXIT_FAILURE);
}
FT_Error error = FT_Init_FreeType(&library);
if (error) {
fprintf(stderr, "Could not init freetype library\n");
return 1;
}
error = FT_New_Face(library, "Stoke-Regular.ttf", 0, &face);
if (error == FT_Err_Unknown_File_Format)
{
std::cout << "font is unsupported" << std::endl;
return 1;
}
else if (error)
{
std::cout << "font could not be read or opened" << std::endl;
return 1;
}
error = FT_Set_Pixel_Sizes(face, 0, 48);
if (error)
{
std::cout << "Problem adjusting pixel size" << std::endl;
return 1;
}
//keyboard controls
glfwSetKeyCallback(window, key_press);
Resize(window);
Setup();
while (!glfwWindowShouldClose(window))
{
Update(window);
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}