前言
在Shader中,我们经常对顶点进行旋转变换。我们在这篇文章中了解一下旋转使用的旋转矩阵。
一、旋转矩阵的原理
我们先在2D平面下,了解2D原理
1、我们以原点为中心,旋转坐标轴θ度
我们需要求的就是坐标系旋转后,P点在旋转后坐标系中的位置。
因为,我们旋转物体时,我们是围绕着一个轴旋转。
旋转后,我们需要求的就是物体顶点围绕该轴旋转后的坐标位置。
这里我们的 P 点就像 模型的顶点一样,得到P点的位置,就相当于得到了模型顶点在旋转后的位置。
- 旋转前 P1(2,3)
- 旋转后 P2 (?,?)
2、求 P2x:
- 求 P2x 可以化为求 OB + BC
- 求OB:
c o s ( θ ) = O B O A cos(θ) = \frac{OB}{OA} cos(θ)=OAOB
O B = c o s ( θ ) ∗ O A OB = cos(θ)*OA OB=cos(θ)∗OA
O B = c o s ( θ ) ∗ P 1 x OB = cos(θ)*P_{1x} OB=cos(θ)∗P1x
- 求BC:
s i n ( θ ) = A D A P sin(θ) = \frac{AD}{AP} sin(θ)=APAD
A D = s i n ( θ ) ∗ A P AD = sin(θ)*AP AD=sin(θ)∗AP
A D = s i n ( θ ) ∗ P 1 y AD = sin(θ)*P_{1y} AD=sin(θ)∗P1y
- P2x = OB + BC
P 2 x = O B + B C = c o s ( θ ) P 1 x + s i n ( θ ) P 1 y P_{2x} = OB + BC = cos(θ)P_{1x} + sin(θ)P_{1y} P2x=OB+BC=cos(θ)P1x+sin(θ)P1y
3、求P2y:
- 求P2y可以化为求 OC - AC
- 求OC:
c o s ( θ ) = O C O B cos(θ)= \frac{OC}{OB} cos(θ)=OBOC
O C = c o s ( θ ) ∗ O B OC=cos(θ)*OB OC=cos(θ)∗OB
O C = c o s ( θ ) ∗ P 1 y OC=cos(θ)*P_{1y} OC=cos(θ)∗P1y
- 求AC:
s i n ( θ ) = B D B P sin(θ) = \frac{BD}{BP} sin(θ)=BPBD
B D = s i n ( θ ) ∗ B P BD = sin(θ)*BP BD=sin(θ)∗BP
A C = s i n ( θ ) ∗ B P AC = sin(θ)*BP AC=sin(θ)∗BP
A C = s i n ( θ ) ∗ P 1 x AC = sin(θ)*P_{1x} AC=sin(θ)∗P1x
- P2y = OC - AC
P 2 y = O C − A C = c o s ( θ ) P 1 y − s i n ( θ ) P 1 x P_{2y} = OC - AC = cos(θ)P_{1y} - sin(θ)P_{1x} P2y=OC−AC=cos(θ)P1y−sin(θ)P1x
4、最后得到 P2点 的点阵
这个点阵就是我们旋转矩阵的核心
- P 2 x = O B + B C = c o s ( θ ) P 1 x + s i n ( θ ) P 1 y P_{2x} = OB + BC = cos(θ)P_{1x} + sin(θ)P_{1y} P2x=OB+BC=cos(θ)P1x+sin(θ)P1y
- P 2 y = O C − A C = c o s ( θ ) P 1 y − s i n ( θ ) P 1 x P_{2y} = OC - AC = cos(θ)P_{1y} - sin(θ)P_{1x} P2y=OC−AC=cos(θ)P1y−sin(θ)P1x
[ c o s ( θ ) ∗ P 1 x s i n ( θ ) ∗ P 1 y − s i n ( θ ) ∗ P 1 x c o s ( θ ) ∗ P 1 y ] \begin{bmatrix} cos(θ)*P_{1x}&sin(θ)*P_{1y}\\ -sin(θ)*P_{1x}&cos(θ)*P_{1y}\\ \end{bmatrix} [cos(θ)∗P1x−sin(θ)∗P1xsin(θ)∗P1ycos(θ)∗P1y]
5、该点阵可以拆分为以下两个矩阵相乘的结果
因为,我们该点阵目前是在二维平面旋转。所以,可以认为我们是围绕 z 轴在旋转。
- Mrotate就是我们的旋转矩阵
M r o t a t e = [ c o s ( θ ) s i n ( θ ) − s i n ( θ ) c o s ( θ ) ] M_{rotate}= \begin{bmatrix} cos(θ)&sin(θ)\\ -sin(θ)&cos(θ)\\ \end{bmatrix} Mrotate=[cos(θ)−sin(θ)sin(θ)cos(θ)] - P1 就是我们旋转前的点
P 1 = [ P 1 x P 1 y ] P_1= \begin{bmatrix} P_{1x}\\ P_{1y}\\ \end{bmatrix} P1=[P1xP1y]
二、在Shader中,使用该旋转矩阵实现围绕 z 轴旋转
1、在属性面板定义 float 变量作为旋转的角度θ
_Angle(“Angle”,Float) = 0
2、在常量缓冲区申明该变量
CBUFFER_START(UnityPerMaterial)
float _Angle;
CBUFFER_END
3、在 顶点着色器 定义旋转矩阵
float2x2 M_rotate = float2x2
(
cos(_Angle),sin(_Angle),
-sin(_Angle),cos(_Angle)
);
4、用旋转矩阵乘以顶点的 xy 实现围绕z轴旋转
v.vertexOS.xy = mul(M_rotate,v.vertexOS.xy);文章来源:https://www.toymoban.com/news/detail-764263.html
5、效果
围绕x轴旋转 和 围绕y轴旋转,我们可以修改 .xy 来实现。
文章来源地址https://www.toymoban.com/news/detail-764263.html
三、测试代码
//平移变换
//缩放变换
//旋转变换
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
}
}
}
到了这里,关于Unity中Shader旋转矩阵(二维旋转矩阵)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!