I am using C++ and OpenGL. But I need the object to scale to a certain scale. For a game engine. My goal is just for the scale to be SET not CHANGED.
#define GLFW_INCLUDE_NONE
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GLFW/glfw3.h>
#include <Glad/glad.h>
#include "vendor/ImGui/imgui.h"
#include "vendor/ImGui/backends/imgui_impl_glfw.h"
#include "vendor/ImGui/backends/imgui_impl_opengl3.h"
#include <stdio.h>
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec3 aPos;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" gl_Position = projection * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char* fragmentShaderSource =
"#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec2 wsize;\n"
"void main()\n"
"{\n"
" vec2 position = gl_FragCoord.xy;\n"
" FragColor = vec4(position.x/wsize.x, position.x/position.y/wsize.x,position.y/wsize.y, 1.0f);\n"
"}\n\0";
float aspectRatio;
glm::mat4 projection;
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
aspectRatio = (float)width / (float)height;
projection = glm::ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, -1.0f, 1.0f);
}
int main()
{
if (!glfwInit())
{
// Initialization failed
}
glfwSetErrorCallback(error_callback);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(640, 480, "GL YA!", NULL, NULL);
if (!window)
{
// Window or context creation failed
}
glfwMakeContextCurrent(window);
gladLoadGL();
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
float vertices[9 * 2] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
glfwSwapInterval(1);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLuint VBO;
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.ConfigDockingWithShift = false;
ImGui::StyleColorsDark();
const char* glsl_version = "#version 100";
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
float x = 0;
float y = 0;
float z = 0;
while (!glfwWindowShouldClose(window))
{
int width, height;
glfwGetFramebufferSize(window, &width, &height);
framebuffer_size_callback(window, width, height);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
ImGui::Begin("Hello OpenGL!");
ImGui::InputFloat("X", &x);
ImGui::InputFloat("Y", &y);
ImGui::InputFloat("Z", &z);
ImGui::End();
ImGui::Render();
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
//Square
glUseProgram(shaderProgram);
GLint wsize = glGetUniformLocation(shaderProgram, "wsize");
glUniform2f(wsize, width, height);
/*
glm::mat4 transform = glm::mat4(1.0f); // Start with an identity matrix
transform = glm::translate(transform, glm::vec3(x, y, z)); // Move the triangle along the x and y axes
for (int i = 0; i < 9 * 2; i += 3) {
glm::vec4 vertex = transform * glm::vec4(vertices[i], vertices[i + 1], vertices[i + 2], 1.0f);
vertices[i] = vertex.x;
vertices[i + 1] = vertex.y;
vertices[i + 2] = vertex.z;
}
*/
float currentX = 0.0f;
float currentY = 0.0f;
float currentZ = 0.0f;
for (int i = 0; i < 9 * 2; i += 3) {
currentX += vertices[i];
currentY += vertices[i + 1];
currentZ += vertices[i + 2];
}
currentX /= 9;
currentY /= 9;
currentZ /= 9;
float tx = x - currentX;
float ty = y - currentY;
float tz = z - currentZ;
for (int i = 0; i < 9 * 2; i += 3) {
vertices[i] += tx;
vertices[i + 1] += ty;
vertices[i + 2] += tz;
}
for (int i = 0; i < 9 * 2; i += 3) {
vertices[i] += x;
vertices[i + 1] += y;
vertices[i + 2] += z;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
//ImGui
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
}
I'm not sure what to do. I want to have an exact variable to set, not change the size. I'm looking for a solution using glm and I will later put everything in classes.
If you have vertex data for a mesh and want to scale the object without iterating over the mesh data, then a solution would be to let the shader do it for you.
For that, we only need to introduce a uniform variable in the vertex shader.
Before the transformation gets applied, we first have to scale the vertex position, e.g.
//vertex shader
in vec3 aPos; //position coords
uniform vec3 uScale; //scale factor
uniform mat4 uProjection; //projection matrix
int main()
{
gl_Position = uProjection * vec4(aPos * uScale, 1.0);
}
Usually, that is done via a transformation matrix which is the result of a projection, view and model matrix (hence mvp matrix).
Then in the vertex shader one has either a single uniform called uMVP
or two uniforms, one for the projection and view (which are modified less frequently, at least not for each object) and a model matrix which could be different for each object (different positions, scales and or rotations).
e.g.
//vertex shader
in vec3 aPos;
uniform mat4 uProjection;
uniform mat4 uView;
uniform mat4 uModel;
void main()
{
gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0);
}