#ifndef UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED #define UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED // This function always return the absolute position in WS float3 GetAbsolutePositionWS(float3 positionRWS) { #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) positionRWS += _WorldSpaceCameraPos; #endif return positionRWS; } // This function return the camera relative position in WS float3 GetCameraRelativePositionWS(float3 positionWS) { #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) positionWS -= _WorldSpaceCameraPos; #endif return positionWS; } float4x4 GetWorldToViewMatrix() { return UNITY_MATRIX_V; } // Return absolute world position of current object float3 GetObjectAbsolutePositionWS() { float4x4 modelMatrix = UNITY_MATRIX_M; return GetAbsolutePositionWS(modelMatrix._m03_m13_m23); // Translation object to world } // Return the PreTranslated ObjectToWorld Matrix (i.e matrix with _WorldSpaceCameraPos apply to it if we use camera relative rendering) float4x4 GetObjectToWorldMatrix() { return UNITY_MATRIX_M; } float4x4 GetWorldToObjectMatrix() { return UNITY_MATRIX_I_M; } // Transform to homogenous clip space float4x4 GetViewToHClipMatrix() { return UNITY_MATRIX_P; } float4x4 GetWorldToHClipMatrix() { return UNITY_MATRIX_VP; } float GetOddNegativeScale() { return unity_WorldTransformParams.w; } float3 TransformWorldToView(float3 positionRWS) { return mul(GetWorldToViewMatrix(), float4(positionRWS, 1.0)).xyz; } float3 TransformObjectToWorld(float3 positionOS) { return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz; } float3 TransformWorldToObject(float3 positionRWS) { return mul(GetWorldToObjectMatrix(), float4(positionRWS, 1.0)).xyz; } float3 TransformObjectToWorldDir(float3 dirOS) { // Normalize to support uniform scaling return normalize(mul((float3x3)GetObjectToWorldMatrix(), dirOS)); } float3 TransformWorldToViewDir(float3 dirWS) { return mul((float3x3)GetWorldToViewMatrix(), dirWS).xyz; } float3 TransformWorldToObjectDir(float3 dirWS) { // Normalize to support uniform scaling return normalize(mul((float3x3)GetWorldToObjectMatrix(), dirWS)); } // Transforms normal from object to world space float3 TransformObjectToWorldNormal(float3 normalOS) { #ifdef UNITY_ASSUME_UNIFORM_SCALING return TransformObjectToWorldDir(normalOS); #else // Normal need to be multiply by inverse transpose return normalize(mul(normalOS, (float3x3)GetWorldToObjectMatrix())); #endif } // Tranforms position from world space to homogenous space float4 TransformWorldToHClip(float3 positionRWS) { return mul(GetWorldToHClipMatrix(), float4(positionRWS, 1.0)); } // Tranforms vector from world space to homogenous space float3 TransformWorldToHClipDir(float3 directionWS) { return mul((float3x3)GetWorldToHClipMatrix(), directionWS); } // Tranforms position from view space to homogenous space float4 TransformWViewToHClip(float3 positionVS) { return mul(GetViewToHClipMatrix(), float4(positionVS, 1.0)); } // Tranforms vector from world space to homogenous space float3 TransformViewToHClipDir(float3 directionVS) { return mul((float3x3)GetViewToHClipMatrix(), directionVS); } float3 GetPrimaryCameraPosition() { #if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0) return float3(0, 0, 0); #else return _WorldSpaceCameraPos; #endif } // Could be e.g. the position of a primary camera or a shadow-casting light. float3 GetCurrentViewPosition() { #if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS) return GetPrimaryCameraPosition(); #else // This is a generic solution. // However, using '_WorldSpaceCameraPos' is better for cache locality, // and in case we enable camera-relative rendering, we can statically set the position is 0. return UNITY_MATRIX_I_V._14_24_34; #endif } // Returns the forward (central) direction of the current view in the world space. float3 GetViewForwardDir() { float4x4 viewMat = GetWorldToViewMatrix(); return -viewMat[2].xyz; } // Returns 'true' if the current view performs a perspective projection. bool IsPerspectiveProjection() { #if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS) return (unity_OrthoParams.w == 0); #else // This is a generic solution. // However, using 'unity_OrthoParams' is better for cache locality. // TODO: set 'unity_OrthoParams' during the shadow pass. return UNITY_MATRIX_P[3][3] == 0; #endif } // Computes the world space view direction (pointing towards the viewer). float3 GetWorldSpaceViewDir(float3 positionRWS) { if (IsPerspectiveProjection()) { // Perspective return GetCurrentViewPosition() - positionRWS; } else { // Orthographic return -GetViewForwardDir(); } } float3 GetWorldSpaceNormalizeViewDir(float3 positionRWS) { return normalize(GetWorldSpaceViewDir(positionRWS)); } float3x3 CreateWorldToTangent(float3 normal, float3 tangent, float flipSign) { // For odd-negative scale transforms we need to flip the sign float sgn = flipSign * GetOddNegativeScale(); float3 bitangent = cross(normal, tangent) * sgn; return float3x3(tangent, bitangent, normal); } float3 TransformTangentToWorld(float3 dirTS, float3x3 worldToTangent) { // Use transpose transformation to go from tangent to world as the matrix is orthogonal return mul(dirTS, worldToTangent); } float3 TransformWorldToTangent(float3 dirWS, float3x3 worldToTangent) { return mul(worldToTangent, dirWS); } float3 TransformTangentToObject(float3 dirTS, float3x3 worldToTangent) { // Use transpose transformation to go from tangent to world as the matrix is orthogonal float3 normalWS = mul(dirTS, worldToTangent); return mul((float3x3)GetWorldToObjectMatrix(), normalWS); } float3 TransformObjectToTangent(float3 dirOS, float3x3 worldToTangent) { return mul(worldToTangent, TransformObjectToWorldDir(dirOS)); } // UNITY_MATRIX_V defines a right-handed view space with the Z axis pointing towards the viewer. // This function reverses the direction of the Z axis (so that it points forward), // making the view space coordinate system left-handed. void GetLeftHandedViewSpaceMatrices(out float4x4 viewMatrix, out float4x4 projMatrix) { viewMatrix = UNITY_MATRIX_V; viewMatrix._31_32_33_34 = -viewMatrix._31_32_33_34; projMatrix = UNITY_MATRIX_P; projMatrix._13_23_33_43 = -projMatrix._13_23_33_43; } // This method should be used for rendering any full screen quad that uses an auto-scaling Render Targets (see RTHandle/HDCamera) // It will account for the fact that the textures it samples are not necesarry using the full space of the render texture but only a partial viewport. float2 GetNormalizedFullScreenTriangleTexCoord(uint vertexID) { return GetFullScreenTriangleTexCoord(vertexID) * _ScreenToTargetScale.xy; } // The size of the render target can be larger than the size of the viewport. // This function returns the fraction of the render target covered by the viewport: // ViewportScale = ViewportResolution / RenderTargetResolution. // Do not assume that their size is the same, or that sampling outside of the viewport returns 0. float2 GetViewportScaleCurrentFrame() { return _ScreenToTargetScale.xy; } float2 GetViewportScalePreviousFrame() { return _ScreenToTargetScale.zw; } #endif // UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED