如何在OpenGL中设置特定比例?

问题描述 投票:0回答:1

我正在使用 C++ 和 OpenGL。但我需要将对象缩放到一定比例。对于游戏引擎来说。 我的目标只是设置比例而不是更改。

#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();
}

我不知道该怎么办。我想要一个精确的变量来设置,而不是改变大小。 我正在寻找使用 glm 的解决方案,稍后我会将所有内容放入类中。

opengl glfw glm-math glew
1个回答
0
投票

如果您有网格的顶点数据并且想要缩放对象而不迭代网格数据,那么解决方案是让着色器为您完成此操作。

为此,我们只需要在顶点着色器中引入一个uniform变量即可。

在应用变换之前,我们首先必须缩放顶点位置,例如

//vertex shader

in vec3 aPos;             //position coords
uniform vec3 uScale;      //scale factor
uniform mat4 uProjection; //mvp matrix

int main()
{
    gl_Position = uProjection * vec4(aPos * uScale, 1.0);
}
© www.soinside.com 2019 - 2024. All rights reserved.