GLKMatrix4MakeOrtho의 사용법을 잘못한 일

10228 단어 SwiftGLKitMetal

Normalized Device Coordinate


OpenGL 등에서 최종 장치에 표시된 좌표는 NDC(정규 Device Coordinate)에서도 X 좌표, Y 좌표-1.0~1.0 범위에서 표시할 수 있다.실제 디스플레이 구역이 종길이든 가로길이든 -1.0~1.0에서 중심은0.0이다.

역시 앱답게 이 NDC 인코딩이 불편하다는 것을 깨닫고 3DGLKMatrix4MakePerspective 등에서 2DGLKMatrix4MakeOrtho를 이용해 4x4의 Matrix(행렬)를 구하고 Matrix와 좌표의 Vector를 곱하고 좌표를 바꾸면 View의 좌표를 NDC로 변환할 수 있다.
NDC의 좌표 = 행렬(4x4)*View의 좌표(x, y, z, w)

행렬 계산


Swift를 사용하면 행렬의 연산은 * 조작원으로 이루어지고 싶습니다.4x4 행렬 사이의 곱셈 결과는 4x4 행렬이고 4x4와 1x4 행렬의 곱셈 결과는 1x4 행렬이다.
func * (l: GLKMatrix4, r: GLKMatrix4) -> GLKMatrix4 {
    return GLKMatrix4Multiply(l, r)
}

func * (l: GLKMatrix4, r: GLKVector4) -> GLKVector4 {
    return GLKMatrix4MultiplyVector4(l, r)
}

GLKMatrix4MakeOrtho

GLKMatrix4MakeOrtho에 View의 위아래 좌우를 지정합니다.문서에는 다음과 같은 설명이 있습니다.
func GLKMatrix4MakeOrtho(left: Float, _ right: Float, _ bottom: Float, _ top: Float, _ nearZ: Float, _ farZ: Float) -> GLKMatrix4
Parameters
description
left
The left coordinate of the projection volume in eye coordinates.
right
The right coordinate of the projection volume in eye coordinates.
bottom
The bottom coordinate of the projection volume in eye coordinates.
top
The top coordinate of the projection volume in eye coordinates.
nearZ
The near coordinate of the projection volume in eye coordinates.
farZ
The far coordinate of the projection volume in eye coordinates.
따라서 화면의 사이즈가 1024×768인 경우 왼쪽 하단을 원점으로 하는 경우와 중심을 원점으로 하는 경우를 각각 코드와 그림으로 표현한다.

1. 왼쪽 하단을 원점으로 할 때

let matrix = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)

2. 중심을 원점으로 할 때

let matrix = GLKMatrix4MakeOrtho(-512, 512, -384, 384, -1, 1)

오해하다


나는 이렇게 하면 View의 좌표를 NDC 좌표계로 변환할 수 있다고 생각하기 때문에 방금 그림의 설명에서 사용한 좌표계의 좌표와nearZ의 행렬을 연산하면 좌표를 간단하게 변환할 수 있다고 생각해 왔다.그러나
사실 두 행렬의 원점farZ이 모두 뷰의 중심으로 전환됐는데 결과는 모두 같은 것으로 나와 아쉬운 결과다.더 일찍 눈치챘으면 쉬웠을 텐데.오른쪽이나 왼쪽을 지정하면 그렇게 생각하잖아.
let t1 = GLKMatrix4MakeOrtho(-512, 512, -384, 384, -1, 1)
let t2 = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)

// 座標 (-512, -384) → (-1, -1)
t1 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, -1.0, -0.0, 0.0 ]"
t2 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, -1.0, -0.0, 0.0 ]"

// 座標 (0, 0) → (0, 0)
t1 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"
t2 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"

// 座標 (512, 384) → (1, 1)
t1 * GLKVector4Make(512, 384, 0, 0) // "[1.0, 1.0, 0.0, 0.0 ]"
t2 * GLKVector4Make(512, 384, 0, 0) // "[1.0, 1.0, 0.0, 0.0 ]"

위아래로 뒤집고 싶을 때


마지막으로 GLKMatrix4MakeOrtho에서 (0, 0)GLKMatrix4MakeOrtho를 교체한 후topbottom의 순서를 주의하면) 위아래가 뒤바뀌면 전환할 수 있다.
let t3 = GLKMatrix4MakeOrtho(0, 1024, 768, 0, -1, 1)
t3 * GLKVector4Make(-512, -384, 0, 0) // "[-1.0, 1.0, -0.0, 0.0 ]"
t3 * GLKVector4Make(0, 0, 0, 0) // "[0.0, 0.0, 0.0, 0.0 ]"
t3 * GLKVector4Make(512, 384, 0, 0) // "[1.0, -1.0, 0.0, 0.0 ]"

전체가 아직 멀었다


여기서는 GLKMatrix4MakeOrtho만 처리했지만 모델 좌표→세계 좌표 등은 전체적으로 일부 설명에 불과하다는 점에 주의해야 한다.

허들 경기는 역시 높다


GPU를 사용하는 프로그램 설계는 문외한(ES1.1은 물린 것)이기 때문에 단순히 코어그래픽스를 사용하는 경우와 비교하면 조금 어렵다.잘못과 잘못된 지적에 주의하면 행운을 알려주세요.

좋은 웹페이지 즐겨찾기