Files

115 lines
3.9 KiB
Plaintext

// Equirectangular skybox with a blurred nadir, for hiding whoever was carrying the camera.
// Drop-in replacement for Skybox/Panoramic (mono, latitude-longitude layout).
//
// REQUIRED: the source texture must have mip maps enabled, or nothing will blur.
// RenderTexture: tick "Mip Maps" on the asset (auto-generate is on by default).
// Still image: tick "Generate Mip Maps" in the import settings.
Shader "Skybox/PanoramicNadirBlur"
{
Properties
{
[NoScaleOffset] _MainTex ("Equirectangular Texture", 2D) = "grey" {}
_Tint ("Tint Color", Color) = (0.5, 0.5, 0.5, 0.5)
[Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0
_Rotation ("Rotation", Range(0, 360)) = 0
[Header(Nadir Blur)]
_BlurStartAngle ("Blur Starts (deg below horizon)", Range(0, 90)) = 40
_BlurFullAngle ("Fully Blurred (deg below horizon)", Range(0, 90)) = 65
_BlurStrength ("Blur Strength (mip level)", Range(0, 10)) = 6
}
SubShader
{
Tags { "Queue" = "Background" "RenderType" = "Background" "PreviewType" = "Skybox" }
Cull Off
ZWrite Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 3.0
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _Tint;
half _Exposure;
float _Rotation;
float _BlurStartAngle;
float _BlurFullAngle;
float _BlurStrength;
float3 RotateAroundYInDegrees(float3 vertex, float degrees)
{
float alpha = degrees * UNITY_PI / 180.0;
float sina, cosa;
sincos(alpha, sina, cosa);
float2x2 m = float2x2(cosa, -sina, sina, cosa);
return float3(mul(m, vertex.xz), vertex.y).xzy;
}
struct appdata_t
{
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 texcoord : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert(appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
float3 rotated = RotateAroundYInDegrees(v.vertex.xyz, _Rotation);
o.vertex = UnityObjectToClipPos(rotated);
o.texcoord = v.vertex.xyz;
return o;
}
// Matches Unity's Skybox/Panoramic mapping so orientation is unchanged.
inline float2 ToRadialCoords(float3 coords)
{
float3 nc = normalize(coords);
float latitude = acos(nc.y);
float longitude = atan2(nc.z, nc.x);
float2 sphereCoords = float2(longitude, latitude) * float2(0.5 / UNITY_PI, 1.0 / UNITY_PI);
return float2(0.5, 1.0) - sphereCoords;
}
fixed4 frag(v2f i) : SV_Target
{
float3 dir = normalize(i.texcoord);
float2 uv = ToRadialCoords(dir);
// Elevation in degrees: +90 straight up, 0 at the horizon, -90 straight down.
float elevation = degrees(asin(dir.y));
// 0 above the start angle, ramping to 1 by the full angle.
float t = 1.0 - smoothstep(-_BlurFullAngle, -_BlurStartAngle, elevation);
// Sampling a coarser mip is the cheap way to blur: no extra taps.
float lod = t * _BlurStrength;
half4 tex = tex2Dlod(_MainTex, float4(uv, 0.0, lod));
half3 col = tex.rgb * _Tint.rgb * unity_ColorSpaceDouble.rgb * _Exposure;
return half4(col, 1.0);
}
ENDCG
}
}
Fallback Off
}