You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
7.1 KiB

Shader "Hidden/RayCastCloud"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }
CGINCLUDE
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile __ DEBUG
#pragma multi_compile __ MIPMAP
#pragma multi_compile __ MULTNOISE
#include "UnityCG.cginc"
#include "../RayCast.cginc"
#pragma target 3.0
sampler2D _MainTex;
sampler2D _CloudTex;
sampler2D _CameraDepthTexture;
float3 _SunGlareColor;
float3 _Color1;
float4 _SunSSSColor;
float3 _Color3;
float3 _Color4;
float cloud_thickness;
float cloud_position;
float cloud_freq1;
float cloud_freq2;
float cloud_freq3;
float cloud_freq4;
float cloud_freq5;
float near1;
float far1;
float near2;
int rayIteratorCount;
float4 _SunDirection;
static float3 sundir = normalize( _SunDirection.xyz );
float3 winddir;
float hash( float n ) { return frac(sin(n)*43758.5453); }
float noise( in float3 x )
{
float3 p = floor(x);
float3 f = frac(x);
f = f * f * (3.0 - 2.0 * f);
float n = p.x + p.y * 57.0 + 113.0 * p.z;
float rgx = lerp(lerp( hash(n + 0.0), hash(n + 1.0),f.x), lerp( hash(n + 57.0), hash(n + 58.0),f.x), f.y);
float rgy = lerp(lerp( hash(n + 113.0), hash(n + 114.0),f.x), lerp( hash(n + 170.0), hash(n + 171.0),f.x), f.y);
return -1.0 + 2.0 * lerp(rgx, rgy, f.z);
}
#if MULTNOISE
#define FBM_O1 f += cloud_freq1 * noise( q - winddir * _Time.y ); q = q*2.02;
#define FBM_O2 f += f * cloud_freq2 * noise( q - winddir * _Time.y ); q = q*2.03;
#define FBM_O3 f += f * cloud_freq3 * noise( q - winddir * _Time.y ); q = q*2.01;
#define FBM_O4 f += f * cloud_freq4 * noise( q - winddir * _Time.y ); q = q*2.02;
#define FBM_O5 f += f * cloud_freq5 * noise( q - winddir * _Time.y );
#else
#define FBM_O1 f += cloud_freq1 * noise( q - winddir * _Time.y ); q = q*2.02;
#define FBM_O2 f += cloud_freq2 * noise( q - winddir * _Time.y ); q = q*2.03;
#define FBM_O3 f += cloud_freq3 * noise( q - winddir * _Time.y ); q = q*2.01;
#define FBM_O4 f += cloud_freq4 * noise( q - winddir * _Time.y ); q = q*2.02;
#define FBM_O5 f += cloud_freq5 * noise( q - winddir * _Time.y );
#endif
#define FBM5 FBM_O1 FBM_O2 FBM_O3 FBM_O4 FBM_O5
#define FBM4 FBM_O1 FBM_O2 FBM_O3 FBM_O4
#define FBM3 FBM_O1 FBM_O2 FBM_O3
#define FBM2 FBM_O1 FBM_O2
#define FBM(func) \
float3 q = p; \
q.y -= cloud_position; \
float f = 0; \
func \
return clamp( - abs(p.y - cloud_position) + cloud_thickness + 1.75 * f, 0.0, 1.0 );
float map5( in float3 p ) { FBM(FBM5) }
float map4( in float3 p ) { FBM(FBM4) }
float map3( in float3 p ) { FBM(FBM3) }
float map2( in float3 p ) { FBM(FBM2) }
float4 integrate( in float4 sum, in float dif, in float den, in float3 bgcol, in float t )
{
// lighting
float3 lin = _Color1 * 1.4 + _SunSSSColor.rgb * dif * _SunSSSColor.a;
float4 col = float4( lerp( _Color3, _Color4, den ), den );
col.xyz *= lin;
col.xyz = lerp( col.xyz, bgcol, 1.0 - exp(-0.003*t*t) );
// front to back blending
col.a *= 0.4;
col.rgb *= col.a;
return sum + col*(1.0-sum.a);
}
#if DEBUG
#define DEBUG_DEPTH sum.r = 1;
#else
#define DEBUG_DEPTH
#endif
#define MARCH(STEPS, MAPLOD) \
for(int i=0; i<STEPS; i++) { \
float3 pos = ro + t*rd; \
if( sum.a > 0.99 ) break; \
float depth = toDepth(float4(pos, 1)); \
if( depth > bg_depth ) { DEBUG_DEPTH break; } \
float den = MAPLOD( pos ); \
float den2 = MAPLOD( pos + 0.3*sundir ); \
float dif = clamp((den - den2)/0.3, 0.0, 1.0 ); \
if((t>near1 && t<far1) || t>near2) \
sum = integrate( sum, dif, den, bgcol.rgb, t ); \
t += max(0.05, 0.02 * t); \
}
float4 raymarch( in float3 ro, in float3 rd, in float4 bgcol )
{
float4 sum = float4(0.0,0.0,0.0,0.0);
float bg_depth = bgcol.a;
float t = 0.0;
#if MIPMAP
int count = rayIteratorCount / 5;
MARCH(count * 2, map5);
MARCH(count, map4);
MARCH(count, map3);
MARCH(count, map2);
#else
MARCH(rayIteratorCount, map5);
#endif
return clamp( sum, 0.0, 1.0 );
}
float2 castRay( in float3 ro, in float3 rd )
{
float tmin = 1.0;
float tmax = 20.0;
float precis = 0.002;
float t = tmin;
float m = -1.0;
for( int i=0; i<50; i++ )
{
float3 pos = ro + rd*t;
float d = length(pos) - 0.25;
if( d < precis || t > tmax ) break;
t += d;
m = 1;
}
if( t > tmax ) m=-1.0;
return float2( t, m );
}
float3 renderxx( in float3 ro, in float3 rd )
{
float3 col = float3(0.0, 0.0, 0.);
float2 res = castRay(ro,rd);
float m = res.y;
if( m > -0.5 )
{
col = 0.45 + 0.3 * sin( float3(0.05,0.08,0.10)*(m-1.0) );
}
return float3( clamp(col,0.0,1.0) );
}
float4 frag_vr_cloud(v2f_img i) : SV_Target
{
float bgDepth = LinearEyeDepth(tex2D(_CameraDepthTexture, float2(i.uv.x, i.uv.y)).r);
// camera
float3 ro = _WorldSpaceCameraPos;
float3 rd = getRayDirection(i.uv);
float4 scene_color = tex2D(_MainTex, i.uv);
// clouds
float4 res = raymarch( ro, rd, float4(float3(1.0, 1.0, 1.0), bgDepth) );
//float4 res = raymarch(ro, rd, float4(scene_color.rgb, bgDepth));
// sun glare
float sun = clamp( dot(sundir,rd), 0.0, 1.0 );
res.rgb += 0.2 * _SunGlareColor * pow( sun, 3.0 );
//if(abs(ro.x - _WorldSpaceCameraPos.x) < 0.01 && abs(ro.y - _WorldSpaceCameraPos.y) < 0.01 && abs(ro.z - _WorldSpaceCameraPos.z) < 0.01)
//if(coord.x < 0 && coord.y < 0)
// col.r = 1;
#if defined(DEBUG)
res.rgb += renderxx(ro, rd);
#endif
//if (unity_CameraProjection[0][2] < 0)
//if(abs(left) > abs(right))
//res.rgb = float3(1.0,0.0,0.0);
/*
float4x4 m = unity_CameraProjection;
float near = m[2][3] / (m[2][2] - 1);
float far = m[2][3] / (m[2][2] + 1);
if (near <= far)
res.rgb = float4(1,0,0,1);
else
res.rgb = float4(0, 1, 0, 1);
*/
return res;
}
float4 frag_vr_blendbg(v2f_img i) : SV_Target
{
// camera
float4 scene_color = tex2D(_MainTex, i.uv);
//scene_color = float4(0.0,0.0,0.0,1.0);
// background sky
float3 col = scene_color;
//col = float3(0.6,0.71,0.75) - rd.y*0.2*float3(1.0,0.5,1.0) + 0.15*0.5;
//col += 0.2 * float3(1.0,.6,0.1) * pow( sun, 8.0 );
// clouds
float4 res = tex2D(_CloudTex, float2(i.uv.x, i.uv.y));
col = col * (1.0 - res.a) + res.rgb;
//col = res.rgb;
return float4( col, 1.0 );
}
ENDCG
// (0) VRRenderCloud
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag_vr_cloud
ENDCG
}
// (0) VRBlendBg
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag_vr_blendbg
ENDCG
}
}
FallBack off
}