You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在OpenGL中为对象设置固定缩放比例(C++&GLM)

固定对象缩放比例的实现方案(基于GLM)

核心思路

不要直接修改顶点数据来实现缩放,而是利用**模型矩阵(Model Matrix)**在GPU端完成变换。这种方式不仅效率更高,还能保持原始顶点数据的纯净,方便后续封装为类管理对象属性。

步骤1:修改顶点着色器

添加model矩阵uniform,将其与投影矩阵结合,完成顶点的最终变换:

#version 330 core
layout(location = 0) in vec3 aPos;
uniform mat4 projection;
uniform mat4 model; // 新增模型矩阵
void main()
{
  gl_Position = projection * model * vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

步骤2:在CPU端用GLM构建模型矩阵

在渲染循环中,基于GLM创建包含固定缩放和位移的模型矩阵,避免直接修改顶点数组:

  1. 定义固定缩放因子(比如让对象保持0.5倍原始大小)
  2. 构建模型矩阵:先平移到目标位置,再应用固定缩放
  3. 将模型矩阵传入着色器

修改后的main函数关键部分:

// 新增固定缩放变量
float scale = 0.5f;

while (!glfwWindowShouldClose(window))
{
    // ... 其他窗口/ImGui初始化代码 ...

    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgram);
    GLint wsize = glGetUniformLocation(shaderProgram, "wsize");
    glUniform2f(wsize, width, height);

    // 1. 构建模型矩阵:平移 + 固定缩放
    glm::mat4 model = glm::mat4(1.0f);
    model = glm::translate(model, glm::vec3(x, y, z)); // 应用位移
    model = glm::scale(model, glm::vec3(scale, scale, 1.0f)); // 固定缩放

    // 2. 将模型矩阵传入着色器
    GLint modelLoc = glGetUniformLocation(shaderProgram, "model");
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    // 3. 传入投影矩阵并绘制
    glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 6);

    // ... ImGui渲染及窗口交换代码 ...
}

步骤3:封装为GameObject类

将位置、缩放、模型矩阵计算逻辑封装到类中,便于管理多个对象:

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

class GameObject {
private:
    glm::vec3 m_position{0.0f};
    glm::vec3 m_scale{1.0f}; // 默认缩放为1倍

public:
    // 设置位置
    void setPosition(const glm::vec3& pos) { m_position = pos; }
    // 设置固定缩放
    void setScale(const glm::vec3& scale) { m_scale = scale; }

    // 获取计算后的模型矩阵
    glm::mat4 getModelMatrix() const {
        glm::mat4 model = glm::mat4(1.0f);
        model = glm::translate(model, m_position);
        model = glm::scale(model, m_scale);
        return model;
    }
};

使用示例:

// 创建游戏对象
GameObject square;
square.setPosition(glm::vec3(x, y, z));
square.setScale(glm::vec3(0.5f, 0.5f, 1.0f)); // 固定缩放

// 渲染时获取矩阵
glm::mat4 model = square.getModelMatrix();
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

关键注意事项

  • 移除原有代码中直接修改顶点数组的逻辑(那部分会导致顶点数据被持续修改,位置偏移越来越大)
  • 固定缩放因子可以根据需求调整,比如设为vec3(0.3f, 0.3f, 1.0f)让对象更小
  • 如果需要保持对象在窗口拉伸时视觉大小不变,可以根据窗口宽高比动态调整缩放因子,但这属于动态适配,不符合你当前的固定缩放需求

内容的提问来源于stack exchange,提问作者kai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 17:48:09