Shader "Unheimlich/Portal Sky Dome" { Properties { _ZenithColor("Zenith", Color) = (0.12, 0.23, 0.38, 1) _HorizonColor("Horizon", Color) = (0.65, 0.72, 0.68, 1) _GroundColor("Below horizon", Color) = (0.07, 0.1, 0.075, 1) _SkyCube("Optional sky cubemap", Cube) = "" {} [Toggle] _UseCubemap("Use cubemap", Float) = 0 _Exposure("Exposure", Range(0,8)) = 1 _Rotation("Sky rotation", Range(0,360)) = 0 [HideInInspector] _Visibility("Visibility", Float) = 0 [HideInInspector] _InsidePortalB("Inside PortalB", Float) = 0 } SubShader { // Draw after the global skybox, but before ordinary transparent geometry. // Depth testing lets all opaque scene geometry occlude the sphere. Tags { "RenderPipeline"="UniversalPipeline" "Queue"="Transparent-100" "RenderType"="Transparent" } Pass { Tags { "LightMode"="SRPDefaultUnlit" } Cull Front ZWrite Off ZTest LEqual Blend One Zero HLSLPROGRAM #pragma target 3.5 #pragma vertex Vert #pragma fragment Frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl" #include "EnkiBilal/Include/Mask.hlsl" CBUFFER_START(UnityPerMaterial) float4 _ZenithColor, _HorizonColor, _GroundColor, _SkyCube_HDR; float _UseCubemap, _Exposure, _Rotation, _Visibility, _InsidePortalB; CBUFFER_END TEXTURECUBE(_SkyCube); SAMPLER(sampler_SkyCube); float4x4 _Mask0, _Mask1, _Mask2; struct Attributes { float3 positionOS : POSITION; }; struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; }; Varyings Vert(Attributes input) { Varyings output; output.positionWS = TransformObjectToWorld(input.positionOS); output.positionCS = TransformWorldToHClip(output.positionWS); return output; } half4 Frag(Varyings input) : SV_Target { clip(1.5 - _Visibility); if (_Visibility > 0.5 && _InsidePortalB < 0.5) { // No active portal = hidden outside. Entry explicitly exposes the full sky. float mask = SampleProjectionMask(input.positionWS, _Mask0) + SampleProjectionMask(input.positionWS, _Mask1) + SampleProjectionMask(input.positionWS, _Mask2); clip(mask - 0.5); } float3 direction = normalize(input.positionWS - _WorldSpaceCameraPos); float s, c; sincos(radians(_Rotation), s, c); direction.xz = float2(c * direction.x - s * direction.z, s * direction.x + c * direction.z); half3 color = direction.y >= 0 ? lerp(_HorizonColor.rgb, _ZenithColor.rgb, pow(saturate(direction.y), 0.55)) : lerp(_HorizonColor.rgb, _GroundColor.rgb, saturate(-direction.y * 4)); if (_UseCubemap > 0.5) color = DecodeHDREnvironment(SAMPLE_TEXTURECUBE(_SkyCube, sampler_SkyCube, direction), _SkyCube_HDR); return half4(color * _Exposure, 1); } ENDHLSL } } }