O sistema de coordenadas OpenGL é canhoto ou destro?

87

Estou tentando entender o sistema de coordenadas OpenGL. No entanto, alguns tutoriais dizem que o sistema de coordenadas padrão é canhoto (consulte http://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ) e outros dizem que é destro (consulte http: // www .falloutsoftware.com / tutorials / gl / gl0.htm ). Qual é correto? Eu entendo que podemos transformar um ao outro por espelhamento, mas gostaria de saber as coordenadas padrão.

341008
fonte
3
Isso não depende inteiramente de como você escreve suas transformações nos shaders e, portanto, depende inteiramente de você?
jcoder
Apenas meus dois centavos evl.uic.edu/ralph/508S98/coordinates.html , tem algumas imagens autoexplicativas.
rraallvv
Suponho que você não considere atualizar sua resposta aceita.
Jonathan Mee

Respostas:

132

Existe alguma confusão aqui.

insira a descrição da imagem aqui

OpenGL é destro no espaço do objeto e no espaço do mundo.

Mas no espaço da janela (também conhecido como espaço da tela), de repente, somos canhotos .

Como isso aconteceu ?

A forma como passamos de destros para canhotos é uma entrada de escala z negativa nas matrizes de projeção glOrthoou glFrustum. Escalar z por -1 (enquanto deixa xey como estavam) tem o efeito de alterar a destreza do sistema de coordenadas.

Para glFrustum,

insira a descrição da imagem aqui insira a descrição da imagem aqui

longe e perto devem ser positivos, com muito > perto . Diga distante = 1000 e próximo = 1. Então C = - (1001) / (999) = -1,002.

Veja aqui mais detalhes e diagramas.

De uma perspectiva ortográfica , glOrtho gera uma matriz como esta:

insira a descrição da imagem aqui

Aqui, esquerda , direita , inferior e superior são apenas as coordenadas para os planos de recorte vertical esquerdo , vertical direito , horizontal inferior , horizontal superior (resp) .

Os planos próximos e distantes , entretanto, são especificados de forma diferente . o próximo parâmetro é definido como

  • Perto: a distância até o plano de corte de profundidade mais próximo. Esta distância é negativa se o avião estiver atrás do observador.

e longe:

  • zFar a distância até o plano de corte de profundidade mais distante. Esta distância é negativa se o avião estiver atrás do observador.

Aqui temos um volume típico de visualização canônica

canônico

Como o multiplicador z é (-2 / (muito perto)), o sinal de menos escala z por -1 . Isso significa que "z" é virado para a esquerda durante a transformação da visualização, sem o conhecimento da maioria das pessoas, pois elas simplesmente funcionam no OpenGL como um sistema de coordenadas "destro".

Então, se você ligar

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

Então o NEAR PLANE está 10 unidades à sua frente . Onde você está? Por que, na origem, com o eixo x à sua direita, o eixo y no topo da sua cabeça e seu nariz apontando para baixo do eixo z negativo (esse é o padrão "Por padrão, a câmera está situada na origem , aponta para baixo o eixo z negativo e tem um vetor superior de (0, 1, 0). " ). Portanto, o plano próximo está em z = -10. O plano distante está 10 unidades atrás de você, em z = + 10 .

bobobobo
fonte
1
"o vetor direto é negado em gluLookAt" - você pode confirmar se é esse o caso? Não é gluPerspective ou glFrustum ou glOrtho?
Kos
1
De repente, somos canhotos do espaço do clipe em diante, não apenas do espaço da janela.
legends2k
3
+1 para a resposta inteira, -1 (espere, em vez de -2) para "A forma como passamos da mão direita para a esquerda é porque o vetor progressivo é negado na implementação padrão de gluLookAt (), que é a função todo mundo usa para criar a matriz de visualização. Quando você nega o vetor progressivo, isso tem o efeito de alterar a destreza do sistema de coordenadas. " , que é mero lixo ...
Christian Rau
2
... Negar o vetor progressivo na gluLookAtcomputação não tem nada a ver com mudar a destreza do espaço de coordenadas, é assim que esta matriz é calculada (e na verdade + z é de fato "para trás" no espaço destro). gluLookAtnada mais faz do que calcular uma transformação de corpo rígido comum (rotação + translação) no espaço da mão direita. São as matrizes de projeção usadas pelo pipeline de função fixa (e geralmente por sombreadores também) que realizam a mudança real de lateralidade em sua negação do componente z, como você já observou em sua resposta.
Christian Rau
2
@bobobobo Você está dizendo que se calcular sua matriz de visualização usando apenas funções de rotação e translação (o que eu acho que você não acusaria de mudar a destreza), em vez de gluLookAt, não haveria uma mudança de base enquanto gluLookAtisso ocorre? Definitivamente não (já que você provavelmente sabe que nem "todo mundo" usa gluLookAtpara cálculo de matriz de visão), já que, como você deve saber gluLookAt, nada mais faz do que um monte de chamadas de rotação e tradução (mesmo que disfarçadas como a mudança de termo de " alto nível" base " ) com absolutamente nenhum reflexo envolvido.
Christian Rau
26

Por padrão, o Normalized Device Coordinate é canhoto.

O glDepthRange é por padrão [0, 1] (próximo, distante) fazendo com que o eixo + z aponte para a tela e com + x para a direita e + y para cima, é um sistema para canhotos.

Alterar o intervalo de profundidade para [1, 0] tornará o sistema destro.

Citando uma resposta anterior de Nicol : (o tachado é meu trabalho, explicado abaixo)

Estou surpreso que ninguém tenha mencionado algo: o OpenGL também funciona em um sistema de coordenadas para canhotos. Pelo menos, isso acontece quando você está trabalhando com sombreadores e usa o intervalo de profundidade padrão.

Depois de descartar o pipeline de função fixa, você lida diretamente com o "espaço do clipe". A especificação OpenGL define o espaço do clipe como um sistema de coordenadas homogêneo 4D. Quando você segue as transformações por meio de coordenadas de dispositivo normalizadas e até o espaço da janela, você encontra isso.

O espaço da janela está no espaço dos pixels de uma janela. A origem está no canto esquerdo inferior, com + Y indo para cima e + X indo para a direita. Isso se parece muito com um sistema de coordenadas para destros. Mas e quanto ao Z?

O intervalo de profundidade padrão (glDepthRange) define o valor próximo de Z como 0 e o valor distante de Z como um . Portanto, o + Z está se afastando do visualizador.

Esse é um sistema de coordenadas para canhotos. Sim você podemude o teste de profundidade de GL_LESS para GL_GREATER ealtere glDepthRange de [0, 1] para [1, 0]. Mas o estado padrão do OpenGL é trabalhar em um sistema de coordenadas para canhotos . E nenhuma das transformações necessárias para chegar ao espaço da janela a partir do espaço do clipe nega o Z. Então, o espaço do clipe, a saída do sombreador de vértice (ou geometria) é um espaço para a mão esquerda (meio. É um espaço homogêneo 4D, então é difícil definir a destreza).

No pipeline de função fixa, todas as matrizes de projeção padrão (produzidas por glOrtho, glFrustum e similares) se transformam de um espaço para destros em um para canhotos . Eles invertem o significado de Z; basta verificar as matrizes que geram. No espaço ocular, + Z se move em direção ao visualizador; no espaço de pós-projeção, ele se afasta.

Suspeito que a Microsoft (e o GLide) simplesmente não se preocuparam em realizar a negação em suas matrizes de projeção.

Eu acertei uma parte, pois divergia de minhas descobertas.

Alterar DepthRange ou DepthFunc e usar ClearDepth (0) funciona, mas ao usar ambos eles cancelam um ao outro de volta para um sistema canhoto.

hultqvist
fonte
O intervalo de profundidade não pode ser [1, -1]. Acho que você quis dizer [1, 0]. Além disso, isso foi apontado antes .
Nicol Bolas
Sua resposta é ótima, uma pena que é para uma pergunta sobre DirectX, você deve postá-la aqui!
hultqvist
3
@SigTerm, por que você acha que corrigir uma afirmação falsa não vale a pena? Passei várias horas solucionando problemas de coordenadas de vértice e geração de rotação de matriz apenas para descobrir que o sistema de coordenadas padrão, na verdade, não era destro.
hultqvist
1
A questão era se era um sistema para canhotos ou destros. Essa resposta tem mais detalhes do que isso, explicando duas outras maneiras de obtê-la com a mão direita. Adicionar -1 em uma transformação de matriz é outra maneira de fazer isso. Mas nada disso importa se você acredita que o sistema é destro por padrão, você só pode mudar algo se souber do que está mudando. Ainda
hultqvist
1
Achei a resposta muito esclarecedora e apareceu em pesquisas, então valeu a pena para mim.
Aprenda OpenGL ES
13

SOMENTE NDC

Você deve apenas notar que OpenGL só conhece NDC! e esse é um sistema de coordenadas para canhotos.

Não importa o sistema de coordenadas que você usa - sistema de coordenadas de eixo para canhotos ou destros - todos precisam ser espelhados para NDC. Se quiser, você pode lidar totalmente com o espaço-mundo como um sistema de coordenadas para canhotos.

Por que geralmente usamos o sistema de coordenadas para destros no espaço mundial?

Eu acho que é convencional. Simplesmente faz. Talvez ele apenas queira fazer uma distinção do DirectX.

ZK_
fonte
3
Acho que isso não se repete o suficiente. Todos esses diagramas que mostram "transformação de modelagem", "transformação de visualização" e "transformação de perspectiva" falham em mostrar que não são uma parte intrínseca do OpenGL. Você pode até fazer todas as suas transformações manualmente, com ou sem shaders, com ou sem matrizes.
Tom
3
Pode ser melhor repeti-lo para incluir as palavras "coordenadas normalizadas do dispositivo".
Tommy,
6
O OpenGL antecede o DirectX em alguns anos, então o OpenGL certamente não estava tentando se diferenciar do DirectX. O principal desenvolvedor do DirectX, Alex St. John, disse que a decisão da Microsoft de optar por um sistema de coordenadas para canhotos foi "em parte por preferência pessoal" e "uma escolha arbitrária".
Chris Nolet de
Isso não é inteiramente correto. OpenGL também conhece o sistema de coordenadas de recorte, uma vez que o recorte acontece nele. O sistema de coordenadas do clipe tem a mesma destreza que o sistema de coordenadas NDC embora.
plasmacel
7

O livro "WebGl Programming Guide" de Kouichi Matsuda gasta quase dez páginas em "WebGl / OpenGl: Left or Right Handed?"

De acordo com o livro:

  • Na prática, a maioria das pessoas usa um sistema destro

  • OpenGl na verdade é um sistema para canhotos internamente

  • Internamente, mais profundamente, não é nenhum dos dois. No fundo, o OpenGl não se preocupa com o valor z. A ordem em que você desenha as coisas determina o que é desenhado no topo (desenhe um triângulo primeiro, depois um quad, o quad substitui o triângulo).

Não concordo totalmente com o "não é nenhum dos dois", mas essa é provavelmente uma questão filosófica de qualquer maneira.

Heinzlmaen
fonte
7
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). Isso é verdade, na ausência de testes de profundidade. Na presença de teste de profundidade, o valor z de um fragmento é comparado com o valor no buffer de profundidade, e o fragmento descartado se falhar no teste de profundidade, então o quad pode ou não sobrescrever o triângulo dependendo de suas profundidades e função de profundidade usada.
chrisvarnz
3

Opengl é definitivamente canhoto. Você vê muitos tutoriais afirmando o oposto porque eles estão negando o valor z na matriz de projeção. Quando os vértices finais são calculados dentro do sombreador de vértice, ele converte os vértices que você passa do lado do cliente (coord à direita) para o canhoto, e os vértices são passados ​​para o sombreador de geometria e o sombreador de fragmento. Se você usar o sistema de coordenadas da mão direita no lado do cliente, Opengl não se importa. Ele conhece apenas o sistema de coordenadas normalizado, que é canhoto.

Edit: Se você não confia em mim, experimente em seu sombreador de vértice adicionando uma matriz de tradução e você poderá ver facilmente se Opengl é canhoto ou não.

ForeignDevil
fonte
0

Usando as funções de projeção e transformação integradas do OpenGL, observar os movimentos na tela segue as regras do sistema de coordenadas para destros . Por exemplo, se um objeto na frente de sua visualização for transladado na direção z positiva, o objeto se moverá em sua direção.

O buffer de profundidade é exatamente o oposto, e é aqui que as NDC (Normalized Device Coordinates) entram em jogo. Se passar GL_LESS para o glDepthFunc significa que os pixels serão desenhados quando estiverem mais próximos de você do que o que já está no buffer de profundidade, então os pixels são considerados como vivendo em um sistema de coordenadas para canhotos .

Há mais um sistema de coordenadas e essa é a janela de visualização! O sistema de coordenadas da janela de visualização é tal que + x aponta para a direita e + y aponta para baixo. Eu acho que neste ponto a lateralidade é discutível, já que estamos lidando apenas com x, y neste ponto.

Por último, gluLookAt sob o capô tem que negar o vetor de visualização. Uma vez que a matemática assume que um vetor está apontando em uma direção positiva em direção ao objeto que está olhando e uma câmera olha para baixo -z, o vetor de olhar deve ser negado para que se alinhe com a câmera.

Algo para mastigar. Não faz muito sentido chamar a direção z de um sistema de coordenadas para destros de vetor direto :). Acho que a Microsoft percebeu isso quando projetou o Direct3D.

Weatx
fonte