当我使用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;
}
不清楚你所说的半个坐标是什么意思,但是很清楚你想用一个绝对值来改变尺寸,而比例矩阵是相对于模型的。 实际上,您还应该考虑当模型不在原点周围时会发生什么--模型和原点之间的空间也是缩放的!
为了得到一个绝对的大小变化,我建议计算模型的边界框和所需的大小。 两者之比将进入尺度函数。 例如,如果模型的边界框是(20,10,5),而您希望它是(19.5,9.5,4.5),那么您需要scale(20/19.5,10/19.5,5/4.5)
。