Pergunta

A partir deste site: http://www.toymaker.info/Games/html /vertex_shaders.html

Temos o seguinte trecho 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;
}

A minha pergunta é: por que o struct VS_OUTPUT tenho um vetor dimensional 4 como a sua posição? não é justa posição x, y e z?

Foi útil?

Solução

Porque você precisa do w coordenadas para cálculo perspectiva. Depois de saída do shader de vértice do DirectX executa uma divisão perspectiva dividindo por w.

Essencialmente, se você tem 32768, -32768, 32768, 65536, como sua posição de vértice de saída depois de w divide você começa 0,5, -0,5, 0,5, 1. Neste ponto, o w pode ser descartada, uma vez que não é mais necessário. Esta informação é então passada através do visor de matriz que transforma a utilizáveis ??2D coordenadas.

Edit:. Se você olhar como uma multiplicação de matrizes é realizada utilizando a matriz de projeção você pode ver como os valores são colocados nos lugares corretos

Tendo a matriz de projecção especificado em 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

E aplicá-lo a um aleatória x, y, z, 1 (Nota para uma posição vértice w será sempre 1) valor de entrada vértice você obter o seguinte

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)

No mesmo instante você pode ver que W e Z são diferentes. O coordene w agora apenas contém a coordenada z passada para a matriz de projecção. z contém algo muito mais complicado.

.. Assim assumir que tem uma posição de entrada (2, 1, 5, 1) que tem uma Zn (Z-Perto) de 1 e um zf (Z-Extremo de 10) e aw (largura) de uma e ah (altura) de 1.

Passando esses valores através chegarmos

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

expansão que, em seguida, obter

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

Em seguida, executar divisão perspectiva final e temos

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

E agora temos a nossa posição final de coordenadas. Isso pressupõe que x e y varia entre -1 e 1 e gamas z de 0 a 1. Como se pode ver o vértice está na tela.

Como um bônus bizarra que você pode ver que se | x '| ou | y '| ou | z '| é maior do que | w '| ou Z' é menor do que 0 que o vértice está fora da tela. Esta informação é usada para desviar o triângulo para a tela.

De qualquer forma eu acho que isso é uma resposta bastante abrangente: D

Edit2: Esteja avisado que eu estou usando ROW principais matrizes. Coluna principais matrizes são transpostas.

Outras dicas

A rotação é especificada por uma matriz dimensional 3 e tradução por um vector. Você pode executar ambos os transforma em uma operação "single", combinando-os em uma única matriz 4 x 3:

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

No entanto, como isso não é praça há várias operações que não podem ser executadas (inversão para um). Ao adicionar uma linha extra (que não faz nada):

0   0   0   1

todas estas operações se possível (se não é fácil).

Como Goz explica em sua resposta, fazendo o "1" um valor diferente de identidade a matriz torna-se uma transformação de perspectiva.

Clipping é uma parte importante deste processo, uma vez que ajuda a visualizar o que acontece com a geometria. O estágio recorte essencialmente devoluções qualquer ponto de uma primitiva que está fora de um 2-unidade de cubo centrado em torno da origem (OK, você tem que reconstruir primitivos que são parcialmente cortadas, mas que não importa aqui).

Seria possível construir uma matriz que mapeada diretamente suas coordenadas espaciais mundiais para tal um cubo, mas o movimento gradual do plano até ao plano próximo, seria linear. Isso quer dizer que um movimento de um pé (para o visor) quando uma milha de distância do espectador causaria o mesmo aumento no tamanho como um movimento de um dos pés quando vários pés da câmera.

No entanto, se temos outra coordenadas no nosso vector (w), podemos dividir o vetor componente-wise por w, e os nossos primitivos não exibirão o comportamento acima, mas ainda podemos torná-los acabar dentro do 2 cubo -unit acima.

Para mais explicações ver http://www.opengl.org /resources/faq/technical/depthbuffer.htm#0060 e http: // en .wikipedia.org / wiki / Transformation_matrix # Perspective_projection .

Uma resposta simples seria dizer que se você não diga o gasoduto que w é, então você não ter dado informações suficientes sobre a sua projeção. Isto pode ser verificado diretamente sem entender o que o gasoduto faz com ele ...

Como você provavelmente sabe a matriz 4x4 pode ser dividido em partes com base no que cada parte faz. A matriz 3x3 no canto superior esquerdo é alterada quando você faz operações de rotação ou escala. A quarta coluna é alterada quando você faz uma tradução. Se você sempre inspecionar uma matriz perspectiva, ele altera a linha inferior da matriz. Se você, em seguida, olhar como uma multiplicação matriz-vetor é feito, você vê que a linha inferior da matriz afeta apenas a resultante w componente do vetor. Então, se você não contar o gasoduto sobre w não terá todas as suas informações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top