我想了解使用矩陣的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
或者我會建議,從相機界面的水平,返回投影和模型視圖矩陣。當對照相機進行渲染時,您可以在現場計算其餘部分(例如:用於正常計算的轉置逆模型視圖)。 –
對於以正確的順序相乘矩陣,是的 - 你必須這樣做。但我不太清楚爲什麼這裏有一個問題 - 只需要按照獲得正確結果所需的順序將它們相乘即可。或者我錯過了一些難以做到的事情? –