89 lines
3.1 KiB
HLSL
89 lines
3.1 KiB
HLSL
#ifndef PORTAL_PROJECTION_MASK_INCLUDED
|
|
#define PORTAL_PROJECTION_MASK_INCLUDED
|
|
|
|
// Global matrices set by Portal.cs via Shader.SetGlobalMatrix
|
|
float4x4 _PortalMatrix;
|
|
float4x4 _CameraMatrix;
|
|
|
|
// URP includes (Core pulls in the right per-draw declarations for SRP).
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl"
|
|
|
|
uint GetMyRenderingLayerMask()
|
|
{
|
|
// Returns asuint(unity_RenderingLayer.x) in URP.
|
|
return GetMeshRenderingLayer();
|
|
}
|
|
|
|
bool HasRenderingLayer(uint mask, uint layerIndex /* 0..31 */)
|
|
{
|
|
return (mask & (1u << layerIndex)) != 0u;
|
|
}
|
|
|
|
void PortalProjectionMask_float(
|
|
float3 WorldPos,
|
|
out float ClipValue
|
|
//out float3 DebugColor
|
|
)
|
|
{
|
|
// Detect shadow pass by comparing camera positions
|
|
// In shadow pass: UNITY_MATRIX_I_V contains light camera, not Main Camera
|
|
float3 currentCamPos = UNITY_MATRIX_I_V._m03_m13_m23;
|
|
float3 mainCamPos = float3(_CameraMatrix[0][3], _CameraMatrix[1][3], _CameraMatrix[2][3]);
|
|
|
|
float distanceBetweenCams = length(currentCamPos - mainCamPos);
|
|
bool isShadowPass = (distanceBetweenCams > 0.01); // Threshold for comparison
|
|
|
|
if (isShadowPass) // For viewport preview
|
|
{
|
|
if ((UNITY_MATRIX_P[0][0] != _CameraMatrix[0][0])) // Is scene view
|
|
isShadowPass = false;
|
|
}
|
|
|
|
// Don't clip in shadow pass
|
|
if (isShadowPass)
|
|
{
|
|
ClipValue = 1;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// Extract camera world position from the matrix
|
|
float3 camPosWorld = float3(_CameraMatrix[0][3], _CameraMatrix[1][3], _CameraMatrix[2][3]);
|
|
|
|
// Transform to portal local space
|
|
float3 localPixelPos = mul(_PortalMatrix, float4(WorldPos, 1)).xyz;
|
|
float3 localCamPos = mul(_PortalMatrix, float4(camPosWorld, 1)).xyz;
|
|
|
|
// Perspective projection of the pixel onto the portal plane (z=0)
|
|
float3 rayDir = localPixelPos - localCamPos;
|
|
float t = -localCamPos.z / rayDir.z;
|
|
float3 projectedPos = localCamPos + rayDir * t;
|
|
|
|
// Check if projected point is inside the quad frame [-0.5, 0.5]
|
|
bool insideFrame = (abs(projectedPos.x) < .5 && abs(projectedPos.y) < 0.5 && t > 0);
|
|
|
|
// Check if pixel is behind the portal (z > 0 in local space)
|
|
bool pixelBehind = localPixelPos.z > 0;
|
|
|
|
// Check if camera is behind the portal (z > 0 in local space)
|
|
bool camBehind = localCamPos.z < 0;
|
|
|
|
uint renderingLayer = GetMeshRenderingLayer();
|
|
//DebugColor = float3(renderingLayer & 1u, (renderingLayer >> 1) & 1u, (renderingLayer >> 2) & 1u);
|
|
|
|
if (HasRenderingLayer(renderingLayer, 1u)) // Is behind portal
|
|
{
|
|
// Next room: visible ONLY through the frame AND behind the portal
|
|
ClipValue = (insideFrame && pixelBehind && camBehind) ? 1 : 0;
|
|
}
|
|
else
|
|
{
|
|
// Active room: visible everywhere EXCEPT through the frame when behind portal
|
|
ClipValue = (insideFrame && pixelBehind && camBehind) ? 0 : 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|