我想了解使用矩阵的opengl中的摄像头。OpenGL模型,视图,投影矩阵
我写了一个简单的着色器,看起来像这样:
#version 330 core
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec4 a_col;
uniform mat4 u_mvp_mat;
uniform mat4 u_mod_mat;
uniform mat4 u_view_mat;
uniform mat4 u_proj_mat;
out vec4 f_color;
void main()
{
vec4 v = u_mvp_mat * vec4(0.0, 0.0, 1.0, 1.0);
gl_Position = u_mvp_mat * vec4(a_pos, 1.0);
//gl_Position = u_proj_mat * u_view_mat * u_mod_mat * vec4(a_pos, 1.0);
f_color = a_col;
}
这是一个有点冗长,但那是因为我测试通过无论是在模型,视图或投影矩阵,做乘法的GPU或者在cpu上进行乘法运算并传入mvp矩阵,然后执行mvp *位置矩阵乘法。
据我所知,后者可以提供性能提升,但绘制1个quad我并没有在这一点上看到任何性能问题。
现在我使用此代码从我的着色器中获取位置并创建模型视图和投影矩阵。
pos_loc = get_attrib_location(ce_get_default_shader(), "a_pos");
col_loc = get_attrib_location(ce_get_default_shader(), "a_col");
mvp_matrix_loc = get_uniform_location(ce_get_default_shader(), "u_mvp_mat");
model_mat_loc = get_uniform_location(ce_get_default_shader(), "u_mod_mat");
view_mat_loc = get_uniform_location(ce_get_default_shader(), "u_view_mat");
proj_matrix_loc =
get_uniform_location(ce_get_default_shader(), "u_proj_mat");
float h_w = (float)ce_get_width() * 0.5f; //width = 320
float h_h = (float)ce_get_height() * 0.5f; //height = 480
model_mat = mat4_identity();
view_mat = mat4_identity();
proj_mat = mat4_identity();
point3* eye = point3_new(0, 0, 0);
point3* center = point3_new(0, 0, -1);
vec3* up = vec3_new(0, 1, 0);
mat4_look_at(view_mat, eye, center, up);
mat4_translate(view_mat, h_w, h_h, -20);
mat4_ortho(proj_mat, 0, ce_get_width(), 0, ce_get_height(), 1, 100);
mat4_scale(model_mat, 30, 30, 1);
mvp_mat = mat4_identity();
之后我设置我的vao和vbo的然后准备做渲染。
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(ce_get_default_shader()->shader_program);
glBindVertexArray(vao);
mvp_mat = mat4_multi(mvp_mat, view_mat, model_mat);
mvp_mat = mat4_multi(mvp_mat, proj_mat, mvp_mat);
glUniformMatrix4fv(mvp_matrix_loc, 1, GL_FALSE, mat4_get_data(mvp_mat));
glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, mat4_get_data(model_mat));
glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, mat4_get_data(view_mat));
glUniformMatrix4fv(proj_matrix_loc, 1, GL_FALSE, mat4_get_data(proj_mat));
glDrawElements(GL_TRIANGLES, quad->vertex_count, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
假设所有矩阵数学是正确的,我想抽象视图和投影矩阵出到照相机结构以及模型矩阵为精灵结构体,这样我可以避免所有这些矩阵数学和使事情更容易使用。
该矩阵乘法的顺序是:
Projection * View * Model * Vector
所以当精灵保持模型矩阵相机将持有投影和视图矩阵。
然后在将数据发送到GPU进行矩阵乘法之前,先进行所有相机转换和精灵转换。
如果我记得矩阵乘法不可交换所以 view * projection * model
会导致错误的结果矩阵。
伪代码
glClearxxx(....);
glUseProgram(..);
glBindVertexArray(..);
mvp_mat = mat4_identity();
proj_mat = camera_get_proj_mat();
view_mat = camera_get_view_mat();
mod_mat = sprite_get_transform_mat();
mat4_multi(mvp_mat, view_mat, mod_mat); //mvp holds model * view
mat4_multi(mvp_mat, proj_mat, mvp_mat); //mvp holds proj * model * view
glUniformMatrix4fv(mvp_mat, 1, GL_FALSE, mat4_get_data(mvp_mat));
glDrawElements(...);
glBindVertexArray(0);
那是一个高性能的方式去这样做是可扩展的?
我明白了你的可扩展性,它确实有道理。还有一个问题。假设我喜欢你的建议,并让相机返回一个视图*投影矩阵,然后不会乘以模型矩阵产生错误的结果,因为它会说'model * proj * view',这不是正确的方法做矩阵乘法。我想有可能将模型矩阵传递给相机,并让它做正确的事情,但这样会使精灵系列非常靠近相机,不是吗? – user1610950
或者我会建议,从相机界面的水平,返回投影和模型视图矩阵。当对照相机进行渲染时,您可以在现场计算其余部分(例如:用于正常计算的转置逆模型视图)。 –
对于以正确的顺序相乘矩阵,是的 - 你必须这样做。但我不太清楚为什么这里有一个问题 - 只需要按照获得正确结果所需的顺序将它们相乘即可。或者我错过了一些难以做到的事情? –