A game about forced loneliness, made by TACStudios
1#ifndef UNITY_SPACE_TRANSFORMS_INCLUDED
2#define UNITY_SPACE_TRANSFORMS_INCLUDED
3
4#if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH || defined(UNITY_UNIFIED_SHADER_PRECISION_MODEL)
5#pragma warning (disable : 3205) // conversion of larger type to smaller
6#endif
7
8// Caution: For HDRP, adding a function in this file requires adding the appropriate #define in PickingSpaceTransforms.hlsl
9
10// Return the PreTranslated ObjectToWorld Matrix (i.e matrix with _WorldSpaceCameraPos apply to it if we use camera relative rendering)
11float4x4 GetObjectToWorldMatrix()
12{
13 return UNITY_MATRIX_M;
14}
15
16float4x4 GetWorldToObjectMatrix()
17{
18 return UNITY_MATRIX_I_M;
19}
20
21float4x4 GetPrevObjectToWorldMatrix()
22{
23 return UNITY_PREV_MATRIX_M;
24}
25
26float4x4 GetPrevWorldToObjectMatrix()
27{
28 return UNITY_PREV_MATRIX_I_M;
29}
30
31float4x4 GetWorldToViewMatrix()
32{
33 return UNITY_MATRIX_V;
34}
35
36float4x4 GetViewToWorldMatrix()
37{
38 return UNITY_MATRIX_I_V;
39}
40
41// Transform to homogenous clip space
42float4x4 GetWorldToHClipMatrix()
43{
44 return UNITY_MATRIX_VP;
45}
46
47// Transform to homogenous clip space
48float4x4 GetViewToHClipMatrix()
49{
50 return UNITY_MATRIX_P;
51}
52
53// This function always return the absolute position in WS
54float3 GetAbsolutePositionWS(float3 positionRWS)
55{
56#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
57 positionRWS += _WorldSpaceCameraPos.xyz;
58#endif
59 return positionRWS;
60}
61
62// This function return the camera relative position in WS
63float3 GetCameraRelativePositionWS(float3 positionWS)
64{
65#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
66 positionWS -= _WorldSpaceCameraPos.xyz;
67#endif
68 return positionWS;
69}
70
71real GetOddNegativeScale()
72{
73 // FIXME: We should be able to just return unity_WorldTransformParams.w, but it is not
74 // properly set at the moment, when doing ray-tracing; once this has been fixed in cpp,
75 // we can revert back to the former implementation.
76 return unity_WorldTransformParams.w >= 0.0 ? 1.0 : -1.0;
77}
78
79float3 TransformObjectToWorld(float3 positionOS)
80{
81 #if defined(SHADER_STAGE_RAY_TRACING)
82 return mul(ObjectToWorld3x4(), float4(positionOS, 1.0)).xyz;
83 #else
84 return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
85 #endif
86}
87
88float3 TransformWorldToObject(float3 positionWS)
89{
90 #if defined(SHADER_STAGE_RAY_TRACING)
91 return mul(WorldToObject3x4(), float4(positionWS, 1.0)).xyz;
92 #else
93 return mul(GetWorldToObjectMatrix(), float4(positionWS, 1.0)).xyz;
94 #endif
95}
96
97float3 TransformWorldToView(float3 positionWS)
98{
99 return mul(GetWorldToViewMatrix(), float4(positionWS, 1.0)).xyz;
100}
101
102float3 TransformViewToWorld(float3 positionVS)
103{
104 return mul(GetViewToWorldMatrix(), float4(positionVS, 1.0)).xyz;
105}
106
107// Transforms position from object space to homogenous space
108float4 TransformObjectToHClip(float3 positionOS)
109{
110 // More efficient than computing M*VP matrix product
111 return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)));
112}
113
114// Transforms position from world space to homogenous space
115float4 TransformWorldToHClip(float3 positionWS)
116{
117 return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
118}
119
120// Transforms position from view space to homogenous space
121float4 TransformWViewToHClip(float3 positionVS)
122{
123 return mul(GetViewToHClipMatrix(), float4(positionVS, 1.0));
124}
125
126// Normalize to support uniform scaling
127float3 TransformObjectToWorldDir(float3 dirOS, bool doNormalize = true)
128{
129 #ifndef SHADER_STAGE_RAY_TRACING
130 float3 dirWS = mul((float3x3)GetObjectToWorldMatrix(), dirOS);
131 #else
132 float3 dirWS = mul((float3x3)ObjectToWorld3x4(), dirOS);
133 #endif
134 if (doNormalize)
135 return SafeNormalize(dirWS);
136
137 return dirWS;
138}
139
140// Normalize to support uniform scaling
141float3 TransformWorldToObjectDir(float3 dirWS, bool doNormalize = true)
142{
143 #ifndef SHADER_STAGE_RAY_TRACING
144 float3 dirOS = mul((float3x3)GetWorldToObjectMatrix(), dirWS);
145 #else
146 float3 dirOS = mul((float3x3)WorldToObject3x4(), dirWS);
147 #endif
148 if (doNormalize)
149 return normalize(dirOS);
150
151 return dirOS;
152}
153
154// Transforms vector from world space to view space
155real3 TransformWorldToViewDir(real3 dirWS, bool doNormalize = false)
156{
157 float3 dirVS = mul((real3x3)GetWorldToViewMatrix(), dirWS).xyz;
158 if (doNormalize)
159 return normalize(dirVS);
160
161 return dirVS;
162}
163
164// Transforms vector from view space to world space
165real3 TransformViewToWorldDir(real3 dirVS, bool doNormalize = false)
166{
167 float3 dirWS = mul((real3x3)GetViewToWorldMatrix(), dirVS).xyz;
168 if (doNormalize)
169 return normalize(dirWS);
170
171 return dirWS;
172}
173
174// Transforms normal from world space to view space
175real3 TransformWorldToViewNormal(real3 normalWS, bool doNormalize = false)
176{
177 // assuming view matrix is uniformly scaled, we can use direction transform
178 return TransformWorldToViewDir(normalWS, doNormalize);
179}
180
181// Transforms normal from view space to world space
182real3 TransformViewToWorldNormal(real3 normalVS, bool doNormalize = false)
183{
184 // assuming view matrix is uniformly scaled, we can use direction transform
185 return TransformViewToWorldDir(normalVS, doNormalize);
186}
187
188// Transforms vector from world space to homogenous space
189real3 TransformWorldToHClipDir(real3 directionWS, bool doNormalize = false)
190{
191 float3 dirHCS = mul((real3x3)GetWorldToHClipMatrix(), directionWS).xyz;
192 if (doNormalize)
193 return normalize(dirHCS);
194
195 return dirHCS;
196}
197
198// Transforms normal from object to world space
199float3 TransformObjectToWorldNormal(float3 normalOS, bool doNormalize = true)
200{
201#ifdef UNITY_ASSUME_UNIFORM_SCALING
202 return TransformObjectToWorldDir(normalOS, doNormalize);
203#else
204 // Normal need to be multiply by inverse transpose
205 float3 normalWS = mul(normalOS, (float3x3)GetWorldToObjectMatrix());
206 if (doNormalize)
207 return SafeNormalize(normalWS);
208
209 return normalWS;
210#endif
211}
212
213// Transforms normal from world to object space
214float3 TransformWorldToObjectNormal(float3 normalWS, bool doNormalize = true)
215{
216#ifdef UNITY_ASSUME_UNIFORM_SCALING
217 return TransformWorldToObjectDir(normalWS, doNormalize);
218#else
219 // Normal need to be multiply by inverse transpose
220 float3 normalOS = mul(normalWS, (float3x3)GetObjectToWorldMatrix());
221 if (doNormalize)
222 return SafeNormalize(normalOS);
223
224 return normalOS;
225#endif
226}
227
228real3x3 CreateTangentToWorld(real3 normal, real3 tangent, real flipSign)
229{
230 // For odd-negative scale transforms we need to flip the sign
231 real sgn = flipSign * GetOddNegativeScale();
232 real3 bitangent = cross(normal, tangent) * sgn;
233
234 return real3x3(tangent, bitangent, normal);
235}
236
237// this function is intended to work on Normals (handles non-uniform scale)
238// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
239real3 TransformTangentToWorld(float3 normalTS, real3x3 tangentToWorld, bool doNormalize = false)
240{
241 // Note matrix is in row major convention with left multiplication as it is build on the fly
242 real3 result = mul(normalTS, tangentToWorld);
243 if (doNormalize)
244 return SafeNormalize(result);
245 return result;
246}
247
248// this function is intended to work on Normals (handles non-uniform scale)
249// This function does the exact inverse of TransformTangentToWorld() and is
250// also decribed within comments in mikktspace.h and it follows implicitly
251// from the scalar triple product (google it).
252// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
253real3 TransformWorldToTangent(real3 normalWS, real3x3 tangentToWorld, bool doNormalize = true)
254{
255 // Note matrix is in row major convention with left multiplication as it is build on the fly
256 float3 row0 = tangentToWorld[0];
257 float3 row1 = tangentToWorld[1];
258 float3 row2 = tangentToWorld[2];
259
260 // these are the columns of the inverse matrix but scaled by the determinant
261 float3 col0 = cross(row1, row2);
262 float3 col1 = cross(row2, row0);
263 float3 col2 = cross(row0, row1);
264
265 float determinant = dot(row0, col0);
266
267 // inverse transposed but scaled by determinant
268 // Will remove transpose part by using matrix as the first arg in the mul() below
269 // this makes it the exact inverse of what TransformTangentToWorld() does.
270 real3x3 matTBN_I_T = real3x3(col0, col1, col2);
271 real3 result = mul(matTBN_I_T, normalWS);
272 if (doNormalize)
273 {
274 float sgn = determinant < 0.0 ? (-1.0) : 1.0;
275 return SafeNormalize(sgn * result);
276 }
277 else
278 return result / determinant;
279}
280
281// this function is intended to work on Vectors/Directions
282// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
283real3 TransformWorldToTangentDir(real3 dirWS, real3x3 tangentToWorld, bool doNormalize = false)
284{
285 // Note matrix is in row major convention with left multiplication as it is build on the fly
286 real3 result = mul(tangentToWorld, dirWS);
287 if (doNormalize)
288 return SafeNormalize(result);
289 return result;
290}
291
292// this function is intended to work on Vectors/Directions
293// This function does the exact inverse of TransformWorldToTangentDir()
294// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
295real3 TransformTangentToWorldDir(real3 dirWS, real3x3 tangentToWorld, bool doNormalize = false)
296{
297 // Note matrix is in row major convention with left multiplication as it is build on the fly
298 float3 row0 = tangentToWorld[0];
299 float3 row1 = tangentToWorld[1];
300 float3 row2 = tangentToWorld[2];
301
302 // these are the columns of the inverse matrix but scaled by the determinant
303 float3 col0 = cross(row1, row2);
304 float3 col1 = cross(row2, row0);
305 float3 col2 = cross(row0, row1);
306
307 float determinant = dot(row0, col0);
308
309 // inverse transposed but scaled by determinant
310 // Will remove transpose part by using matrix as the second arg in the mul() below
311 // this makes it the exact inverse of what TransformWorldToTangentDir() does.
312 real3x3 matTBN_I_T = real3x3(col0, col1, col2);
313 real3 result = mul(dirWS, matTBN_I_T);
314 if (doNormalize)
315 {
316 float sgn = determinant < 0.0 ? (-1.0) : 1.0;
317 return SafeNormalize(sgn * result);
318 }
319 else
320 return result / determinant;
321}
322
323// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
324real3 TransformTangentToObject(real3 dirTS, real3x3 tangentToWorld)
325{
326 // Note matrix is in row major convention with left multiplication as it is build on the fly
327 real3 normalWS = TransformTangentToWorld(dirTS, tangentToWorld);
328 return TransformWorldToObjectNormal(normalWS);
329}
330
331// tangentToWorld is the matrix representing the transformation of a normal from tangent to world space
332real3 TransformObjectToTangent(real3 dirOS, real3x3 tangentToWorld)
333{
334 // Note matrix is in row major convention with left multiplication as it is build on the fly
335
336 // don't normalize, as normalWS will be normalized after TransformWorldToTangent
337 float3 normalWS = TransformObjectToWorldNormal(dirOS, false);
338
339 // transform from world to tangent
340 return TransformWorldToTangent(normalWS, tangentToWorld);
341}
342
343#if SHADER_API_MOBILE || SHADER_API_GLES3 || SHADER_API_SWITCH
344#pragma warning (enable : 3205) // conversion of larger type to smaller
345#endif
346
347#endif