Hello Gamedev!
I'm currently working on a project which utilize opengl to render a GUI.
Now when i'm resizing the window i want to resize the gui elements with it. But when i do all elements seem to lag behind. See video.
Why is this?
My framebuffer size callback:
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
Window::Render(window);
Services::Get<CameraService>()->cameras[0].screenSize = {width, height};
}
void Window::Render(GLFWwindow *w)
{
float currentFrame = glfwGetTime();
static int lastFrame;
static int deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glClear(GL_COLOR_BUFFER_BIT);
RendererService *rendererService = Services::Get<RendererService>();
auto renderers = rendererService->renderers;
for (auto renderer : renderers)
{
renderer->Render();
}
glfwSwapBuffers(w);
}
And for example, a rounded rectangle looks like this:
#include <glew.h>
#include <GLFW/glfw3.h>
#include "Rectangle.h"
#include "stb_image.h"
Rectangle::Rectangle()
{
shader = new OpenGL::Core3::Shader();
std::string vertexShaderSource = R"END(
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform vec2 pos;
uniform vec3 rectColor;
uniform vec2 rectSize;
uniform float radius;
out vec2 position;
out vec3 RectColor;
out vec2 RectSize;
out float Radius;
void main()
{
RectColor = rectColor;
RectSize = rectSize;
position = pos;
Radius = radius;
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
)END";
std::string fragmentShaderSource = R"END(
#version 330 core
out vec4 FragColor;
in vec2 position;
in vec3 RectColor;
in vec2 RectSize;
in float Radius;
// from https://iquilezles.org/articles/distfunctions
float roundedBoxSDF(vec2 CenterPosition, vec2 Size, float Radius) {
return length(max(abs(CenterPosition)-Size+Radius,0.0))-Radius;
}
void main() {
// the pixel space location of the rectangle.
vec2 location = position;
// How soft the edges should be (in pixels). Higher values could be used to simulate a drop shadow.
float edgeSoftness = 1.0f;
// The radius of the corners (in pixels).
float radius = Radius;
// Calculate distance to edge.
float distance = roundedBoxSDF(gl_FragCoord.xy - location - (RectSize/2.0f), RectSize / 2.0f, radius);
// Smooth the result (free antialiasing).
float smoothedAlpha = 1.0f-smoothstep(0.0f, edgeSoftness * 2.0f,distance);
// Return the resultant shape.
vec4 quadColor = mix(vec4(1.0f, 1.0f, 1.0f, 0.0), vec4(RectColor, smoothedAlpha), smoothedAlpha);
// Apply a drop shadow effect.
float shadowSoftness = 30.0f;
vec2 shadowOffset = vec2(0.0, 0.0);
float shadowDistance = roundedBoxSDF(gl_FragCoord.xy - location + shadowOffset - (RectSize/2.0f), RectSize / 2.0f, radius);
float shadowAlpha = 1.0f-smoothstep(-shadowSoftness, shadowSoftness, shadowDistance);
vec4 shadowColor = vec4(1.0f, 1.0f, 1.0f, 0.6f);
FragColor = mix(quadColor, shadowColor, shadowAlpha - smoothedAlpha);
}
)END";
shader->Compile(vertexShaderSource.c_str(), fragmentShaderSource.c_str());
float vertices[] = {
// first triangle
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, 0.5f, 0.0f, // top left
// second triangle
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 VBO, VAO;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(vao);
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), (void*)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
addElement(this);
}
void Rectangle::Draw(float deltaTime)
{
// Activate shader
shader->Activate();
// @todo Do something about mainCamera and following cameras.. Active camera?
Camera mainCamera = Services::Get<CameraService>()->cameras[0];
// @todo this is fine me thinks for now!
auto openglShader = static_cast<OpenGL::Core3::Shader *>(shader);
glm::mat4 projection = glm::perspective(glm::radians(mainCamera.Zoom), (float)mainCamera.screenSize.x / (float)mainCamera.screenSize.y, 0.2f, 100.0f);
glm::mat4 view = mainCamera.GetViewMatrix();
glm::mat4 model = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0.0f, 0.0f, 0.0f));
view = glm::rotate(view, glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
// model = glm::translate(model, glm::vec3(0.0f, 0.0f, 0.0f));
model = glm::scale(model, glm::vec3(10.0f, 10.0f, 0.0f));
openglShader->setMat4("projection", projection);
openglShader->setMat4("view", view);
openglShader->setMat4("model", model);
openglShader->setFloat("radius", transform.dimension.radius);
openglShader->setVec2("pos", glm::vec2{transform.position.x, transform.position.y});
openglShader->setVec2("rectSize", glm::vec2{transform.dimension.width, transform.dimension.height});
openglShader->setVec3("rectColor", glm::vec3{style.Background.r, style.Background.g, style.Background.b});
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
Thanks for help,
Joakim Wennergren