Glkit VS. Metal Perspective Matrix Difference

GLKit vs. Metal perspective matrix difference

Quoting from this forum question

OpenGL uses different clip-space coordinates than Metal (in GL, z goes
from -1 to 1, while in Metal z goes from 0 to 1), so using
GLKMatrix4MakePerspective doesn't give you a matrix that properly
transforms from eye space to clip space. Instead, it transforms half
of the viewing volume behind the eye, causing sometimes-subtle
clipping and culling issues. You can fix up the matrix you get back
from GLK by setting the matrix elements that are relevant to depth by
adding the following code to makePerspectiveViewAngle:

let zs = farZ / (nearZ - farZ)

q[2][2] = zs

q[3][2] = zs * nearZ

Is there a Metal library function to create a simd rotation matrix?

There are not currently utility functions for creating such matrices in simd.framework, Metal, or MetalKit. However, you can use GLKit's matrix functions and convert the resulting GLKMatrix4s into float4x4s before, for example, copying them into a Metal buffer for use in a shader.

A GLKMatrix4 is just a union containing an array of 16 floats, stored in column-major order.

Therefore, we can write an extension on float4x4 that allows initializing a simd matrix with a GLKit matrix:

extension float4x4 {
init(matrix: GLKMatrix4) {
self.init(columns: (float4(x: matrix.m00, y: matrix.m01, z: matrix.m02, w: matrix.m03),
float4(x: matrix.m10, y: matrix.m11, z: matrix.m12, w: matrix.m13),
float4(x: matrix.m20, y: matrix.m21, z: matrix.m22, w: matrix.m23),
float4(x: matrix.m30, y: matrix.m31, z: matrix.m32, w: matrix.m33)))
}
}

I verified that the resulting matrix matched my expectations by creating a GLKit matrix that represents a 45-degree rotation counterclockwise about the +Z axis, and ensuring that it does, in fact, rotate the unit vector <1, 0, 0> onto the unit vector <sqrt(2)/2, sqrt(2)/2, 0>:

let rotation = GLKMatrix4MakeZRotation(.pi / 4)
let simdRotation = float4x4(matrix: rotation)
let v = float4(1, 0, 0, 0)
let vp = simdRotation * v
print("\(vp)")

> float4(0.707107, 0.707107, 0.0, 0.0)

Note that I'm abiding the convention here that matrix-vector multiplication treats the vector as a column vector and places the matrix on the left, which is the most common convention in current use.

There is one caveat you should be aware of with respect to GLKit and Metal's clip space. You can read about the issue, and how to correct for it, here.

Storage of `ray_data` in ray tracing payload

According to the answer I received on the Apple Developer Forums,

The way the GPU stores the payload varies between device and there is no particular size. All we can really say is that cost scales roughly with the size so you should minimize that payload. If the payload gets too large you may run into a dramatic performance drop.

Nested GLKView and GLKViewController

Ok so I found the answer.

The "OpenGL View Controller" in the picture must be a normal UIViewController. Subclass this view controller and in the viewDidLoad, create programmatically your OpenGL View Controller:

- (void)viewDidLoad
{
[super viewDidLoad];

_openGLViewController = [[FZIOpenGLViewController alloc] initWithNibName:@"FZIOpenGLView" bundle:nil];

_openGLViewController.view.frame = _openGLView.frame;

[self.view addSubview:_openGLViewController.view];

}

In this code, _openGLView is an IBOutlet representing "GLKit View" in the picture. It's basically just there to get the right dimensions.

_openGLViewController is your GLKViewController subclass that handles everything OpenGL. The .xib file FZIOpenGLView.xib is just a GLKView with the appropriate File Owner (FZIOpenGLViewController).

It works:

result
(source: canardpc.com)



Related Topics



Leave a reply



Submit