#ifndef SSR_COMMON #define SSR_COMMON struct VertexPositionInputs { float3 positionWS; // World space position float3 positionVS; // View space position float4 positionCS; // Homogeneous clip space position float4 positionNDC;// Homogeneous normalized device coordinates }; struct VertexNormalInputs { float3 tangentWS; float3 bitangentWS; float3 normalWS; }; #define FLT_MIN 1.175494351e-38 // Minimum normalized positive floating-point number // Normalize that account for vectors with zero length float3 SafeNormalize(float3 inVec) { float dp3 = max(FLT_MIN, dot(inVec, inVec)); return inVec * rsqrt(dp3); } float4x4 GetObjectToWorldMatrix() { return UNITY_MATRIX_M; } float4x4 GetWorldToObjectMatrix() { return unity_WorldToObject; } float4x4 GetWorldToViewMatrix() { return UNITY_MATRIX_V; } float4x4 GetWorldToHClipMatrix() { return UNITY_MATRIX_VP; } float3 GetCameraPositionWS() { return _WorldSpaceCameraPos; } float3 TransformObjectToWorld(float3 positionOS) { return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz; } float3 TransformWorldToView(float3 positionWS) { return mul(GetWorldToViewMatrix(), float4(positionWS, 1.0)).xyz; } float3 TransformObjectToWorldDir(float3 dirOS) { // Normalize to support uniform scaling return SafeNormalize(mul((float3x3)GetObjectToWorldMatrix(), dirOS)); } float3 TransformWorldToViewDir(float3 dirWS) { return mul((float3x3)GetWorldToViewMatrix(), dirWS).xyz; } float4 TransformObjectToHClip(float3 positionOS) { // More efficient than computing M*VP matrix product return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0))); } float4 TransformWorldToHClip(float3 positionWS) { return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0)); } float3 TransformTangentToWorld(float3 dirTS, float3x3 tangentToWorld) { // Note matrix is in row major convention with left multiplication as it is build on the fly return mul(dirTS, tangentToWorld); } float3 TransformObjectToWorldNormal(float3 normalOS) { #ifdef UNITY_ASSUME_UNIFORM_SCALING return TransformObjectToWorldDir(normalOS); #else // Normal need to be multiply by inverse transpose return SafeNormalize(mul(normalOS, (float3x3)GetWorldToObjectMatrix())); #endif } VertexPositionInputs GetVertexPositionInputs(float3 positionOS) { VertexPositionInputs input; input.positionWS = TransformObjectToWorld(positionOS); input.positionVS = TransformWorldToView(input.positionWS); input.positionCS = TransformWorldToHClip(input.positionWS); float4 ndc = input.positionCS * 0.5f; input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w; input.positionNDC.zw = input.positionCS.zw; return input; } float GetOddNegativeScale() { return unity_WorldTransformParams.w; } VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS) { VertexNormalInputs tbn; // mikkts space compliant. only normalize when extracting normal at frag. float sign = tangentOS.w * GetOddNegativeScale(); tbn.normalWS = TransformObjectToWorldNormal(normalOS); tbn.tangentWS = TransformObjectToWorldDir(tangentOS.xyz); tbn.bitangentWS = cross(tbn.normalWS, tbn.tangentWS) * sign; return tbn; } float4 ComputeClipSpacePosition(float2 positionNDC, float deviceDepth) { float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0); #if UNITY_UV_STARTS_AT_TOP // Our world space, view space, screen space and NDC space are Y-up. // Our clip space is flipped upside-down due to poor legacy Unity design. // The flip is baked into the projection matrix, so we only have to flip // manually when going from CS to NDC and back. positionCS.y = -positionCS.y; #endif return positionCS; } float3 ComputeViewSpacePosition(float2 positionNDC, float deviceDepth, float4x4 invProjMatrix) { float4 positionCS = ComputeClipSpacePosition(positionNDC, deviceDepth); float4 positionVS = mul(invProjMatrix, positionCS); // The view space uses a right-handed coordinate system. positionVS.z = -positionVS.z; return positionVS.xyz / positionVS.w; } UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture); float4 _CameraDepthTexture_TexelSize; inline float GetDepth01(float2 uv) { float rawDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(uv, 0, 0)).r; return Linear01Depth(rawDepth); } inline float GetLinearDepth(float2 uv) { float rawDepth = SAMPLE_DEPTH_TEXTURE_LOD(_CameraDepthTexture, float4(uv, 0, 0)).r; return LinearEyeDepth(rawDepth); } #endif // SSR_COMMON