-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnormal.compute
82 lines (72 loc) · 2.66 KB
/
normal.compute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma kernel NormalMain
#include "common.cginc"
#include "UnityCG.cginc"
#define QUATERNION_IDENTITY float4(0, 0, 0, 1)
RWStructuredBuffer<MeshData> _Buffer;
float4x4 _LocalToWorldMatrix;
float4x4 _Rotation;
float4 rotate_angle_axis(float angle, float3 axis)
{
float sn = sin(angle * 0.5);
float cs = cos(angle * 0.5);
return float4(axis * sn, cs);
}
// UnityEngine.Quaternion.FromToRotation(Vector3, Vector3)
float4 from_to_rotation(float3 v1, float3 v2)
{
float4 q;
float d = dot(v1, v2);
if (d < -0.999999)
{
float3 right = float3(1, 0, 0);
float3 up = float3(0, 1, 0);
float3 tmp = cross(right, v1);
if (length(tmp) < 0.000001)
{
tmp = cross(up, v1);
}
tmp = normalize(tmp);
q = rotate_angle_axis(UNITY_PI, tmp);
}
else if (d > 0.999999)
{
q = QUATERNION_IDENTITY;
}
else
{
q.xyz = cross(v1, v2);
q.w = 1 + d;
q = normalize(q);
}
return q;
}
// UnityEngine.Matrix4x4.MultiplyPoint(Vector3)
float3 multiply_point(float3 pt, float4x4 mat)
{
float3 vector3;
vector3.x = (mat[0][0] * pt.x + mat[0][1] * pt.y + mat[0][2] * pt.z) + mat[0][3];
vector3.y = (mat[1][0] * pt.x + mat[1][1] * pt.y + mat[1][2] * pt.z) + mat[1][3];
vector3.z = (mat[2][0] * pt.x + mat[2][1] * pt.y + mat[2][2] * pt.z) + mat[2][3];
float num = 1.0 / ((mat[3][0] * pt.x + mat[3][1] * pt.y + mat[3][2] * pt.z) + mat[3][3]);
vector3.x *= num;
vector3.y *= num;
vector3.z *= num;
return vector3;
}
[numthreads(8,1,1)]
void NormalMain(uint3 id: SV_DispatchThreadID)
{
const int index = id.x;
MeshData data = _Buffer[index];
// Since it is necessary to give the rotation of the object to the Cube for display in the vertex shader, obtain the rotation matrix to orient the normal direction considering the rotation of the object.
// 頂点シェーダーで表示用のCubeに対してオブジェクトの回転を与える必要があるため、オブジェクトの回転を考慮した法線の方向を向くための回転行列を得る
float4 q = from_to_rotation(float3(0, 1, 0), mul(_Rotation, data.normal));
float4x4 mat = {
1 - 2 * q.y * q.y - 2 * q.z * q.z, 2 * q.x * q.y - 2 * q.z * q.w, 2 * q.x * q.z + 2 * q.y * q.w, 0,
2 * q.x * q.y + 2 * q.z * q.w, 1 - 2 * q.x * q.x - 2 * q.z * q.z, 2 * q.y * q.z - 2 * q.x * q.w, 0,
2 * q.x * q.z - 2 * q.y * q.w, 2 * q.y * q.z + 2 * q.x * q.w, 1 - 2 * q.x * q.x - 2 * q.y * q.y, 0,
0, 0, 0, 1,
};
_Buffer[index].rotationMatrix = mat;
_Buffer[index].worldVertex = multiply_point(data.vertex, _LocalToWorldMatrix);
}