提问者:小点点

OpenGL和GLM矩阵不能正确缩放,总是缩放


当我使用GLM::scale更新我的顶点着色器中的模型矩阵时,无论我做什么,它总是会将其按比例缩小。 有人知道我做错了什么吗? 图像有时也会上下翻转。

key=='W'和key=='s'虽然代码不同,但它们做的事情完全一样,目标是通过按W使模型变大,通过按s使模型变小。

用于根据按键进行缩放的相关代码是:

if (key == 'w') {
        model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 's') {
        model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }

整个代码是:

#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include <iostream>
#include <SOIL.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "OBJ.h"

const char* vs = "#version 330 core\n"
"layout (location = 0) in vec3 pos;\n"
"layout (location = 1) in vec2 texpos;\n"
"out vec2 texCoords;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(pos, 1);\n"
"texCoords = texpos;\n"
"}\0";

const char* fs = "#version 330 core\n"
"in vec2 texCoords;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex;\n"
"void main()\n"
"{\n"
"fragColor = texture(tex, texCoords);"
"}\0";

float verts[] = {
    0, 1, 0, 0.5, 1,
    -1, -1, 0, 0, 0,
    1, -1, 0, 1, 0
};

unsigned short indices[] = {
    0, 1, 2
};

unsigned int vao, vbo, ebo, prog, vert, frag, texid;

glm::mat4 model, view, projection;


void changeViewPort(int w, int h)
{
    glViewport(0, 0, w, h);
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindVertexArray(vao);
    glBindTexture(GL_TEXTURE_2D, texid);
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
    glutSwapBuffers();
}

void initGL() {
    //Context stuff
    glViewport(0, 0, 800, 600);
    glClearColor(0.5, 0.5, 0.5, 1);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //Shader stuff
    int success;
    prog = glCreateProgram();
    vert = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vert, 1, &vs, NULL);
    glCompileShader(vert);
    glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
    std::cout << "Vertex shader " << (success ? "compiled" : "not compiled") << std::endl;

    frag = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(frag, 1, &fs, NULL);
    glCompileShader(frag);
    glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
    std::cout << "Fragment shader " << (success ? "compiled" : "not compiled") << std::endl;

    glAttachShader(prog, vert);
    glAttachShader(prog, frag);

    glLinkProgram(prog);
    glUseProgram(prog);

    glGetShaderiv(prog, GL_LINK_STATUS, &success);
    std::cout << "Program " << (success ? "linked" : "not linked") << std::endl;

    glDeleteShader(vert);
    glDeleteShader(frag);
    //Vertex stuff
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(1, &vbo);
    glGenBuffers(1, &ebo);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), 0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    //Texture stuff
    int width, height;
    unsigned char* texData = SOIL_load_image("brick.png", &width, &height, NULL, SOIL_LOAD_RGBA);

    glGenTextures(1, &texid);
    glBindTexture(GL_TEXTURE_2D, texid);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    if (texData) {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "Texture not loaded." << std::endl;
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    SOIL_free_image_data(texData);

    //Matrix stuff
    //Model matrix
    model = glm::mat4(1.0f);
    model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
    int modelMatrix = glGetUniformLocation(prog, "model");
    glUniformMatrix4fv(modelMatrix, 1, GL_FALSE, glm::value_ptr(model));
    //View matrix
    view = glm::mat4(1.0f);
    view = glm::translate(view, glm::vec3(0, 0, -3));
    int viewMatrix = glGetUniformLocation(prog, "view");
    glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(view));
    //Projection matrix, something is messing up here
    projection = glm::mat4(1.0f);
    projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
    int projectionMatrix = glGetUniformLocation(prog, "projection");
    glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, glm::value_ptr(projection));

}

void input(unsigned char key, int x, int y) {
    if (key == 'a') {
        model = glm::translate(model, glm::vec3(-0.5, 0, 0));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 'd') {
        model = glm::translate(model, glm::vec3(0.5, 0, 0));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 'w') {
        model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 's') {
        model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 'q') {

        model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0, 0, 1));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    if (key == 'e') {

        model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(0, 0, 1));
        int loc = glGetUniformLocation(prog, "model");
        glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
    }
    glutPostRedisplay();
}

int main(int argc, char* argv[]) {

    // Initialize GLUT
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("OBJ Viewer");
    glutReshapeFunc(changeViewPort);
    glutDisplayFunc(render);
    glutKeyboardFunc(input);
    GLenum err = glewInit();
    if (GLEW_OK != err) {
        fprintf(stderr, "GLEW error");
        return 1;
    }
    initGL();
    glutMainLoop();
    return 0;
}

共1个答案

匿名用户

不清楚你所说的半个坐标是什么意思,但是很清楚你想用一个绝对值来改变尺寸,而比例矩阵是相对于模型的。 实际上,您还应该考虑当模型不在原点周围时会发生什么--模型和原点之间的空间也是缩放的!

为了得到一个绝对的大小变化,我建议计算模型的边界框和所需的大小。 两者之比将进入尺度函数。 例如,如果模型的边界框是(20,10,5),而您希望它是(19.5,9.5,4.5),那么您需要scale(20/19.5,10/19.5,5/4.5)