【问题标题】:glm::rotate leads to bulging of textureglm::rotate 导致纹理膨胀
【发布时间】:2019-06-18 01:48:57
【问题描述】:

我正在实现一个能够旋转图像和放大/缩小的小型图像查看器。我是故意使用 OpenGL 和 GLM 进行自学的。到目前为止一切正常,发生的唯一问题是当我旋转图像时图像严重倾斜。当图像的宽度和高度有很大不同时,尤其会发生这种情况。旋转 90 度后,纹理似乎会弯曲直到适合,这会导致图像失真。我对这里的轮换方式理解完全错误吗?据我了解,它只是将多边形坐标与旋转矩阵相乘。但后来我不明白为什么会导致纹理膨胀。

我尝试过使用视角,甚至使用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";

轮换的实现:

//...
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));
                    }
//...

顶点数组的实现(这些因素使纹理不会填满整个窗口。它们以边框始终为200像素的方式生成):

//...
 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
    };
//...

设置纹理:

GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getX(), image.getY(), 0, GL_BGRA, GL_UNSIGNED_BYTE, (const GLvoid*)data);
    //Defining how to proceed if the texture is smaller than the space
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    //Specify Border Color
    float color[] = {1.0f, 0.0f, 0.0f, 1.0f};
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
    //Set up filter for up and downscaling of the texture (linear smooth, nearest would give pixelised result)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

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

【问题讨论】:

    标签: c++ opengl glm-math


    【解决方案1】:

    尤其是当图像的宽度和高度相差很大时会发生这种情况

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

    投影矩阵将所有顶点数据从视图坐标转换为剪辑坐标。剪辑坐标转换为标准化设备坐标 (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 ));
    

    注意,如果你想画一个矩形,那么你必须通过顶点坐标来形成这个矩形。
    正交投影矩阵是为了保证一个正方形在投影到视口上时也是正方形。

    【讨论】:

    • 感谢投影矩阵的讲解。它对了解正在发生的事情有很大帮助。我仍然在为你的添加而挣扎,但它引导我朝着正确的方向前进。当我实施您的解决方案时,我首先忽略了我与顶点矩阵一起使用的因素。添加它们后,现在一切都很好。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多