tutorial - opengl c++ windows
ConfusiĆ³n entre el orden de matriz de C++ y OpenGL(row-major vs column-major) (3)
Estás lidiando con dos problemas separados.
Primero, sus ejemplos se refieren al diseño de la memoria. Su matriz [4] [4] es principal de fila porque ha utilizado la convención establecida por las matrices multidimensionales C para que coincida con su matriz lineal.
El segundo problema es una cuestión de convención sobre cómo interpretas las matrices en tu programa. glUniformMatrix4fv se usa para establecer un parámetro de sombreado. Si su transformación se calcula para un vector de fila o una transformación de vector de columna es una cuestión de cómo utiliza la matriz en su código de sombreado. Como dices que necesitas usar vectores de columna, supongo que tu código de sombreado usa la matriz A y un vector de columna x para calcular x '' = A x .
Yo diría que la documentación de glUniformMatrix es confusa. La descripción del parámetro transponer es una manera realmente indirecta de decir que la matriz está transpuesta o no. OpenGL solo está transportando esos datos a su sombreador, ya sea que desee transponerlo o no es una cuestión de convención que debe establecer para su programa.
Este enlace tiene una buena discusión adicional: http://steve.hollasch.net/cgindex/math/matrix/column-vec.html
Estoy completamente confundido sobre las definiciones de la matriz. Tengo una clase de matriz, que contiene un float[16]
que asumí que es fila mayor, en base a las siguientes observaciones:
float matrixA[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
float matrixB[4][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 8, 9, 10, 11 }, { 12, 13, 14, 15 } };
matrixA
y matrixB
tienen el mismo diseño lineal en la memoria (es decir, todos los números están en orden). De acuerdo con http://en.wikipedia.org/wiki/Row-major_order esto indica un diseño de fila mayor.
matrixA[0] == matrixB[0][0];
matrixA[3] == matrixB[0][3];
matrixA[4] == matrixB[1][0];
matrixA[7] == matrixB[1][3];
Por lo tanto, matrixB[0]
= fila 0, matrixB[1]
= fila 1, etc. De nuevo, esto indica el diseño principal de fila.
Mi problema / confusión surge cuando creo una matriz de traducción que se ve así:
1, 0, 0, transX
0, 1, 0, transY
0, 0, 1, transZ
0, 0, 0, 1
Que se presenta en la memoria como, { 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }
.
Luego, cuando llamo a glUniformMatrix4fv , necesito establecer el indicador de transposición en GL_FALSE, lo que indica que es column-major, de lo contrario las transformaciones como translate / scale etc. no se aplican correctamente:
Si la transposición es GL_FALSE, se supone que cada matriz se suministrará en orden principal de columna. Si la transposición es GL_TRUE, se supone que cada matriz se suministrará en orden principal de fila.
¿Por qué mi matriz, que parece ser una fila principal, debe pasarse a OpenGL como column-major?
Para resumir las respuestas de SigTerm y dsharlet: La forma habitual de transformar un vector en GLSL es multiplicar por la izquierda el vector por la matriz de transformación:
mat4 T; vec4 v; vec4 v_transformed;
v_transformed = T*v;
Para que esto funcione, OpenGL espera que el diseño de la memoria de T
, tal como lo describe SigTerm,
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }
que también se llama ''columna principal''. En su código de sombreado (como lo indican sus comentarios), sin embargo, usted multiplicó el vector a la derecha por la matriz de transformación:
v_transformed = v*T;
que solo produce el resultado correcto si T
se transpone, es decir, tiene el diseño
{ 1, 0, 0, transX, 0, 1, 0, transY, 0, 0, 1, transZ, 0, 0, 0, 1 }
(es decir, ''fila principal''). Como ya proporcionó el diseño correcto para su sombreador, es decir, fila principal, no fue necesario configurar el indicador de transpose
de glUniform4v
.
la notación de matriz utilizada en la documentación de OpenGL no describe el diseño en memoria para matrices OpenGL
Si crees que será más fácil si olvidas o te olvidas de todo el asunto "fila / columna-principal". Esto se debe a que, además de la fila / columna principal, el programador también puede decidir cómo desearía disponer la matriz en la memoria (si los elementos adyacentes forman filas o columnas), además de la notación, lo que aumenta la confusión.
Las matrices OpenGL tienen el mismo diseño de memoria que las matrices directx .
x.x x.y x.z 0
y.x y.y y.z 0
z.x z.y z.z 0
p.x p.y p.z 1
o
{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }
x, y, z son vectores de 3 componentes que describen el sistema de coordenadas de la matriz (sistema de coordenadas local dentro del sistema de coordenadas global).
p es un vector de 3 componentes que describe el origen del sistema de coordenadas de la matriz.
Lo que significa que la matriz de traducción debe estar dispuesta en una memoria como esta:
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.
Déjalo así, y el resto debería ser fácil.
--- cita de un antiguo FAQ de OpenGL--
9.005 ¿Las matrices OpenGL son column-major o row-major?
Para propósitos de programación, las matrices OpenGL son matrices de 16 valores con vectores base establecidos contiguamente en la memoria. Los componentes de traducción ocupan los elementos 13º, 14º y 15º de la matriz de 16 elementos, donde los índices están numerados del 1 al 16, como se describe en la sección 2.11.2 de la Especificación 2.1 de OpenGL.
Column-major versus row-major es puramente una convención de notación. Tenga en cuenta que la post-multiplicación con matrices de columna mayor produce el mismo resultado que la multiplicación previa con matrices de fila mayor. La especificación de OpenGL y el manual de referencia de OpenGL usan la notación de columna principal. Puedes usar cualquier notación, siempre y cuando esté claramente indicado.
Lamentablemente, el uso del formato de columna principal en la especificación y el libro azul ha resultado en una confusión interminable en la comunidad de programación OpenGL. La notación de la columna principal sugiere que las matrices no se presentan en la memoria como lo esperaría un programador.