Pregunta

Desde este sitio: http://www.toymaker.info/Games/html /vertex_shaders.html

Tenemos el siguiente fragmento de código:

// transformations provided by the app, constant Uniform data
float4x4 matWorldViewProj: WORLDVIEWPROJECTION;

// the format of our vertex data
struct VS_OUTPUT
{
  float4 Pos  : POSITION;
};

// Simple Vertex Shader - carry out transformation
VS_OUTPUT VS(float4 Pos  : POSITION)
{
  VS_OUTPUT Out = (VS_OUTPUT)0;
  Out.Pos = mul(Pos,matWorldViewProj);
  return Out;
}

Mi pregunta es: ¿por qué la estructura VS_OUTPUT tiene un vector de 4 dimensiones como su posición? ¿No es la posición solo x, y, z?

¿Fue útil?

Solución

Porque necesitas la coordenada w para el cálculo de la perspectiva. Después de que salga desde el sombreado de vértices, DirectX realiza una división de perspectiva dividiendo por w.

Esencialmente, si tiene 32768, -32768, 32768, 65536 como su posición de vértice de salida, luego de w divide obtiene 0,5, -0,5, 0,5, 1. En este punto, la w puede descartarse ya que ya no es necesaria. Esta información luego se pasa a través de la matriz de la ventana gráfica que la transforma en coordenadas 2D utilizables.

Editar: si observas cómo se realiza una multiplicación de matrices utilizando la matriz de proyección, puedes ver cómo se colocan los valores en los lugares correctos.

Tomando la matriz de proyección especificada en D3DXMatrixPerspectiveLH

2*zn/w  0       0              0
0       2*zn/h  0              0
0       0       zf/(zf-zn)     1
0       0       zn*zf/(zn-zf)  0

Y aplicándolo a un x aleatorio, y, z, 1 (Nota para una posición de vértice w siempre será 1) el valor de entrada de vértice obtiene lo siguiente

x' = ((2*zn/w) * x) + (0 * y) + (0 * z) + (0 * w)
y' = (0 * x) + ((2*zn/h) * y) + (0 * z) + (0 * w)
z' = (0 * x) + (0 * y) + ((zf/(zf-zn)) * z) + ((zn*zf/(zn-zf)) * w)
w' = (0 * x) + (0 * y) + (1 * z) + (0 * w)

Al instante puedes ver que w y z son diferentes. La coordenada w ahora solo contiene la coordenada z pasada a la matriz de proyección. z contiene algo mucho más complicado.

Entonces ... supongamos que tenemos una posición de entrada de (2, 1, 5, 1) tenemos un zn (Z-Near) de 1 y un zf (Z-Far de 10) y aw (ancho) de 1 y ah (altura) de 1.

Pasando estos valores a través de nosotros obtenemos

x' = (((2 * 1)/1) * 2
y' = (((2 * 1)/1) * 1
z' = ((10/(10-1)  * 5 + ((10 * 1/(1-10)) * 1)
w' = 5

expandiendo eso entonces obtenemos

x' = 4
y' = 2
z' = 4.4
w' = 5

Luego realizamos la división de la perspectiva final y obtenemos

x'' = 0.8
y'' = 0.4
z'' = 0.88
w'' = 1

Y ahora tenemos nuestra posición coordinada final. Esto supone que los rangos de x e y de -1 a 1 y los de z de 0 a 1. Como puede ver, el vértice está en pantalla.

Como bono extraño, puedes ver que si | x '| o | y '| o | z '| es más grande que | w '| o z 'es menor que 0 que el vértice está fuera de la pantalla. Esta información se utiliza para recortar el triángulo a la pantalla.

De todos modos, creo que esa es una respuesta bastante completa: D

Edit2: Recuerda que estoy usando matrices principales ROW. Las matrices principales de columnas están transpuestas.

Otros consejos

La rotación se especifica mediante una matriz tridimensional y la traducción mediante un vector. Puede realizar ambas transformaciones en un " único " Operación combinándolos en una sola matriz de 4 x 3:

rx1 rx2 rx3 tx1
ry1 ry2 ry3 ty1
rz1 rz2 rz3 tz1

Sin embargo, como esto no es cuadrado, hay varias operaciones que no se pueden realizar (inversión para una). Añadiendo una fila extra (que no hace nada):

0   0   0   1

todas estas operaciones son posibles (si no es fácil).

Como explica Goz en su respuesta haciendo que " 1 " un valor sin identidad, la matriz se convierte en una transformación de perspectiva.

El recorte es una parte importante de este proceso, ya que ayuda a visualizar lo que sucede con la geometría. La etapa de recorte esencialmente descarta cualquier punto en una primitiva que esté fuera de un cubo de 2 unidades centrado alrededor del origen (OK, tienes que reconstruir primitivas que están parcialmente recortadas pero eso no importa aquí).

Sería posible construir una matriz que mapeara directamente tus coordenadas espaciales del mundo a un cubo de este tipo, pero el movimiento gradual desde el plano lejano al plano cercano sería lineal. Es decir, un movimiento de un pie (hacia el espectador) cuando está a una milla del espectador causaría el mismo aumento de tamaño que un movimiento de un pie cuando está a varios pies de la cámara.

Sin embargo, si tenemos otra coordenada en nuestro vector (w), podemos dividir el vector por w, y nuestros primitivos no mostrarán el comportamiento anterior, pero aún podemos hacer que terminen dentro de los 2 -unidad del cubo de arriba.

Para obtener más información, consulte http://www.opengl.org /resources/faq/technical/depthbuffer.htm#0060 y http: // es .wikipedia.org / wiki / Transformation_matrix # Perspective_projection .

Una respuesta simple sería decir que si no le dice a la tubería qué es, entonces no le ha dado suficiente información sobre su proyección. Esto se puede verificar directamente sin comprender lo que hace la tubería con él ...

Como probablemente sepa, la matriz 4x4 se puede dividir en partes según lo que hace cada parte. La matriz de 3x3 en la parte superior izquierda se modifica cuando realiza operaciones de rotación o escala. La cuarta columna se altera cuando haces una traducción. Si alguna vez inspecciona una matriz de perspectiva, se altera la fila inferior de la matriz. Si luego observa cómo se realiza una multiplicación de Matriz-Vector, verá que la fila inferior de la matriz SOLO afecta al componente w resultante del vector. Por lo tanto, si no le dice al canalización w no tendrá toda su información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top