glm :: rotate导致纹理凸出

时间:2019-06-17 17:24:53

标签: c++ opengl glm-math

我正在实现一个小型图像查看器,该图像查看器能够旋转图像并放大/缩小。我通过使用OpenGL和GLM进行自学来有目的地进行此操作。到目前为止,一切工作都很好,发生的唯一问题是,当我旋转图像时,图像会严重卡住。尤其是当图像的宽度和高度明显不同时,会发生这种情况。旋转90度后,似乎会拉开纹理直到适合为止,这会导致图像失真。我对这里的轮换方式完全理解不对吗?据我了解,这只是多边形坐标与旋转矩阵的乘积。但是后来我不明白为什么会导致纹理膨胀。

我试图从透视角度出发,甚至走了很远,用 object inject is not a member of package com.google package controllers import java.nio.ByteBuffer import boopickle.Default._ import com.google.inject.Inject import play.api.{Configuration, Environment} import play.api.mvc._ import services.ApiService import spatutorial.shared.Api 搭建了一个虚构的相机,但到目前为止没有成功。

顶点着色器的实现:

glm::lookAt()

实施轮换:

const GLchar* vertexSource = R"glsl(
#version 150 core
in vec2 position;
in vec3 color;
in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

uniform mat4 model;
void main()
{
    Color = color;
    Texcoord = texcoord;
    gl_Position = model *  vec4(position, 0.0, 1.0);
}
)glsl";

顶点数组的实现(存在使纹理无法填充整个窗口的因素。这些因素以边界始终为200像素的方式生成):

//...
model = glm::mat4(1.0f);
//Get the transformation into the shader
uniTrans = glGetUniformLocation(shaderProgram, "model");
//...
else if(windowEvent.key.code == sf::Keyboard::Left){
                        degree = 5;
                        model = glm::rotate(model, glm::radians(degree), glm::vec3(0.0f, 0.0f, 1.0f));
                        glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(model));
                    }
                    else if(windowEvent.key.code == sf::Keyboard::Right){
                        degree = -5;
                        model = glm::rotate(model, glm::radians(degree), glm::vec3(0.0f, 0.0f, 1.0f));
                        glUniformMatrix4fv(uniTrans, 1, GL_FALSE, glm::value_ptr(model));
                    }
//...

设置纹理:

//...
 GLfloat vertices[] = {
        //Position                //Color          //Texcoords
        facX*(-1.0f), facY*( 1.0f), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, //top-left
        facX*( 1.0f), facY*( 1.0f), 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, //top-right
        facX*( 1.0f), facY*(-1.0f), 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, //bottom-right
        facX*(-1.0f), facY*(-1.0f), 1.0f, 1.0f, 1.0f, 0.0f, 1.0f //bottom-left
    };
//...

为了更直观地描述发生的问题,当我将宽度!=高度的图像旋转90度时,“新”高度将为旧宽度。但是,发生的事情是高度保持不变,这当然会导致图像凸起。 有人对我在做什么错有想法吗?

1 个答案:

答案 0 :(得分:3)

  

尤其是当图像的宽度和高度相差很大时

您必须使用正交投影矩阵,该矩阵考虑了视口的纵横比。

投影矩阵将所有顶点数据从视图坐标转换为剪辑坐标。剪辑坐标将转换为归一化的设备坐标(NDC)(Perspective divide)。
规范化的设备坐标在(-1, -1, -1)(1, 1, 1)范围内,并形成一个理想的立方体体积。
使用正交投影时,眼睛空间坐标被线性映射到NDC。
如果视口是矩形的,则必须通过映射坐标来考虑。

将投影矩阵添加到顶点着色器:

const GLchar* vertexSource = R"glsl(
#version 150 core
in vec2 position;
in vec3 color;
in vec2 texcoord;

out vec3 Color;
out vec2 Texcoord;

uniform mat4 projection;
uniform mat4 model;
void main()
{
    Color = color;
    Texcoord = texcoord;
    gl_Position = projection * model * vec4(position, 0.0, 1.0);
}

通过ortho()设置正交投影矩阵,该投影矩阵根据纵横比“缩放”几何并将矩阵设置为均匀:

uniProjection = glGetUniformLocation(shaderProgram, "projection");
int widht  = ...; // width of the viewport (window)
int height = ...; // height of the viewport (window)
float aspect = (float)width / height; 

glm::mat4 project = glm::ortho(-aspect, aspect, -1.0f, 1.0f, -1.0f, 1.0f);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(project ));

请注意,如果要绘制矩形,则必须通过顶点坐标形成此矩形。
正投影投影矩阵旨在确保正方形投影在视口上时也为正方形。