在Shader中,我们经常对顶点进行旋转变换。我们在这篇文章中了解一下旋转使用的旋转矩阵。
我们先在2D平面下,了解2D原理
我们需要求的就是坐标系旋转后,P点在旋转后坐标系中的位置。
因为,我们旋转物体时,我们是围绕着一个轴旋转。
旋转后,我们需要求的就是物体顶点围绕该轴旋转后的坐标位置。
这里我们的 P 点就像 模型的顶点一样,得到P点的位置,就相当于得到了模型顶点在旋转后的位置。
求 P2x 可以化为求 OB + BC
求OB:
求BC:
P2x = OB + BC
P2x = OB + BC = cos(θ)P1x + sin(θ)P1y
这个点阵就是我们旋转矩阵的核心
因为,我们该点阵目前是在二维平面旋转。所以,可以认为我们是围绕 z 轴在旋转。
_Angle(“Angle”,Float) = 0
CBUFFER_START(UnityPerMaterial)
float _Angle;
CBUFFER_END
float2x2 M_rotate = float2x2
(
cos(_Angle),sin(_Angle),
-sin(_Angle),cos(_Angle)
);
v.vertexOS.xy = mul(M_rotate,v.vertexOS.xy);
围绕x轴旋转 和 围绕y轴旋转,我们可以修改 .xy 来实现。
//平移变换
//缩放变换
//旋转变换
Shader "MyShader/URP/P3_5_5"
{
Properties
{
_Translate("Translate(XYZ)",Vector) = (0,0,0,0)
_Scale("Scale(XYZ)",Vector)= (1,1,1,1)
_Angle("Angle",Float) = 0
}
SubShader
{
Tags
{
"PenderPipeline"="UniversalPipeline"
"RenderType"="Opaque"
"Queue"="Geometry"
}
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attribute
{
float4 vertexOS : POSITION;
};
struct Varying
{
float4 vertexCS : SV_POSITION;
};
CBUFFER_START(UnityPerMaterial)
float4 _Translate;
float4 _Scale;
float _Angle;
CBUFFER_END
Varying vert (Attribute v)
{
Varying o;
//平移变换
float4x4 M_Translate = float4x4
(
1,0,0,_Translate.x,
0,1,0,_Translate.y,
0,0,1,_Translate.z,
0,0,0,1
);
v.vertexOS = mul(M_Translate,v.vertexOS);
//缩放交换
float4x4 M_Scale = float4x4
(
_Scale.x,0,0,0,
0,_Scale.y,0,0,
0,0,_Scale.z,0,
0,0,0,1
);
v.vertexOS = mul(M_Scale,v.vertexOS);
//旋转变换
float2x2 M_rotate = float2x2
(
cos(_Angle),sin(_Angle),
-sin(_Angle),cos(_Angle)
);
v.vertexOS.xy = mul(M_rotate,v.vertexOS.xy);
o.vertexCS = TransformObjectToHClip(v.vertexOS.xyz);
return o;
}
half4 frag (Varying i) : SV_Target
{
return 1;
}
ENDHLSL
}
}
}