Reputation: 446
Simple and short question but I don't know why it is not working. When I call glViewport in the window frame buffer callback nothing changes. Error code is 1282 (0x502). I already googled and found no helpful article. Some said I should use glScissor in addition but does not work either.
Here an MCVE with an oscillating quad for visualization:
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/vec3.hpp"
#include <thread>
#include <iostream>
#include <vector>
#include <chrono>
#include <Windows.h>
#include <wingdi.h>
int createShaders() {
const char* vertex = R"(
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
uniform float scale;
void main() {
gl_Position = vec4(vertexPosition_modelspace, 1.0) * vec4(vec3(scale), 1.0f);
}
)";
const char* fragment = R"(
#version 330 core
void main() {
gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
}
)";
int vertexID, fragmentID, pid;
vertexID = glCreateShader(GL_VERTEX_SHADER);
const GLchar* source = (const GLchar*)vertex;
glShaderSource(vertexID, 1, &source, 0);
glCompileShader(vertexID);
int isCompiled = 0;
glGetShaderiv(vertexID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(vertexID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(vertexID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(vertexID);
return 0;
}
fragmentID = glCreateShader(GL_FRAGMENT_SHADER);
source = (const GLchar*)fragment;
glShaderSource(fragmentID, 1, &source, 0);
glCompileShader(fragmentID);
glGetShaderiv(fragmentID, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int maxLength = 0;
glGetShaderiv(fragmentID, GL_INFO_LOG_LENGTH, &maxLength);
char* infoLog = new char[maxLength];
glGetShaderInfoLog(fragmentID, maxLength, &maxLength, infoLog);
std::cout << infoLog << std::endl;
glDeleteShader(fragmentID);
glDeleteShader(vertexID);
return 0;
}
pid = glCreateProgram();
glAttachShader(pid, vertexID);
glAttachShader(pid, fragmentID);
glLinkProgram(pid);
int isLinked = 0;
glGetProgramiv(pid, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE)
{
int maxLength = 0;
glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(pid, maxLength, &maxLength, &infoLog[0]);
glDeleteProgram(pid);
glDeleteShader(vertexID);
glDeleteShader(fragmentID);
return 0;
}
glDetachShader(pid, vertexID);
glDetachShader(pid, fragmentID);
return pid;
}
unsigned int createVertexArray() {
std::vector<glm::vec3> vertices = {
glm::vec3(0.5f, 0.5f, 0.0f),
glm::vec3(0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, -0.5f, 0.0f),
glm::vec3(-0.5f, 0.5f, 0.0f)
};
unsigned int arrayID, id;
glGenVertexArrays(1, &arrayID);
glBindVertexArray(arrayID);
glGenBuffers(1, &id);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
return arrayID;
}
int main() {
if (!glfwInit())
return 1;
GLFWwindow* window = glfwCreateWindow(960, 520, "MCVE", NULL, NULL);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
});
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
return 1;
wglMakeCurrent(NULL, NULL);
std::thread mainLoopThread([window]() {
glfwMakeContextCurrent(window);
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
int shaderID = createShaders();
int vertexID = createVertexArray();
while (!glfwWindowShouldClose(window)) {
std::chrono::steady_clock::time_point current = std::chrono::steady_clock::now();
std::chrono::microseconds time = std::chrono::duration_cast<std::chrono::microseconds>(current - start);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shaderID);
float s = sin(time.count() / 1000000.0f * 2.0f);
glUniform1f(glGetUniformLocation(shaderID, "scale"), s);
glBindVertexArray(vertexID);
glDrawArrays(GL_QUADS, 0, 4);
glfwSwapBuffers(window);
}
});
while (!glfwWindowShouldClose(window))
glfwWaitEvents();
mainLoopThread.join();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Upvotes: 2
Views: 250
Reputation: 211278
You try to call a OpenGL instruction without a current OpenGL Context.
The callback is executed in the main thread. However the OpenGL Context is not current in the main thread. The OpenGL context is current in the mainLoopThread
thread.
Set a state in the callback function (e.g. std::atomic<bool>
) and invoke glViewport
in the mainLoopThread
thread, once the state is set.
Upvotes: 3