196 lines
6.6 KiB
HLSL
196 lines
6.6 KiB
HLSL
#ifndef BEAUTIFY_PPSSF_FX
|
|
#define BEAUTIFY_PPSSF_FX
|
|
|
|
// Copyright 2020-2021 Kronnect - All Rights Reserved.
|
|
#include "BeautifyCommon.hlsl"
|
|
|
|
TEXTURE2D_X(_MainTex);
|
|
TEXTURE2D(_FlareTex);
|
|
TEXTURE2D(_OcclusionTex);
|
|
|
|
float4 _MainTex_ST;
|
|
float4 _MainTex_TexelSize;
|
|
float4 _SunPos;
|
|
float3 _SunDir;
|
|
float4 _SunData; // x = sunIntensity, y = disk size, z = ray difraction, w = ray difraction amount
|
|
float4 _SunCoronaRays1; // x = length, y = streaks, z = spread, w = angle offset
|
|
float4 _SunCoronaRays2; // x = length, y = streaks, z = spread, w = angle offset
|
|
float4 _SunGhosts1; // x = reserved, y = size, 2 = pos offset, 3 = brightness
|
|
float4 _SunGhosts2; // x = reserved, y = size, 2 = pos offset, 3 = brightness
|
|
float4 _SunGhosts3; // x = reserved, y = size, 2 = pos offset, 3 = brightness
|
|
float4 _SunGhosts4; // x = reserved, y = size, 2 = pos offset, 3 = brightness
|
|
float3 _SunHalo; // x = offset, y = amplitude, z = intensity
|
|
float4 _SunTint;
|
|
float _SunFlaresAspectRatio;
|
|
float _SunOcclusionThreshold;
|
|
#define SUN_TINT_COLOR _SunTint.rgb
|
|
#define OCCLUSION_SPEED _SunTint.a
|
|
#define OCCLUSION_THRESHOLD _SunOcclusionThreshold
|
|
|
|
struct VaryingsSF {
|
|
float4 positionCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float2 sunPos : TEXCOORD1;
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
VaryingsSF VertSF(AttributesSimple input) {
|
|
VaryingsSF output;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
|
output.positionCS = input.positionOS;
|
|
output.positionCS.y *= _ProjectionParams.x * _FlipY;
|
|
output.uv = input.uv.xy;
|
|
|
|
float4 clipPos = TransformWorldToHClip(_WorldSpaceCameraPos.xyz - _SunDir.xyz * 1000.0);
|
|
float2 sunPos = float2(clipPos.x, clipPos.y * _ProjectionParams.x) * 0.5 / clipPos.w + 0.5;
|
|
output.sunPos = sunPos;
|
|
|
|
return output;
|
|
}
|
|
|
|
void rotate(inout float2 uv, float ang) {
|
|
float2 sico;
|
|
sincos(ang, sico.x, sico.y);
|
|
float2 cosi = float2(sico.y, -sico.x);
|
|
uv = float2(dot(cosi, uv), dot(sico, uv));
|
|
}
|
|
|
|
float3 sunflare(VaryingsSF input) {
|
|
|
|
// general params
|
|
float2 uv = input.uv;
|
|
float2 sunPos = input.sunPos;
|
|
|
|
#if BEAUTIFY_SF_OCCLUSION_SIMPLE
|
|
float depth = BEAUTIFY_GET_SCENE_DEPTH_01(sunPos);
|
|
if (depth < 1.0) return 0;
|
|
const float occlusion = 1.0;
|
|
#elif BEAUTIFY_SF_OCCLUSION_SMOOTH
|
|
float occlusion = SAMPLE_TEXTURE2D(_OcclusionTex, sampler_LinearRepeat, float2(0,0)).r;
|
|
if (occlusion <= 0.02) return 0.0.xxx;
|
|
#else
|
|
const float occlusion = 1.0;
|
|
#endif
|
|
|
|
float2 grd = uv - sunPos;
|
|
float aspectRatio = _SunFlaresAspectRatio;
|
|
grd.y *= aspectRatio;
|
|
float len = length(grd);
|
|
|
|
// sun disk
|
|
float s0 = pow( 1.0 + saturate(_SunData.y - len), 75) - 1.0;
|
|
|
|
// corona rays
|
|
float gang = _SunPos.w; //atan2(0.5 - sunPos.y, sunPos.x - 0.5);
|
|
float ang = atan2(grd.y, grd.x) + gang;
|
|
float ray1 = _SunCoronaRays1.z + abs(_SunCoronaRays1.x * cos(_SunCoronaRays1.w + ang * _SunCoronaRays1.y)); // design
|
|
ray1 *= pow( 1.0 + len, 1.0/_SunCoronaRays1.x);
|
|
s0 += 1.0 / ray1;
|
|
|
|
float ray2 = _SunCoronaRays2.z + abs(_SunCoronaRays2.x * sin(_SunCoronaRays2.w + ang * _SunCoronaRays2.y)); // design
|
|
ray2 *= pow( 1.0 + len, 1.0/_SunCoronaRays2.x);
|
|
s0 += 1.0 / ray2;
|
|
|
|
s0 *= _SunData.x;
|
|
|
|
float3 flare = s0.xxx;
|
|
|
|
#if BEAUTIFY_SF_USE_GHOSTS // defined(UNITY_SINGLE_PASS_STEREO) && !defined(UNITY_STEREO_INSTANCING_ENABLED) && !defined(UNITY_STEREO_MULTIVIEW_ENABLED)
|
|
// ghosts circular (not compatible with XR due to how projection works)
|
|
|
|
float2 ghost1Pos = 1.0 - sunPos;
|
|
grd = uv - ghost1Pos + (ghost1Pos - 0.5) * _SunGhosts1.z;
|
|
grd.y *= aspectRatio;
|
|
|
|
float g0 = saturate(_SunGhosts1.y / length(grd));
|
|
g0 = pow(g0, 12);
|
|
flare += g0 * _SunGhosts1.w / len;
|
|
|
|
float2 ghost2Pos = 1.0 - sunPos;
|
|
grd = uv - ghost2Pos + (ghost2Pos - 0.5) * _SunGhosts2.z;
|
|
grd.y *= aspectRatio;
|
|
g0 = saturate(_SunGhosts2.y / length(grd));
|
|
g0 = pow(g0, 12);
|
|
flare += g0 * _SunGhosts2.w / len;
|
|
|
|
float2 ghost3Pos = 1.0 - sunPos;
|
|
grd = uv - ghost3Pos + (ghost3Pos - 0.5) * _SunGhosts3.z;
|
|
grd.y *= aspectRatio;
|
|
g0 = saturate(_SunGhosts3.y / length(grd));
|
|
g0 = pow(g0, 12);
|
|
flare += g0 * _SunGhosts3.w / len;
|
|
|
|
float2 ghost4Pos = 1.0 - sunPos;
|
|
grd = uv - ghost4Pos + (ghost4Pos - 0.5) * _SunGhosts4.z;
|
|
grd.y *= aspectRatio;
|
|
g0 = saturate(_SunGhosts4.y / length(grd));
|
|
g0 = pow(g0, 12);
|
|
flare += g0 * _SunGhosts4.w / len;
|
|
|
|
#endif
|
|
|
|
// light rays
|
|
float2 uv2 = uv - sunPos;
|
|
float clen = length(uv2);
|
|
rotate(uv2, gang);
|
|
uv2.x *= aspectRatio;
|
|
uv2.x *= 0.1;
|
|
uv2 /= len;
|
|
float lr = saturate(SAMPLE_TEXTURE2D(_FlareTex, sampler_LinearRepeat, uv2 + _SunPos.zz).r - _SunData.w);
|
|
float3 rays = lr * sin(float3(len, len + 0.1, len + 0.2) * 3.1415927);
|
|
float atten = pow(1.0 + clen, 13.0);
|
|
rays *= _SunData.z / atten;
|
|
flare += rays;
|
|
|
|
// halo
|
|
float hlen = clamp( (len - _SunHalo.x) * _SunHalo.y, 0, 3.1415927);
|
|
float3 halo = pow(sin(float3(hlen, hlen + 0.1, hlen + 0.2)), 12.0.xxx);
|
|
halo *= _SunHalo.z / atten;
|
|
flare += halo;
|
|
|
|
return max(0, flare * SUN_TINT_COLOR * occlusion);
|
|
}
|
|
|
|
float4 FragSF (VaryingsSF i) : SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
//i.uv = UnityStereoTransformScreenSpaceTex(i.uv);
|
|
|
|
return float4(sunflare(i), 1.0);
|
|
}
|
|
|
|
float4 FragSFAdditive (VaryingsSF i) : SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
|
|
float2 stereoUV = UnityStereoTransformScreenSpaceTex(i.uv);
|
|
|
|
float4 p = SAMPLE_TEXTURE2D_X(_MainTex, sampler_LinearClamp, stereoUV);
|
|
return p + float4(sunflare(i), 1.0);
|
|
}
|
|
|
|
float GetDepth(float2 sunPos, float2 offset) {
|
|
float2 pos = saturate(sunPos + offset * _MainTex_TexelSize.xy);
|
|
return BEAUTIFY_GET_SCENE_DEPTH_01(pos);
|
|
}
|
|
|
|
float OcclusionTest(float2 sunPos) {
|
|
|
|
float depth1 = GetDepth(sunPos, float2(-1, -1));
|
|
float depth2 = GetDepth(sunPos, float2( 1, 1));
|
|
float depth3 = GetDepth(sunPos, float2( 3, 3));
|
|
float depth4 = GetDepth(sunPos, float2(-3, -3));
|
|
float occlusion = (depth1 + depth2 + depth3 + depth4) * 0.25;
|
|
occlusion *= step(OCCLUSION_THRESHOLD, occlusion);
|
|
return occlusion;
|
|
}
|
|
|
|
float4 FragSFOcclusion (VaryingsSF input) : SV_Target {
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
float occlusion = OcclusionTest(input.sunPos);
|
|
#if BEAUTIFY_SF_OCCLUSION_INIT
|
|
return float4(occlusion, occlusion, occlusion, 1.0);
|
|
#else
|
|
return float4(occlusion, occlusion, occlusion, unity_DeltaTime.x * OCCLUSION_SPEED);
|
|
#endif
|
|
}
|
|
|
|
#endif |