文章目录
- 前言
- 一、围绕X轴旋转
- 二、围绕Y轴旋转
- 三、围绕Z轴旋转
- 四、在Shader实现
-
- 1、在属性面板定义四维变量,用xyz控制XYZ轴上的旋转
- 2、在常量缓冲区申明该变量
- [3、在 顶点着色器 定义旋转矩阵](#3、在 顶点着色器 定义旋转矩阵)
- 4、使用旋转矩阵与模型顶点相乘输出
- 5、最终效果
- 五、最终测试代码
前言
在上篇文章中,我们推算出了Shader物体旋转所使用的二维旋转矩阵。
在这篇文章中,我们来推算得到四维旋转矩阵。
一、围绕X轴旋转
围绕X轴旋转代表,物体顶点的X轴不变。
1、可以使用上篇文章中,同样的方法推导得出围绕X轴旋转的点阵。
- 我们把P~2~增加一维且分量为1
2、求M~rotate~
- M~rotate~ * P~1~ = P~2~
- M~rotate~ = P~2~* P~1~^-1^
- 最后得到M~rotate~
二、围绕Y轴旋转
围绕Y轴旋转代表,物体顶点的Y轴不变。
1、可以使用上篇文章中,同样的方法推导得出围绕Y轴旋转的点阵。
- 我们把P~2~增加一维且分量为1
2、求M~rotate~
- M~rotate~ * P~1~ = P~2~
- M~rotate~ = P~2~* P~1~^-1^
- 最后得到M~rotate~
三、围绕Z轴旋转
围绕Z轴旋转代表,物体顶点的Z轴不变。
1、可以使用上篇文章中,同样的方法推导得出围绕Z轴旋转的点阵。
- 我们把P~2~增加一维且分量为1
2、求M~rotate~
- M~rotate~ * P~1~ = P~2~
- M~rotate~ = P~2~* P~1~^-1^
- 最后得到M~rotate~
可以修改sin函数前面的负号位置实现顺时针还是逆时针。这篇文章中是顺时针
四、在Shader实现
1、在属性面板定义四维变量,用xyz控制XYZ轴上的旋转
_Rotation("Rotation(XYZ)",Vector) = (0,0,0,0)
2、在常量缓冲区申明该变量
CBUFFER_START(UnityPerMaterial)
float4 _Rotation;
CBUFFER_END
3、在 顶点着色器 定义旋转矩阵
float4x4 M_rotateX = float4x4
(
1,0,0,0,
0,cos(_Rotation.x),sin(_Rotation.x),0,
0,-sin(_Rotation.x),cos(_Rotation.x),0,
0,0,0,1
);
float4x4 M_rotateY = float4x4
(
cos(_Rotation.y),0,sin(_Rotation.y),0,
0,1,0,0,
-sin(_Rotation.y),0,cos(_Rotation.y),0,
0,0,0,1
);
float4x4 M_rotateZ = float4x4
(
cos(_Rotation.z),sin(_Rotation.z),0,0,
-sin(_Rotation.z),cos(_Rotation.z),0,0,
0,0,1,0,
0,0,0,1
);
4、使用旋转矩阵与模型顶点相乘输出
v.vertexOS = mul(M_rotateX,v.vertexOS);
v.vertexOS = mul(M_rotateY,v.vertexOS);
v.vertexOS = mul(M_rotateZ,v.vertexOS);
5、最终效果
五、最终测试代码
//平移变换
//缩放变换
//旋转变换(四维)
Shader "MyShader/URP/P3_5_7"
{
Properties
{
_Translate("Translate(XYZ)",Vector) = (0,0,0,0)
_Scale("Scale(XYZ)",Vector)= (1,1,1,1)
_Rotation("Rotation(XYZ)",Vector) = (0,0,0,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;
float4 _Rotation;
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);
//旋转变换
float4x4 M_rotateX = float4x4
(
1,0,0,0,
0,cos(_Rotation.x),sin(_Rotation.x),0,
0,-sin(_Rotation.x),cos(_Rotation.x),0,
0,0,0,1
);
float4x4 M_rotateY = float4x4
(
cos(_Rotation.y),0,sin(_Rotation.y),0,
0,1,0,0,
-sin(_Rotation.y),0,cos(_Rotation.y),0,
0,0,0,1
);
float4x4 M_rotateZ = float4x4
(
cos(_Rotation.z),sin(_Rotation.z),0,0,
-sin(_Rotation.z),cos(_Rotation.z),0,0,
0,0,1,0,
0,0,0,1
);
v.vertexOS = mul(M_rotateX,v.vertexOS);
v.vertexOS = mul(M_rotateY,v.vertexOS);
v.vertexOS = mul(M_rotateZ,v.vertexOS);
o.vertexCS = TransformObjectToHClip(v.vertexOS.xyz);
return o;
}
half4 frag (Varying i) : SV_Target
{
return 1;
}
ENDHLSL
}
}
}