使用 glUniformMatrix4fv() 用新矩阵更新旧矩阵?

Updating old matrix with new one using glUniformMatrix4fv()?

本文关键字:更新 新矩阵 glUniformMatrix4fv 使用      更新时间:2023-10-16

我有一个问题,当我从 WebGL 过渡到 OpenGL 时,当我想用键操作翻译对象时,它开始变得令人生畏,问题是当我想进行新的翻译时,应该更新新矩阵,并且提供给顶点着色器(统一u_matrix)的数据也应该更改, 但事实并非如此。

为了展示这个问题,我让它更简单,我用平移矩阵画一次,在 sleep(2) 之后,我再次画一次,但用不同的平移矩阵再睡 2 秒钟才能看到结果,问题是矩阵在第二阶段根本没有更新,根本没有变化。

matC.translate(nb1, nb2, nb2) 通过返回指向存储在堆栈上的 16' 值 1D 数组的第一个值的指针来很好地工作。

#include <GL/glew.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <assert.h>
#include <unistd.h>
#include "./../Matrix/main.cpp";
using namespace std;
GLuint prog_hdlr;
GLint   a_position;
const int SCREEN_WIDTH  = 1024;
const int SCREEN_HEIGHT = 1024;
// float * translation = matC.translation(0.2, 0, 0);
// float * rotationX;
// float * rotationY;
// float * rotationZ;
// float translate = 0.01;
// float * tab4 = matC.multiplyMatrices(tab1, tab2);
static unsigned int CompileShader(unsigned int type, const string& source) {
unsigned int id = glCreateShader(type);
cout << source.c_str() << endl;
const char * src = source.c_str();
glShaderSource(id, 1, &src, NULL);
glCompileShader(id);
int result; 
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if(result == GL_FALSE) {
std::cout << "failed to compile shader" << std::endl;
GLint maxLength = 0;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &maxLength);
vector<GLchar> errorLog(maxLength);
glGetShaderInfoLog(id, maxLength, &maxLength, &errorLog[0]);
int iter;
for (vector<GLchar>::const_iterator iter = errorLog.begin(); iter != errorLog.end(); ++iter)
cout << *iter;
glDeleteShader(id);
}
return id;
}
static int CreateProgram(const string& vertexShader, const string& fragmentShader) {
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDetachShader(program,vs);
glDetachShader(program,fs);
glDeleteShader(vs); 
glDeleteShader(fs);
return program;
}
void input(GLFWwindow * window, int key, int action, int u, int i) {
// switch(key) {
//    case GLFW_KEY_W : {
//       translate += 0.1;
//       translation = matC.translation(translate, 0, 0);
//    };
//    case GLFW_KEY_A : {
//    };
//    case GLFW_KEY_S : {
//       translate -= 0.1;
//       translation = matC.translation(translate, 0, 0);
//    };
//    case GLFW_KEY_D : {
//    };
// };
}
int main(int argc, char * argv) {
glutInit(&argc, &argv);
GLFWwindow * window;
cout << glGetString(GL_VERSION) << endl;
if(!glfwInit())
return -1;
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Triangle rendering", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if(glewInit() != GLEW_OK) {
std::cout << "error..!!" << std::endl;
}
float positions[108] = {
-0.5f, -0.5f, 0.0f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, -1.0f, -0.5f, 0.5f, -1.0f, 0.5f, 0.5f, -1.0f,
0.5f, 0.5f, -1.0f, 0.5f, -0.5f, -1.0f, -0.5f, -0.5f, -1.0f,
-0.5f, -0.5f, 0.0f, -0.5f, 0.5f, 0.0f, -0.5f, 0.5f, -1.0f,
-0.5f, 0.5f, -1.0f, -0.5f, -0.5f, -1.0f, -0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f, 0.5f, 0.5f, -1.0f, 0.5f, 0.5f, 0.0f,
0.5f, 0.5f, -1.0f, 0.5f, -0.5f, 0.0f, 0.5f, -0.5f, -1.0f,
-0.5f, 0.5f, 0.0f, 0.5f, 0.5f, -1.0f, -0.5f, 0.5f, -1.0f,
0.5f, 0.5f, -1.0f, -0.5f, 0.5f, 0.0f, 0.5f, 0.5f, 1.0f, 
-0.5f, -0.5f, 0.0f, -0.5f, -0.5f, -1.0f, 0.5f, -0.5f, -1.0f,
0.5f, -0.5f, -1.0f, 0.5f, -0.5f, 1.0f, -0.5f, -0.5f, 0.0f
};
float colors[108] = {
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,  1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};
string vertexShader = R"(
#version 130
attribute vec4 a_position;
attribute vec3 a_color;
varying vec3 v_color;
uniform mat4 u_matrix;
void main() {
mat4 a_matrix;
a_matrix = mat4(1.0f);
vec4 pos = u_matrix*a_position;
gl_Position = vec4(pos.xyz, 1.0);
v_color = a_color;
}
)";
string fragmentShader = R"(
#version 130
varying vec3 v_color;
void main() {
gl_FragColor = vec4(v_color, 1.0);
}
)";

unsigned int program = CreateProgram(vertexShader, fragmentShader);
glUseProgram(program);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
GLint attributePositionLocation = glGetAttribLocation(program, "a_position");
GLint uniformMatrixLocation = glGetUniformLocation(program, "u_matrix");
GLint attributeColorLocation = glGetAttribLocation(program, "a_color");
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 108*sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(attributePositionLocation);
glVertexAttribPointer(attributePositionLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);
unsigned int bufferColor;
glGenBuffers(1, &bufferColor);
glBindBuffer(GL_ARRAY_BUFFER, bufferColor);
glBufferData(GL_ARRAY_BUFFER, 108*sizeof(float), colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(attributeColorLocation);
glVertexAttribPointer(attributeColorLocation, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glfwSetKeyCallback(window, input);
// while(!glfwWindowShouldClose(window)) {
//     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//     glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, translation);
//     glDrawArrays(GL_TRIANGLES, 0, 36);
//     glfwSwapBuffers(window);
//     glfwPollEvents();
// }
Matrix matC = Matrix();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, matC.translation(0.5, 0.5, 0));
glDrawArrays(GL_TRIANGLES, 0, 36);
glfwSwapBuffers(window);
glfwPollEvents();
sleep(2);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(uniformMatrixLocation, 1, GL_FALSE, matC.translation(-0.5, -0.5, 0));
glDrawArrays(GL_TRIANGLES, 0, 36);
glfwSwapBuffers(window);
glfwPollEvents();
sleep(2);
glfwTerminate();
return 0;
}

在WebGL中,它可以完美地工作:

function drawScene(gl) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.uniformMatrix4fv(whateverMatrixLocation, false, whateverMatrix);
gl.drawArrays(gl.TRIANGLES, 0, whateverNumber);
requestAnimationFrame(drawScene.bind(this, gl));
}

我做错了什么?我使用的是 GLSL 版本 1.3...?

编辑:

class Matrix {
public:
Matrix() {};
static float * translation(float x, float y, float z) {
static float tab[16] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1
};
return tab;
}
}

static初始值设定项只运行一次,而不是每次都通过函数运行。 您可以通过以下方式每次切换到std::array并分配新值:

class Matrix
{
public:
float* translation( float x, float y, float z )
{
static std::array< float, 16 > tab;
tab =
{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1
};
return tab.data();
}
};

或者使用 GLM :)