문제

이 사이트에서: http://www.toymaker.info/Games/html/vertex_shaders.html

다음과 같은 코드 조각이 있습니다.

// 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;
}

내 질문은 다음과 같습니다VS_OUTPUT 구조체의 위치가 4차원 벡터인 이유는 무엇입니까?위치는 단지 x, y, z가 아닌가요?

도움이 되었습니까?

해결책

원근 계산을 위해서는 w 좌표가 필요하기 때문입니다. Directx보다 정점 셰이더에서 출력 한 후에는 w로 나누어 관점을 분할합니다.

본질적으로 출력 정점 위치로 32768, -32768, 32768, 65536이있는 경우 W 분할 후 0.5, -0.5, 0.5, 1이됩니다.이 시점에서 W는 더 이상 필요하지 않기 때문에 폐기 할 수 있습니다. 그런 다음이 정보는 뷰포트 매트릭스를 통해 전달되어 사용 가능한 2D 좌표로 변환합니다.

편집 : 투영 행렬을 사용하여 매트릭스 곱셈을 수행하는 방법을 살펴보면 값이 올바른 위치에 어떻게 배치되는지 확인할 수 있습니다.

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

그리고 임의의 x, y, z, 1에 적용하면 (정점 위치 w는 항상 1) 정점 입력 값을 얻을 수 있습니다.

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)

즉시 W와 Z가 다르다는 것을 알 수 있습니다. w 코드는 이제 전달 된 z 좌표가 투사 행렬에 전달됩니다. Z에는 훨씬 더 복잡한 것을 포함합니다.

그래서 .. 우리는 (2, 1, 5, 1)의 입력 위치가 1과 zf (z-far 10)와 1 및 ah의 aw (너비)가 있다고 가정합니다. 높이) 1.

우리는이 값을 통과시킵니다

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

우리가 얻는 확장

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

그런 다음 최종 관점 분할을 수행하면 얻습니다

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

그리고 이제 우리는 최종 좌표 위치를 가지고 있습니다. 이것은 x와 y 범위가 -1에서 1 사이이며 z는 0에서 1 사이의 범위를 가정합니다.

기괴한 보너스로 | x '| 또는 | y '| 또는 | z '| | w '|보다 큽니다 또는 z '는 정점이 화면 오프 스크린 인 것보다 0보다 작습니다. 이 정보는 삼각형을 화면에 클리핑하는 데 사용됩니다.

어쨌든 나는 그것이 꽤 포괄적 인 대답이라고 생각합니다 : D

edit2 : 행 메이저 매트릭스를 사용하고 있다는 경고를받습니다. 열 메이저 매트릭스가 바뀌 었습니다.

다른 팁

회전은 3차원 행렬로 지정되고 변환은 벡터로 지정됩니다.두 가지 변환을 단일 4 x 3 행렬로 결합하여 "단일" 작업으로 수행할 수 있습니다.

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

그러나 이것은 정사각형이 아니기 때문에 수행할 수 없는 다양한 작업이 있습니다(하나의 반전).추가 행을 추가하면(아무 작업도 수행되지 않음):

0   0   0   1

이러한 모든 작업이 가능해집니다(쉽지는 않더라도).

Goz가 설명했듯이 그의 대답 "1"을 동일하지 않은 값으로 만들면 행렬이 원근 변환이 됩니다.

클리핑은이 프로세스에서 중요한 부분입니다. 기하학에 발생하는 일을 시각화하는 데 도움이됩니다. 클리핑 스테이지는 본질적으로 원점을 중심으로하는 2 단위 큐브 외부에있는 원시의 모든 지점을 버립니다 (OK, 부분적으로 클리핑되었지만 여기서는 중요하지 않은 프리미티브를 재구성해야합니다).

세계 공간 좌표를 직접 큐브에 매핑하는 매트릭스를 구성하는 것이 가능하지만, 먼 비행기에서 가까운 비행기로 점진적인 움직임은 선형입니다. 즉, 시청자에서 1 마일 떨어진 곳에서 한 발의 움직임은 카메라에서 몇 피트에서 한 발의 움직임과 동일한 크기를 증가시킬 수 있습니다.

그러나 벡터 (W)에 또 다른 좌표가있는 경우 벡터 구성 요소를 W로 나눌 수 있으며 프리미티브는 위의 동작을 나타내지 않지만 여전히 2 단위 큐브 내부에서 끝날 수 있습니다. 위에.

자세한 설명은 참조하십시오 http://www.opengl.org/resources/faq/technical/depthbuffer.htm#0060 그리고 http://en.wikipedia.org/wiki/transformation_matrix#perspection_projection.

간단한 대답은 파이프 라인에 W가 무엇인지 말하지 않으면 투영에 대한 충분한 정보를 제공하지 않았다고 말하는 것입니다. 파이프 라인이 무엇을하는지 이해하지 않고 직접 확인할 수 있습니다 ...

아시다시피, 4x4 매트릭스는 각 부품이하는 일에 따라 부품으로 분할 될 수 있습니다. 왼쪽 상단의 3x3 행렬은 회전 또는 스케일 작업을 수행 할 때 변경됩니다. 네 번째 열은 번역을 할 때 변경됩니다. 원근 행렬을 검사하면 행렬의 하단 행을 변경합니다. 그런 다음 매트릭스 벡터 곱셈이 어떻게 수행되는지 살펴보면 행렬의 하단 행이 벡터의 결과 W 구성 요소에만 영향을 미친다는 것을 알 수 있습니다. 따라서 파이프 라인에 w에 대해 말하지 않으면 모든 정보가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top