Closed3
UnityでCompute Shaderを用いて画像の回転を行う
はじめに
入力画像に回転処理を施す。画像取得には以下のパッケージを使用。
実装
以下リポジトリで公開中。Compute Shaderを用いることで高速に動作させる。
ImageRotation.hlslについて
テクスチャのサイズを取得
// Get the dimensions of the input texture
uint textureWidth, textureHeight;
inputTexture.GetDimensions(textureWidth, textureHeight);
ピクセルの位置を正規化
// Normalize pixel coordinates to [-0.5, 0.5] range
float2 uv = float2(id.x, id.y) / float2(textureWidth, textureHeight) - 0.5;
ピクセルの位置をテクスチャの幅と高さで割る。その結果、ピクセルの位置は [0, 1] の範囲に正規化される。さらに、0.5を引くことで [-0.5, 0.5] の範囲になる。(ピクセルの中心を原点とする座標系に変換)
回転行列の計算
// Compute rotation matrix based on the rotation angle
float2x2 rotationMatrix = float2x2(cos(rotationAngle), -sin(rotationAngle), sin(rotationAngle), cos(rotationAngle));
回転行列はrotationAngleから計算され、2次元ベクトルを回転させるために使用する。
ピクセルの位置を回転
// Rotate the pixel position and shift back to [0, 1] range
float2 uvRotated = mul(rotationMatrix, uv) + 0.5;
回転行列を使ってピクセルの位置 uv を回転させ、0.5を足すことで [0, 1] の範囲に戻す。
範囲外チェック
// If rotated pixel is out of bounds, set pixel color to black
if (any(uvRotated < 0.0) || any(uvRotated > 1.0))
{
resultColor = float4(0.0, 0.0, 0.0, 1.0);
}
回転後のピクセル位置 uvRotated が [0, 1] の範囲を超えているかどうかを確認する。範囲を超えている場合(つまり、回転によりテクスチャの範囲外になった場合)、そのピクセルの値を黒(0.0, 0.0, 0.0, 1.0)に設定する。
バイリニア補間
else
{
// Scale up the rotated coordinates to original texture size
uvRotated *= float2(textureWidth, textureHeight);
// Compute the integer and fractional parts of the coordinates
int2 uvInt = int2(uvRotated);
float2 uvFrac = frac(uvRotated);
// Get the color of four neighboring pixels
float4 topLeftColor = inputTexture[uvInt]; // Top-left
float4 topRightColor = inputTexture[uvInt + int2(1, 0)]; // Top-right
float4 bottomLeftColor = inputTexture[uvInt + int2(0, 1)]; // Bottom-left
float4 bottomRightColor = inputTexture[uvInt + int2(1, 1)]; // Bottom-right
// Perform bilinear interpolation to compute final color of the rotated pixel
float4 topInterpolation = lerp(topLeftColor, topRightColor, uvFrac.x); // Top interpolation
float4 bottomInterpolation = lerp(bottomLeftColor, bottomRightColor, uvFrac.x); // Bottom interpolation
resultColor = lerp(topInterpolation, bottomInterpolation, uvFrac.y); // Final interpolation
}
範囲内に留まったピクセルの値を計算する。まず、回転後のピクセル位置 uvRotated をテクスチャのサイズにスケールアップする。次に、ピクセルの整数部分と小数部分を取得する。整数部分はピクセルの位置を表し、小数部分はその位置からのオフセットを表す。この情報を使用して、バイリニア補間を行い、新しいピクセルの値を計算する。バイリニア補間は、4つの隣接ピクセルの値を使い、新しいピクセルの値を計算する。
成果物
インスペクターから回転角を指定可能。
このスクラップは2023/08/02にクローズされました