RealityKitではMetalをCustomMaterialとして使用する場合、SurfaceShaderとGeometryModifierが必要になる
SurfaceShader
描画対象となるエンティティの見た目をレンダリングするためのピクセルを決定できる。
GeometryShader
描画の対象となるモデルの頂点を操作することができるので、サイズ、形状を動的に操作できる。
AppleのRealityKitのMetalApiのドキュメント。
それぞれの二つのMetalファイルを作成して作るたいシェーダーを記述する。下記例
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
[[visible]]
void waveMotion(realitykit::geometry_parameters params)
{
float xSpeed = 1;
float zSpeed = 1.1;
float xAmp = 0.01;
float zAmp = 0.02;
float3 localPos = params.geometry().model_position();
float xPeriod = (sin(localPos.x * 40 + params.uniforms().time() /40) + 3) * 2;
float zPeriod = (sin(localPos.z * 20 + params.uniforms().time() /13) + 3);
float xOffset = xAmp * sin(xSpeed * params.uniforms().time() + xPeriod * localPos.x);
float zOffset = zAmp * sin(zSpeed * params.uniforms().time() + zPeriod * localPos.z);
params.geometry().set_model_position_offset(
float3(0, xOffset + zOffset, 0)
);
}
[[visible]]
void waveSurface(realitykit::surface_parameters params)
{
auto surface = params.surface();
float maxAmp = 0.03;
half3 oceanBlue = half3(0, 0.412, 0.58);
float waveHeight = (
params.geometry().model_position().y + maxAmp
) / (maxAmp * 2);
surface.set_base_color(
oceanBlue + min(1.0f, pow(waveHeight, 8)) * (1 - oceanBlue)
);
}
その後下記のようなコードでCustomMaterialをイニシャライザする際の引数にセットしてあげればMaterialとして扱う。
// deviceを取ってくる。
guard let device = MTLCreateSystemDefaultDevice() else { return }
// metalLibraryを取ってくる
guard let library = device.makeDefaultLibrary() else { return }
// ここで作成したGeometry ModifierとsurfaceShaderを用意してセットしてあげる。
let geometryModifier = CustomMaterial.GeometryModifier(named: "myGeometryModifier", in: library)
let surfaceShader = CustomMaterial.SurfaceShader(named: "mySurfaceShader", in: library)
let customMaterial: CustomMaterial
do {
try customMaterial = CustomMaterial(surfaceShader: surfaceShader, geometryModifier: geometryModifier, lightingModel: .lit)
} catch {
fatalError()
}
let mesh = MeshResource.generateSphere(radius: 0.5)
let modelEntity = ModelEntity(mesh: mesh, materials: [customMaterial])
意外とシンプルにCustomMaterialにセットすればできるが、そもそもMetalのAPIが難しい。。
そこさえできればいろんなMaterialを自在に扱えそう。