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
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
|
|
}
|
|
|