我正在尝试使用 glm 旋转纹理图像,但输出看起来拉伸(stretch)或没有沿 z 轴正确旋转。这个可能的解决方案是什么。
float imgAspectRatio = imageWidth / (float) imageHeight;
float viewAspectRatio = viewWidth / (float) viewHeight;
if (imgAspectRatio > viewAspectRatio) {
yScale = viewAspectRatio / imgAspectRatio;
} else {
xScale = imgAspectRatio / viewAspectRatio;
}
glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(0, 0, 0));
model = glm::rotate(model, glm::radians(angle),
glm::vec3(0, 0, 1));
model = glm::scale(model, glm::vec3(xScale, yScale, 1.0f));
一些建议与 glm::ortho 相乘,但它给出方形
glm::mat4 projection(1.0f);
projection = glm::ortho(
-imgAspectRatio,
imgAspectRatio,
-1.0f,
1.0f,
-1.0f,
1.0f
);
最佳答案
如果您有一个方形窗口,您当前拥有的代码实际上可以工作。
通过将图像纵横比缩放和 View 纵横比缩放结合到一个步骤中,您当前的操作顺序基本上如下:
但是,您真的想在最后按 View 纵横比进行缩放。一个简单的练习来帮助可视化原因:想象你有一个完美的方形窗口,在其中渲染一个 xy 坐标为 (-1, -1), (1, -1), (0, 1) 的三角形。现在假设您的窗口高度增加了一倍,但您希望形状保持不变:显然,您只需将每个 y 坐标乘以 1/2。现在假设您要将三角形逆时针旋转 90 度,但仍保持形状相同。您是否先旋转然后按 View 纵横比缩放?或相反亦然?通过运行这两个选项,很明显您必须最后按 View 纵横比进行缩放。
换句话说,您需要以下顺序:
这是通过看起来像这样的代码实现的:
float xScaleImg = 1.0f;
float yScaleImg = xScaleImg / imgAspectRatio;
float xScaleView = 1.0f;
float yScaleView = viewAspectRatio;
glm::mat4 model(1.0f);
model = glm::scale(model, glm::vec3(xScaleView, yScaleView, 1.0f));
model = glm::translate(model, glm::vec3(0, 0, 0));
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 0, 1));
model = glm::scale(model, glm::vec3(xScaleImg, yScaleImg, 1.0f));
与您的示例一样,前四行假设 View 和图像宽度都大于各自的高度。如果反过来为真,您可能需要添加一些逻辑来改变这一点。更新:
根据您想要实现的翻译效果,您可能需要移动
glm::translate(...)
命令一行。我在原始答案中给出的顺序使平移单位以像素为单位。例如。如果你传入 glm::vec3(1.0f, 1.0f, 0.0f)
, 并且窗口的宽度是 1280 像素,那么图像将向左平移 640 像素,向上平移 640 像素。但是,您可能希望在两个轴上保持 OpenGL [-1, 1] 范围。也就是说,当你传入
glm::vec3(1.0f, 1.0f, 0.0f)
对于翻译,您可能希望将图像翻译为窗口宽度的一半和窗口高度的一半。在这种情况下,您需要使翻译成为对图像执行的最后一个操作,这是通过将 glm::translate(...)
设置为第一行代码。这就是 Nile Qor 想要的。在这种情况下,代码的最后几行变为: glm::mat4 model(1.0f);
model = glm::translate(model, glm::vec3(1.0f, 1.0f, 0));
model = glm::scale(model, glm::vec3(xScaleView, yScaleView, 1.0f));
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 0, 1));
model = glm::scale(model, glm::vec3(xScaleImg, yScaleImg, 1.0f));
有关更多上下文,您可以在此答案的评论部分查看讨论。
关于c++ - 具有缩放拉伸(stretch)纵横比的 glm 旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63261779/