ScriptableRenderPassで行列をいじる
#URP #MVP変換
関連 : View行列を反転するとメッシュが反転する問題の対処
環境
環境 : Unity2021.2.0b7, Universal RP 12.0.0
行列の取得
ScriptableRenderPassのExecute実行時に渡されるRenderingDataからはView行列とProjection行列を取り出すことができます。
code:cs
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
Matrix4x4 view = renderingData.cameraData.GetViewMatrix();
Matrix4x4 proj = renderingData.cameraData.GetProjectionMatrix();
行列の上書き
ScriptableRenderContext.Renderでオブジェクトを描画する際のView行列とProjection行列は上書きすることができます。
code:cs
var cmd = CommandBufferPool.Get();
// 行列設定
cmd.SetViewProjectionMatrices(proj, view);
context.ExecuteCommandBuffer(cmd);
// レンダリング
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filters);
CommandBufferPool.Release(cmd);
View行列からTRS成分を取り出す
View行列の中身は Camera.worldToCameraMatrixです。
UniversalRenderPipeline.cs の917行目あたりに、行列を設定している処理があります。
code:UniversalRenderPipeline.cs
Matrix4x4 projectionMatrix = camera.projectionMatrix;
...
cameraData.SetViewAndProjectionMatrix(camera.worldToCameraMatrix, projectionMatrix);
renderingData.cameraData.GetViewMatrix()で取得できるView行列は、
カメラの平行移動(T)、回転(R)、スケール(S)から構築されたTRS行列になっています。
TRS = T * R * S
このView行列からT, R, S成分を取り出すことに挑戦してみました。
code:cs
Matrix4x4 view = renderingData.cameraData.GetViewMatrix();
// T
var translate = new Vector4(view.m02, view.m12, view.m22, view.m32);
// S
var scale = new Vector3(
Vector3.Magnitude(new Vector3(view.m00, view.m10, view.m20)),
Vector3.Magnitude(new Vector3(view.m01, view.m11, view.m21)),
Vector3.Magnitude(new Vector3(view.m02, view.m12, view.m22))
);
// R
var rotation = new Matrix4x4();
rotation0, 0 = view0, 0 / scale.x;
rotation0, 1 = view0, 1 / scale.x;
rotation0, 2 = view0, 2 / scale.x;
rotation1, 0 = view1, 0 / scale.y;
rotation1, 1 = view1, 1 / scale.y;
rotation1, 2 = view1, 2 / scale.y;
rotation2, 0 = view2, 0 / scale.z;
rotation2, 1 = view2, 1 / scale.z;
rotation2, 2 = view2, 2 / scale.z;
rotation3, 3 = 1;
参考 : https://math.stackexchange.com/questions/237369/given-this-transformation-matrix-how-do-i-decompose-it-into-translation-rotati/417813
TRS成分からView行列を構築する
code:cs
var trs = Matrix4x4.Scale(scale);
trs = rotation * trs;
trs.SetColumn(3, trs.GetColumn(3) + translate);
補足
Matrix4x4.TRS(translate, rotation.rotation, scale) で計算すると、なぜか元のView行列と違う結果になってしまうようです。