392 lines
10 KiB
Plaintext
392 lines
10 KiB
Plaintext
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
|
|
|
|
Shader "TENKOKU/TenkokuFog" {
|
|
|
|
Properties {
|
|
_MainTex ("Base (RGB)", 2D) = "black" {}
|
|
_SkyTex ("Base (RGB)", 2D) = "black" {}
|
|
//_FogDistance("Fog Distance",Float) = 1.0
|
|
}
|
|
|
|
|
|
|
|
CGINCLUDE
|
|
|
|
#pragma target 3.0
|
|
#include "UnityCG.cginc"
|
|
#include "Lighting.cginc"
|
|
|
|
uniform sampler2D _MainTex, _SkyTex;
|
|
uniform sampler2D_float _CameraDepthTexture;
|
|
sampler2D _CameraDepthNormalsTexture;
|
|
|
|
uniform float4 _HeightParams;
|
|
|
|
// x = start distance
|
|
uniform float4 _DistanceParams;
|
|
|
|
int4 _SceneFogMode;
|
|
float4 _SceneFogParams;
|
|
|
|
|
|
|
|
float _Tenkoku_FogStart;
|
|
float _Tenkoku_FogEnd;
|
|
|
|
|
|
uniform float4 _MainTex_TexelSize;
|
|
|
|
// for fast world space reconstruction
|
|
uniform float4x4 _FrustumCornersWS;
|
|
uniform float4 _CameraWS;
|
|
|
|
half4 _Tenkoku_FogColor;
|
|
float _fogSkybox;
|
|
float _fogHorizon;
|
|
float _FogStart;
|
|
float _FogDistance;
|
|
float _camDistance;
|
|
|
|
float _Tenkoku_Ambient;
|
|
float _Tenkoku_AmbientGI;
|
|
float _Tenkoku_AtmosphereDensity;
|
|
float _Tenkoku_FogDensity;
|
|
float4 _Tenkoku_overcastColor;
|
|
float _Tenkoku_overcastAmt;
|
|
float _tenkokufogFull;
|
|
|
|
float4 Tenkoku_Vec_SunFwd;
|
|
float4 Tenkoku_Vec_MoonFwd;
|
|
float4 Tenkoku_Vec_LightningFwd;
|
|
float4 Tenkoku_LightningColor;
|
|
|
|
float4x4 _Tenkoku_CameraMV;
|
|
samplerCUBE _Tenkoku_EnvironmentCube;
|
|
samplerCUBE _Tenkoku_SkyCube;
|
|
samplerCUBE _Tenkoku_SnowCube;
|
|
sampler2D _Tenkoku_TexFX;
|
|
sampler2D _Tenkoku_ParticleTex;
|
|
|
|
|
|
sampler2D _HeatDistortText;
|
|
float _Tenkoku_HeatDistortAmt;
|
|
float _HeatDistortSpeed;
|
|
float _HeatDistortScale;
|
|
float _HeatDistortDist;
|
|
float _tenkoku_rainbowFac1, _tenkoku_rainbowFac2;
|
|
float Tenkoku_LightningLightIntensity;
|
|
float _Tenkoku_shaderDepth;
|
|
float _Tenkoku_FadeDistance;
|
|
float _Tenkoku_FogObscurance;
|
|
float _Tenkoku_UseElek;
|
|
|
|
sampler2D _Tenkoku_SkyTex;
|
|
sampler2D _Tenkoku_SkyBox;
|
|
|
|
|
|
struct v2f {
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
float2 uv_depth : TEXCOORD1;
|
|
float4 interpolatedRay : TEXCOORD2;
|
|
float4 screenPos: TEXCOORD3;
|
|
};
|
|
|
|
v2f vert (appdata_img v)
|
|
{
|
|
v2f o;
|
|
half index = v.vertex.z;
|
|
v.vertex.z = 0.1;
|
|
o.pos = UnityObjectToClipPos(v.vertex);
|
|
o.screenPos=ComputeScreenPos(o.pos);
|
|
|
|
o.uv = v.texcoord.xy;
|
|
o.uv_depth = v.texcoord.xy;
|
|
|
|
#if UNITY_UV_STARTS_AT_TOP
|
|
if (_MainTex_TexelSize.y < 0){
|
|
o.uv.y = 1-o.uv.y;
|
|
}
|
|
#endif
|
|
|
|
|
|
//set frustrum indexes specifically
|
|
// this fixes fog/effect errors under webGL
|
|
if (0 == (int)index)
|
|
o.interpolatedRay = _FrustumCornersWS[0];
|
|
else if (1 == (int)index)
|
|
o.interpolatedRay = _FrustumCornersWS[1];
|
|
else if (2 == (int)index)
|
|
o.interpolatedRay = _FrustumCornersWS[2];
|
|
else
|
|
o.interpolatedRay = _FrustumCornersWS[3];
|
|
|
|
//o.interpolatedRay.w = index;
|
|
|
|
|
|
return o;
|
|
}
|
|
|
|
|
|
// Distance-based fog
|
|
float ComputeDistance (float3 camDir, float zdepth)
|
|
{
|
|
float dist;
|
|
if (_SceneFogMode.y == 1)
|
|
dist = length(camDir);
|
|
else
|
|
dist = zdepth;// * _ProjectionParams.z;
|
|
|
|
return dist;
|
|
}
|
|
|
|
// Linear half-space fog, from https://www.terathon.com/lengyel/Lengyel-UnifiedFog.pdf
|
|
float ComputeHalfSpace (float3 wsDir)
|
|
{
|
|
float3 wpos = _CameraWS + wsDir;
|
|
float FH = _HeightParams.x;
|
|
float3 C = _CameraWS;
|
|
float3 V = wsDir;
|
|
float3 P = wpos;
|
|
float3 aV = _HeightParams.w * V;
|
|
float FdotC = _HeightParams.y;
|
|
float k = _HeightParams.z;
|
|
float FdotP = P.y-FH;
|
|
float FdotV = wsDir.y;
|
|
float c1 = k * (FdotP + FdotC);
|
|
float c2 = (1-2*k) * FdotP;
|
|
float g = min(c2, 0.0);
|
|
g = -length(aV) * (c1 - g * g / abs(FdotV+1.0e-5f));
|
|
return g;
|
|
}
|
|
|
|
half4 ComputeFog (v2f i, bool distance, bool height) : SV_Target
|
|
{
|
|
|
|
|
|
|
|
//------ Turned off temporarily --------------
|
|
//CALCULATE VIEW NORMALS
|
|
//float3 normalValues;
|
|
//float depthValue;
|
|
//DecodeDepthNormal(tex2D(_CameraDepthNormalsTexture, i.screenPos.xy), depthValue, normalValues);
|
|
//float4 viewNormalColor = float4(normalValues, 1);
|
|
|
|
//GET WORLD NORMAL CUBEMAP
|
|
//float4 worldNormalColor = texCUBE(_Tenkoku_EnvironmentCube,mul(_Tenkoku_CameraMV, float4(normalValues, 0)).xyz);
|
|
|
|
//GET SKY CUBEMAP
|
|
//float4 skyCube = texCUBE(_Tenkoku_SkyCube,mul(_Tenkoku_CameraMV, float4(normalValues, 0)).xyz);
|
|
// --------
|
|
|
|
|
|
|
|
// Reconstruct world space position & direction
|
|
// towards this screen pixel.
|
|
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
|
|
float dpth = Linear01Depth(rawDepth);
|
|
float4 wsDir = dpth * i.interpolatedRay;
|
|
|
|
|
|
//CALCULATE FOG
|
|
float diff = _Tenkoku_FogEnd - _Tenkoku_FogStart;
|
|
float invDiff = abs(diff) > 0.0001f ? 1.0 / diff : 0.0;
|
|
_SceneFogParams.z = -invDiff;
|
|
_SceneFogParams.w = _Tenkoku_FogEnd * invDiff;
|
|
half usedpth = _DistanceParams.z + ComputeDistance(wsDir, dpth) + ComputeHalfSpace (wsDir);
|
|
half fogFac = (saturate(max(0.0,usedpth) * _SceneFogParams.z + _SceneFogParams.w));
|
|
|
|
|
|
|
|
//CALCULATE HEAT EFFECT OVERLAY
|
|
half heatDistFac = (saturate(max(0.0,usedpth) * _SceneFogParams.z + _SceneFogParams.w));
|
|
heatDistFac += (saturate(wsDir.y/2000));
|
|
heatDistFac = saturate(lerp(half(1),half(0-_HeatDistortDist),heatDistFac));
|
|
|
|
half3 distortTex = UnpackNormal(tex2D(_HeatDistortText,i.uv*_HeatDistortScale+float2(0.0,-_Time.x*_HeatDistortSpeed)));
|
|
half2 dUV = i.uv;
|
|
dUV.x += (distortTex.x * (_Tenkoku_HeatDistortAmt*(heatDistFac)));
|
|
|
|
|
|
i.uv_depth = dUV;
|
|
i.uv = dUV;
|
|
|
|
#if UNITY_UV_STARTS_AT_TOP
|
|
if (_MainTex_TexelSize.y < 0){
|
|
i.uv_depth.y = 1.0-i.uv_depth.y;
|
|
}
|
|
#endif
|
|
float2 uvx = i.uv_depth;
|
|
|
|
//Recalculate Depth with Heat Distortion
|
|
rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv_depth);
|
|
dpth = Linear01Depth(rawDepth);
|
|
wsDir = dpth * i.interpolatedRay;
|
|
|
|
|
|
//Get Scene Color Info
|
|
half4 sceneColor = tex2D(_MainTex, i.uv);
|
|
|
|
|
|
//Recalculate fog with heat distortion
|
|
diff = _Tenkoku_FogEnd - _Tenkoku_FogStart;
|
|
invDiff = abs(diff) > 0.0001f ? 1.0 / diff : 0.0;
|
|
_SceneFogParams.z = -invDiff;
|
|
_SceneFogParams.w = _Tenkoku_FogEnd * invDiff;
|
|
usedpth = _DistanceParams.z + ComputeDistance(wsDir, dpth) + ComputeHalfSpace (wsDir);
|
|
fogFac = (saturate(max(0.0,usedpth) * _SceneFogParams.z + _SceneFogParams.w));
|
|
|
|
|
|
|
|
// Handle skybox fog
|
|
if (dpth == 1.0){
|
|
if (_fogSkybox == 1.0){
|
|
fogFac = 1.0;
|
|
}
|
|
if (_fogSkybox == 0.0){
|
|
fogFac = 0.0;
|
|
}
|
|
}
|
|
|
|
|
|
fogFac = saturate(fogFac+saturate(lerp(half(1.0),half(0.0),_Tenkoku_AtmosphereDensity*2.0)));
|
|
|
|
//Handle Horizon Fog
|
|
float diff2 = _tenkokufogFull - (10.0);
|
|
float invDiff2 = abs(diff2) > 0.0001f ? 1.0 / diff2 : 0.0;
|
|
half fogFac3 = saturate(max(0.0,usedpth) * -invDiff2 + (_tenkokufogFull * invDiff2));
|
|
|
|
if (_fogHorizon == 1.0){
|
|
fogFac *= saturate((wsDir.y/min(_tenkokufogFull,250.0)) + fogFac3);
|
|
}
|
|
|
|
|
|
|
|
//read texture mipmap based on depth
|
|
half colFac = 1;
|
|
if (dpth >= 1.0){
|
|
colFac = 0;
|
|
}
|
|
|
|
//_SkyTex
|
|
half4 skyColor = tex2Dlod(_Tenkoku_SkyTex, float4(uvx.x,uvx.y,0,0));
|
|
half4 skyBox = tex2Dlod(_Tenkoku_SkyBox, float4(uvx.x,uvx.y,0,0));
|
|
|
|
|
|
skyColor = lerp(half4(skyColor),half4(skyColor * _Tenkoku_FogColor),_Tenkoku_FogColor.a * (colFac));
|
|
|
|
|
|
half4 fCol = lerp(half4(skyColor), half4(sceneColor), fogFac);
|
|
|
|
|
|
|
|
//DARKEN FOG
|
|
if (dpth < 1.0){
|
|
half tcM1 = lerp(half(0.98),half(0.4),saturate(lerp(float(0),float(1.0),saturate(_Tenkoku_overcastColor.a))));
|
|
fCol = fCol * half4(tcM1,tcM1,tcM1,tcM1);
|
|
|
|
}
|
|
|
|
|
|
fCol.rgb = lerp(half3(fCol.rgb), half3(fCol.rgb)*half3(0.65,0.65,0.65), saturate(_Tenkoku_overcastColor.a*4.0));
|
|
|
|
|
|
//Blend Fog Obscurance
|
|
fCol.rgb = lerp(fCol.rgb, skyBox, (1.0-fogFac) * _Tenkoku_FogObscurance);
|
|
|
|
|
|
|
|
//set overall fog density
|
|
if (dpth < 1.0){
|
|
fCol = lerp(half4(sceneColor), half4(fCol), _Tenkoku_FogDensity);
|
|
|
|
//lightning
|
|
half lVec = saturate(dot(Tenkoku_Vec_LightningFwd.xyz, normalize( i.interpolatedRay.xyz))) - 0.1;
|
|
fCol.rgb = lerp(half3(fCol.rgb), half3(Tenkoku_LightningColor.rgb), (1-fogFac) * 2.6 * lVec * saturate(lerp(float(1.0),float(0.2),rawDepth)) * Tenkoku_LightningLightIntensity * 0.2f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dpth >= 1.0){
|
|
if (_Tenkoku_UseElek == 1.0){
|
|
fCol = sceneColor;
|
|
}
|
|
fCol = lerp(half4(fCol), half4(sceneColor), saturate(lerp(-0.1,1.0, ((dot(half3(0,1,0), half3(i.interpolatedRay.xyz))*0.0005)))));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Fade Into Background
|
|
float diff3 = _camDistance - (_camDistance*0.1);
|
|
invDiff2 = abs(diff3) > 0.0001f ? 1.0 / diff3 : 0.0;
|
|
float fogFacX = (saturate(max(0.0,usedpth) * -invDiff2 + (_camDistance * invDiff2)));
|
|
float skDepth = saturate(lerp((float(-1.1)-(_Tenkoku_FadeDistance*lerp(float(1),float(50),_Tenkoku_FadeDistance))), 1.0, 1.0-fogFacX));
|
|
|
|
fCol = lerp(fCol,skyBox,skDepth);
|
|
|
|
|
|
|
|
|
|
|
|
//RENDER RAINBOWS
|
|
half3 origCol = fCol.rgb;
|
|
half3 rainCol = 0;
|
|
half3 rainCol2 = 0;
|
|
half rFac = saturate((fCol.r*0.4) + (fCol.g*0.8) + (fCol.b*0.5));
|
|
half rVec = saturate(dot(Tenkoku_Vec_SunFwd.xyz, normalize( -i.interpolatedRay.xyz))) - 0.1;
|
|
half rVec2 = saturate(dot(Tenkoku_Vec_SunFwd.xyz, normalize( -i.interpolatedRay.xyz)) + 0.1);
|
|
|
|
//primary
|
|
half rS1 = 12;
|
|
rainCol.rgb = lerp(rainCol,half3(1.7,0,0),saturate(lerp(float(0.0-rS1), float(rS1), rVec))); //red
|
|
rainCol.rgb = lerp(rainCol,half3(0,1.0,0),saturate(lerp(float(0.0-rS1-0.2), float(rS1),rVec))); //green
|
|
rainCol.rgb = lerp(rainCol,half3(0,0,1.0),saturate(lerp(float(0.0-rS1-1.0), float(rS1),rVec))); //blue
|
|
rainCol.rgb = lerp(rainCol,half3(0.2,0.15,0.1),saturate(lerp(float(0.0-rS1-1.0), float(rS1),rVec)));
|
|
|
|
fCol.rgb = lerp(fCol.rgb, fCol.rgb - (rainCol.r*0.5) + rainCol*2, saturate(dot(Tenkoku_Vec_SunFwd.xyz, half3(0,1,0)-0.1)) * saturate(lerp(1.0,-2.0,fogFac)) * _tenkoku_rainbowFac1 * rFac );
|
|
|
|
//secondary
|
|
half rS2 = 8;
|
|
rainCol2 = lerp(half3(rainCol2), half3(0.0,0.0,1.0), saturate(lerp(float(0.0-rS2), float(rS2), rVec2))); //blue
|
|
rainCol2 = lerp(half3(rainCol2), half3(0.0,1.0,0.0), saturate(lerp(float(0.0-rS2-0.2), float(rS2),rVec2))); //green
|
|
rainCol2 = lerp(half3(rainCol2), half3(1.2,0.0,0.0), saturate(lerp(float(0.0-rS2-1.0), float(rS2),rVec2))); //red
|
|
rainCol2 = lerp(half3(rainCol2), half3(0.0,0.0,0.0), saturate(lerp(float(0.0-rS2-1.0), float(rS2),rVec2)));
|
|
|
|
half tcM2 = rainCol2.r*0.5;
|
|
fCol.rgb = lerp(fCol.rgb, fCol.rgb - half3(tcM2,tcM2,tcM2) + rainCol2*2, saturate(dot(float3(Tenkoku_Vec_SunFwd.xyz), float3(0.0,1.0,0.0))) * saturate(lerp(float(0.8),float(-5.0),fogFac)) * (_tenkoku_rainbowFac2 * rFac * 0.73) );
|
|
|
|
|
|
|
|
|
|
|
|
return fCol;
|
|
}
|
|
|
|
ENDCG
|
|
|
|
SubShader
|
|
{
|
|
|
|
Tags { "RenderType"="Opaque" }
|
|
ZTest Always Cull Off ZWrite Off Fog { Mode Off }
|
|
|
|
// 0: distance + height
|
|
Pass
|
|
{
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
half4 frag (v2f i) : SV_Target { return ComputeFog (i, true, true); }
|
|
ENDCG
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Fallback off
|
|
|
|
}
|