SIMD math library for game developers
Tested on x86_64 and AArch64.
Provides ~140 optimized routines and ~70 extensive tests.
Can be used with any graphics API.
Documentation can be found here.
Benchamrks can be found here.
An intro article can be found here.
How to get dependencies
- specific version:
zig fetch --save https://github.com/zig-gamedev/zmath/archive/refs/tags/<REPLACE ME>.tar.gz - main branch version:
zig fetch --save git+https://github.com/zig-gamedev/zmath.git
Example build.zig
pubfnbuild(b: *std.Build) void {
constexe=b.addExecutable(.{ ... });
constzmath=b.dependency("zmath", .{});
exe.root_module.addImport("zmath", zmath.module("root"));
}Now in your code you may import and use zmath:
constzm=@import("zmath");
pubfnmain() !void {
//// OpenGL/Vulkan example//constobject_to_world=zm.rotationY(..);
constworld_to_view=zm.lookAtRh(
zm.f32x4(3.0, 3.0, 3.0, 1.0), // eye positionzm.f32x4(0.0, 0.0, 0.0, 1.0), // focus pointzm.f32x4(0.0, 1.0, 0.0, 0.0), // up direction ('w' coord is zero because this is a vector not a point)
);
// `perspectiveFovRhGl` produces Z values in [-1.0, 1.0] range (Vulkan app should use `perspectiveFovRh`)constview_to_clip=zm.perspectiveFovRhGl(0.25*math.pi, aspect_ratio, 0.1, 20.0);
constobject_to_view=zm.mul(object_to_world, world_to_view);
constobject_to_clip=zm.mul(object_to_view, view_to_clip);
// Transposition is needed because GLSL uses column-major matrices by defaultgl.uniformMatrix4fv(0, 1, gl.TRUE, zm.arrNPtr(&object_to_clip));
// In GLSL: gl_Position = vec4(in_position, 1.0) * object_to_clip;//// DirectX example//constobject_to_world=zm.rotationY(..);
constworld_to_view=zm.lookAtLh(
zm.f32x4(3.0, 3.0, -3.0, 1.0), // eye positionzm.f32x4(0.0, 0.0, 0.0, 1.0), // focus pointzm.f32x4(0.0, 1.0, 0.0, 0.0), // up direction ('w' coord is zero because this is a vector not a point)
);
constview_to_clip=zm.perspectiveFovLh(0.25*math.pi, aspect_ratio, 0.1, 20.0);
constobject_to_view=zm.mul(object_to_world, world_to_view);
constobject_to_clip=zm.mul(object_to_view, view_to_clip);
// Transposition is needed because HLSL uses column-major matrices by defaultconstmem=allocateUploadMemory(...);
zm.storeMat(mem, zm.transpose(object_to_clip));
// In HLSL: out_position_sv = mul(float4(in_position, 1.0), object_to_clip);//// 'WASD' camera movement example//
{
constspeed=zm.f32x4s(10.0);
constdelta_time=zm.f32x4s(demo.frame_stats.delta_time);
consttransform=zm.mul(zm.rotationX(demo.camera.pitch), zm.rotationY(demo.camera.yaw));
varforward=zm.normalize3(zm.mul(zm.f32x4(0.0, 0.0, 1.0, 0.0), transform));
zm.storeArr3(&demo.camera.forward, forward);
constright=speed*delta_time*zm.normalize3(zm.cross3(zm.f32x4(0.0, 1.0, 0.0, 0.0), forward));
forward=speed*delta_time*forward;
varcam_pos=zm.loadArr3(demo.camera.position);
if (keyDown('W')) {
cam_pos+=forward;
} elseif (keyDown('S')) {
cam_pos-=forward;
}
if (keyDown('D')) {
cam_pos+=right;
} elseif (keyDown('A')) {
cam_pos-=right;
}
zm.storeArr3(&demo.camera.position, cam_pos);
}
//// SIMD wave equation solver example (works with vector width 4, 8 and 16)// 'T' can be F32x4, F32x8 or F32x16//varz_index: i32=0;
while (z_index<grid_size) : (z_index+=1) {
constz=scale*@intToFloat(f32, z_index-grid_size/2);
constvz=zm.splat(T, z);
varx_index: i32=0;
while (x_index<grid_size) : (x_index+=zm.veclen(T)) {
constx=scale*@intToFloat(f32, x_index-grid_size/2);
constvx=zm.splat(T, x) +voffset*zm.splat(T, scale);
constd=zm.sqrt(vx*vx+vz*vz);
constvy=zm.sin(d-vtime);
constindex=@intCast(usize, x_index+z_index*grid_size);
zm.store(xslice[index..], vx, 0);
zm.store(yslice[index..], vy, 0);
zm.store(zslice[index..], vz, 0);
}
}
}