yum-archive/Tooner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/Tooner
8d2c110
master
1#include "UnityCG.cginc" 2 3#include "audiolink.cginc" 4#include "atrix256.cginc" 5#include "cnlohr.cginc" 6#include "globals.cginc" 7#include "interpolators.cginc" 8#include "math.cginc" 9#include "noise.cginc" 10#include "oklab.cginc" 11#include "pbr.cginc" 12#include "poi.cginc" 13#include "tone.cginc" 14 15#ifndef __FOG_INC 16#define __FOG_INC 17 18#if defined(_GIMMICK_FOG_00) 19 20struct Fog00PBR { 21 float4 albedo; 22 float depth; 23}; 24 25#define FOG_PERLIN_NOISE_SCALE 1 26 27float3 perlin_noise_3d_tex(float3 p) 28{ 29 // 1/256 = 0.00390625 30 return _Gimmick_Fog_00_Noise.SampleLevel(trilinear_repeat_s, p.xyz * 0.00390625, 0); 31} 32 33#define FBM_OCTAVES 3 34 35float3 perlin_noise_3d_tex_fbm(float3 p) 36{ 37 float3 res = perlin_noise_3d_tex(p); 38 float p_scale = 1; 39 //float d_scale = .66666; 40 float d_scale = .571428571; 41 for (uint i = 1; i < FBM_OCTAVES; i++) { 42 p_scale *= 2; 43 d_scale *= .5; 44 res += perlin_noise_3d_tex(p*p_scale)*d_scale; 45 } 46 return res; 47} 48 49// idea from here https://iquilezles.org/articles/warp/ 50float3 perlin_noise_3d_tex_warp(float3 p) 51{ 52 p = perlin_noise_3d_tex(p); 53 p = perlin_noise_3d_tex(p * 255); 54 p = perlin_noise_3d_tex(p * 255); 55 return p; 56} 57 58float3 light_fog00( 59 float3 albedo, 60 float NoL, 61 float3 direct, 62 float3 diffuse 63 ) { 64 half diffuseTerm = NoL; 65 float wrappedDiffuse = saturate((diffuseTerm + _WrappingFactor) / 66 (1.0f + _WrappingFactor)) * 2 / (2 * (1 + _WrappingFactor)); 67#if 0 68 float3 direct_unlit = .01; 69 direct = lerp(direct, direct_unlit, wrappedDiffuse); 70#endif 71 float3 diffCol = albedo * (diffuse + direct * wrappedDiffuse); 72 return diffCol; 73} 74 75float map(float3 p, out float3 normal) { 76#if 1 77 float3 t = float3(0, -_Time[0] * FOG_PERLIN_NOISE_SCALE, 0) * _Gimmick_Fog_00_Motion_Vector; 78#else 79 float3 t = 0; 80#endif 81#define RADIUS_TRANS_WIDTH .5 82#define RADIUS_TRANS_WIDTH_RCP (1.0 / RADIUS_TRANS_WIDTH) 83 // Try to create a smooth transition without doing any length() or other 84 // transcendental ops. 85#if 1 && defined(_GIMMICK_FOG_00_BOUNDARY_CYLINDER) 86 float radius2 = clamp(_Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius - dot(p.xz, p.xz), 0, RADIUS_TRANS_WIDTH) * RADIUS_TRANS_WIDTH_RCP; 87#elif 1 && defined(_GIMMICK_FOG_00_BOUNDARY_SPHERE) 88 float radius2 = clamp(_Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius - dot(p, p), 0, RADIUS_TRANS_WIDTH) * RADIUS_TRANS_WIDTH_RCP; 89#else 90 float radius2 = 1; 91#endif 92 93 float3 pp = p * _Gimmick_Fog_00_Noise_Scale * FOG_PERLIN_NOISE_SCALE; 94 normal = normalize(perlin_noise_3d_tex(pp+t) * 2 - 1); 95 float density = perlin_noise_3d_tex_warp(pp+t) * radius2; 96 //float density = perlin_noise_3d_tex(pp+t) * radius2; 97 //float density = 0.5 * radius2; 98 //density = pow(density, _Gimmick_Fog_00_Noise_Exponent); 99 // EV is 0.5, so apply corrective factor of pow(2, _Gimmick_Fog_00_Noise_Exponent - 1) 100 //density *= pow(2, _Gimmick_Fog_00_Noise_Exponent - 1); 101 //density *= 8; 102 density *= density * 2; 103 104 return density; 105} 106 107#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE) 108// Returns weighted color 109void getEmitterData(float3 p, 110 float dither, 111 float step_size, 112 float3 em_loc, 113 float3 em_normal, 114 float3 em_tangent, 115 float3 em_normal_x_tangent, 116 float2 emitter_scale, 117 float2 emitter_scale_rcp, 118 out float3 diffuse, 119 out float3 direct) 120{ 121 // Using identity a_parallel_to_b = (dot(a, b) / dot(b, b)) * b 122 // float3 along_tangent = dot(p - em_loc, em_tangent) * em_tangent; 123 // float3 along_normal_x_tangent = dot(p - em_loc, em_normal_x_tangent) * 124 // em_normal_x_tangent; 125 // Given that em_tangent and em_normal_x_tangent are normalized, and the fact 126 // that we really want uvs, we can simplify this: 127 float2 uv = float2(dot(p - em_loc, em_normal_x_tangent), dot(p - em_loc, em_tangent)); 128 uv *= emitter_scale_rcp; 129 uv *= 0.5; 130 uv += 0.5; 131 132 //uv.x += dither * .01; 133 const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x); 134 //uv.x += ign_anim((dither+1000) * 1000, frame, /*speed=*/1.0) * .01; 135 //uv.y += ign_anim(dither * 1000, frame, /*speed=*/1.0) * .01; 136 137 bool in_range = uv.x < 1 && uv.y < 1 && uv.x > 0 && uv.y > 0; 138 139#if 0 140 uv.y = FOG_PERLIN_NOISE(float3(uv*100, _Time[2])); 141 uv.x = FOG_PERLIN_NOISE(p); 142 uv.y = FOG_PERLIN_NOISE(float3(uv*100, _Time[2])); 143#endif 144 145 const float3 p_to_emitter = p - em_loc; 146 const float t = dot(p_to_emitter, em_normal); 147 148 const float raw_noise_sample = _Gimmick_Fog_00_Noise_2D.SampleLevel(point_repeat_s, uv * 1000, 0).x; 149 float emitter_lod = floor((abs(t) + dither) / ((_Gimmick_Fog_00_Emitter_Lod_Half_Life*(1+raw_noise_sample*2.5) * step_size))); 150 float3 em_color = _Gimmick_Fog_00_Emitter_Texture.SampleLevel(point_clamp_s, uv, emitter_lod); 151 float emitter_dist = in_range ? abs(t) : 1000; 152 float emitter_falloff = min(1, rcp(emitter_dist)); 153 154 direct = in_range * emitter_falloff * em_color; 155 156#if 1 157 float e = 0.1; 158 float2 uv_inv = 1.0 - uv; 159 diffuse = _Gimmick_Fog_00_Emitter_Texture.SampleLevel(point_clamp_s, float2(uv.x, uv.y), 16) + 160 _Gimmick_Fog_00_Emitter_Texture.SampleLevel(point_clamp_s, float2(uv.x, uv_inv.y), 16) + 161 _Gimmick_Fog_00_Emitter_Texture.SampleLevel(point_clamp_s, float2(uv_inv.x, uv.y), 16); 162 diffuse *= 0.3333; 163 float3 em_loc_clamp = em_loc + (saturate(uv.x) *2 - 1) * em_tangent + (saturate(uv.y) * 2 - 1) * em_normal_x_tangent; 164 em_loc_clamp += em_loc; 165 // TODO parameterize shaping constants 166 float diffuse_length = dot(p - em_loc_clamp, p - em_loc_clamp); 167 diffuse /= diffuse_length; 168#else 169 diffuse = 0; 170#endif 171} 172#endif // defined(_GIMMICK_FOG_00_EMITTER_TEXTURE) 173 174#if defined(_GIMMICK_FOG_00_RAY_MARCH_0) 175float fog00_map(float3 p, float rid_entropy) 176{ 177 float sin_term = sin(rid_entropy*2*TAU+_Time[0]*2)+1.0; 178 sin_term *= sin_term; 179 sin_term *= 0.7; 180 return length(p)+0.7-rid_entropy*2.3* 181 sin_term*.2; 182} 183float fog00_map_dr( 184 float3 p, 185 float3 period, 186 float3 count, 187 float seed, 188 out float3 which 189 ) 190{ 191 p -= float3(0, period.y * floor(count.y/2) + 1, 0); 192 p -= unity_ObjectToWorld._m03_m13_m23; 193 194 which = round(p / period); 195 // Direction to nearest neighboring cell. 196 float3 min_d = p - period * which; 197 float3 o = sign(min_d); 198 199 float d = 1E9; 200 float3 which_tmp = which; 201#if 1 202 for (uint xi = 0; xi < 2; xi++) 203 for (uint yi = 0; yi < 2; yi++) 204 for (uint zi = 0; zi < 2; zi++) 205#else 206 uint xi = 0; 207 uint yi = 0; 208 uint zi = 0; 209#endif 210 { 211 float3 rid = which + float3(xi, yi, zi) * o; 212 rid = clamp(rid, ceil(-(count)*0.5), floor((count-1)*0.5)); 213 float3 r = p - period * rid; 214 float3 rid_entropy = float3( 215 ign(rid.yz+seed), 216 ign(rid.xz+seed), 217 ign(rid.xy+seed)); 218 float3 random_dir = normalize(rid_entropy); 219 r += 220 (sin(_Time[0] * 2 + (rid_entropy.x + rid_entropy.y + rid_entropy.z) * TAU * .6666) * 2 - 1.0) * 221 period * 0.5 * 222 random_dir * 223 float3(1, 1, 1) * .3; 224 float cur_d = fog00_map(r, FOG_PERLIN_NOISE((rid+seed)*100)); 225 which_tmp = cur_d < d ? rid : which_tmp; 226 d = min(d, cur_d); 227 } 228 229 which = which_tmp; 230 return d; 231} 232#endif 233 234Fog00PBR __getFog00(v2f i, ToonerData tdata, 235 float3 obj_pos_depth_hit, 236 float2 screen_uv); 237 238Fog00PBR getFog00(v2f i, ToonerData tdata) 239{ 240 float3 obj_pos_depth_hit; 241 float2 screen_uv; 242 { 243 float3 full_vec_eye_to_geometry = i.worldPos - _WorldSpaceCameraPos; 244 float3 world_dir = normalize(i.worldPos - _WorldSpaceCameraPos); 245 float perspective_divide = 1.0 / i.pos.w; 246 float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide); 247 screen_uv = i.screenPos.xy * perspective_divide; 248 float eye_depth_world = 249 GetLinearZFromZDepth_WorksWithMirrors( 250 SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, tdata.screen_uv), 251 screen_uv) * perspective_factor; 252 float3 world_pos_depth_hit = _WorldSpaceCameraPos + eye_depth_world * world_dir; 253 obj_pos_depth_hit = mul(unity_WorldToObject, float4(world_pos_depth_hit, 1.0)).xyz; 254 } 255 256 return __getFog00(i, tdata, obj_pos_depth_hit, screen_uv); 257} 258 259Fog00PBR __getFog00(v2f i, ToonerData tdata, 260 float3 obj_pos_depth_hit, 261 float2 screen_uv) 262{ 263 float3 cam_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0)).xyz; 264 float3 obj_pos = i.objPos; 265 266 const float3 rd = normalize(obj_pos - cam_pos); 267 float3 ro = cam_pos; 268 269#if defined(_GIMMICK_FOG_00_BOUNDARY_CYLINDER) 270 { 271 // Raytrace distance to cylinder 272 bool no_intersection = false; 273 float distance_to_cylinder = 1E6; 274 { 275 float a = dot(rd.xz, rd.xz); 276 float b = 2 * dot(rd.xz, ro.xz); 277 float c = dot(ro.xz, ro.xz) - _Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius; 278 float t0, t1; 279 if (solveQuadratic(a, b, c, t0, t1)) { 280 no_intersection = (t0 < 0) * (t1 < 0); 281 const bool inside_cylinder = (t0 < 0) * (t1 > 0); 282 if (!inside_cylinder) { 283 distance_to_cylinder = no_intersection ? distance_to_cylinder : min(max(t0, 0), max(t1, 0)); 284 ro += distance_to_cylinder * rd; 285 } 286 } 287 } 288 clip(no_intersection ? -1 : 1); 289 } 290#elif defined(_GIMMICK_FOG_00_BOUNDARY_PLANE) 291 { 292 // Raytrace distance to plane 293 bool no_intersection = false; 294 float distance_to_plane = 1E6; 295 { 296 // Define the plane by normal and point 297 float3 n = normalize(mul(unity_WorldToObject, float4(_Gimmick_Fog_00_Plane_Normal, 0.0)).xyz); 298 float3 p0 = _Gimmick_Fog_00_Plane_Center; 299 300 float denom = dot(n, rd); 301 if (abs(denom) > 1e-6) { 302 // The ray is not parallel to the plane 303 float t = dot(n, (p0 - ro)) / denom; 304 if (t >= 0) { 305 distance_to_plane = t; 306 ro += distance_to_plane * rd; 307 } else { 308 no_intersection = true; // Intersection is behind the ray origin 309 } 310 } else { 311 no_intersection = true; // Ray is parallel to the plane 312 } 313 } 314 clip(no_intersection ? -1 : 1); 315 } 316#elif defined(_GIMMICK_FOG_00_BOUNDARY_SPHERE) 317 { 318 bool no_intersection = false; 319 float distance_to_sphere = 1E6; 320 { 321 float3 l = ro; 322 float a = 1; 323 float b = 2 * dot(rd, l); 324 float c = dot(l, l) - _Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius; 325 float t0, t1; 326 if (solveQuadratic(a, b, c, t0, t1)) { 327 no_intersection = (t0 < 0) * (t1 < 0); 328 const bool inside_sphere = (t0 < 0) * (t1 > 0); 329 if (!inside_sphere) { 330 distance_to_sphere = no_intersection ? distance_to_sphere : min(max(t0, 0), max(t1, 0)); 331 ro += distance_to_sphere * rd; 332 } 333 } 334 } 335 clip(no_intersection ? -1 : 1); 336 } 337#endif 338 339 float density_ss_term = 1 / _Gimmick_Fog_00_Density; 340 //density_ss_term = dclamp(density_ss_term, 0.33, 3.00, 5); 341 const float step_size = _Gimmick_Fog_00_Step_Size_Factor * density_ss_term; 342 const float step_size_sqrt = sqrt(step_size); 343 const float step_size_sqrt_max1 = max(1, step_size_sqrt); 344 //step_size = clamp(step_size, 1E-2, 1E2); 345 uint2 screen_uv_round = floor(screen_uv * _ScreenParams.xy); 346 const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x); 347#if defined(_GIMMICK_FOG_00_NOISE_2D) 348 const float raw_noise_sample = _Gimmick_Fog_00_Noise_2D.SampleLevel(point_repeat_s, screen_uv * _ScreenParams.xy * _Gimmick_Fog_00_Noise_2D_TexelSize.xy, 0).x; 349 const float dither_seed = frac(raw_noise_sample + frame * PHI); 350#elif 1 351 const float dither_seed = frac(ign_anim(screen_uv_round, frame, /*speed=*/0.000) + frame * 1.618033989); 352#else 353 const float dither_seed = rand2(float2(screen_uv_round.x, screen_uv_round.y)*.001); 354#endif 355 float dither = dither_seed * step_size * _Gimmick_Fog_00_Ray_Origin_Randomization; 356 ro += rd * (_Gimmick_Fog_00_Initial_Offset + dither); 357 358 const float depth_hit_l = length(obj_pos_depth_hit - ro); 359 360 // Get common lighting data 361 UnityLight direct_light; 362 UnityIndirect indirect_light; 363 direct_light.dir = getDirectLightDirection(i); 364 direct_light.ndotl = 0; // Not used 365 direct_light.color = getDirectLightColor() *_Direct_Lighting_Factor; 366 // TODO try per-sample baked lighting 367 indirect_light.diffuse = getIndirectDiffuse(i, /*vertex_light_color=*/0) * _Indirect_Diffuse_Lighting_Factor; 368 // TODO consider doing specular. At time of writing it seems pointless. 369 indirect_light.specular = 0; 370 371 float4 acc = 0; 372 uint step_count = floor(min(_Gimmick_Fog_00_Max_Ray, depth_hit_l) / step_size); 373 //step_count *= (1 - no_intersection); 374#define FOG_MAX_LOOP 20 375 step_count = min(step_count, FOG_MAX_LOOP); 376 377#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE) 378 const float3 em_loc = mul(unity_WorldToObject, float4(_Gimmick_Fog_00_Emitter0_Location, 1.0)).xyz; 379 const float3 em_normal = normalize(mul(unity_WorldToObject, float4(_Gimmick_Fog_00_Emitter0_Normal, 0.0)).xyz); 380 const float3 em_tangent = normalize(mul(unity_WorldToObject, float4(_Gimmick_Fog_00_Emitter0_Tangent, 0.0)).xyz); 381 const float3 em_normal_x_tangent = normalize(cross(em_normal, em_tangent)); 382 const float em_scale_t = _Gimmick_Fog_00_Emitter0_Scale_T * length(mul(unity_WorldToObject, float4(_Gimmick_Fog_00_Emitter0_Normal, 0.0))); 383 const float em_scale_nxt = _Gimmick_Fog_00_Emitter0_Scale_NxT * length(mul(unity_WorldToObject, float4(cross(_Gimmick_Fog_00_Emitter0_Normal, _Gimmick_Fog_00_Emitter0_Tangent), 0.0))); 384 const float2 em_scale = float2(em_scale_t, em_scale_nxt); 385 const float2 em_scale_rcp = rcp(em_scale); 386#endif 387 388 const float3 ro_world = mul(unity_ObjectToWorld, float4(ro, 1.0)).xyz; 389 const float3 rd_world = mul(unity_ObjectToWorld, float4(rd, 0.0)).xyz; 390 const float3 rd_world_normalized = normalize(rd_world); 391 const float step_size_world = step_size * length(rd_world); 392 const float3 view_dir_world = normalize(_WorldSpaceCameraPos - i.worldPos); 393 394 const float3 noise_scale_rcp = 1.0 / _Gimmick_Fog_00_Noise_Scale; 395 uint ii; 396 for (ii = 0; ii < step_count; ii++) { 397 const float3 p = ro + rd * ii * step_size; 398 399 float4 c; 400 float3 c_lit = 0; 401#if 1 402 float3 map_normal; 403 const float map_p_raw = map(p, map_normal); 404 const float map_p = map_p_raw * _Gimmick_Fog_00_Density * step_size; 405 c = float4(_Color.rgb, map_p); 406 float3 diffuse = 0; 407 float3 direct = 0; 408#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE) && !defined(_GIMMICK_FOG_00_EMITTER_VARIABLE_DENSITY) 409 // We put the emitter color into diffuse instead of doing a directional 410 // calculation because it looks better and it's cheaper. Less accurate 411 // though! 412 if (_Gimmick_Fog_00_Enable_Area_Lighting) { 413 // Note that I'm intentionally passing in `direct` and `diffuse` 414 // backwards. It looks better if the collimated light is immune to normal 415 // dimming, and if the diffuse light is not. 416 getEmitterData(p, dither, step_size, em_loc, em_normal, em_tangent, em_normal_x_tangent, em_scale, 417 em_scale_rcp, direct, diffuse); 418 } 419 diffuse *= _Gimmick_Fog_00_Emitter_Brightness_Diffuse; 420 direct *= _Gimmick_Fog_00_Emitter_Brightness_Direct; 421#else 422#endif 423 424 // Scaling brightness by sqrt(step_size) seems to look more consistent as 425 // you vary density. No idea why :( 426 float NoL = dot(map_normal, direct_light.dir); 427 c_lit += light_fog00( 428 c.rgb, 429 NoL, 430 (direct_light.color + direct) * step_size_sqrt_max1, 431 (indirect_light.diffuse + diffuse) * step_size_sqrt_max1); 432#else 433 c_lit = .05 * step_size; 434 c.a = 0.1; 435#endif 436#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE) && defined(_GIMMICK_FOG_00_EMITTER_VARIABLE_DENSITY) 437 float3 em_c = getEmitterData(p, step_size, em_loc, em_normal, em_scale, em_scale_rcp) * step_size; 438 float em_NoL = saturate((map(p + dd_e * em_normal, lod) - map_p_raw) / dd_e); 439 c_lit += light_fog00( 440 c.rgb, 441 em_NoL, 442 em_c, 443 0); 444#endif 445 c.rgb = c_lit; 446 447 // Intuition: add c scaled by the remaining transparent portion of acc. 448 acc = acc + (1 - acc.a) * c; 449 450#if 1 451 // For performance, stop if we... 452 // 1. accumulate enough alpha 453 // 2. go outside of the sphere 454 if (acc.a > _Gimmick_Fog_00_Alpha_Cutoff) { 455 break; 456 } 457#if defined(_GIMMICK_FOG_00_BOUNDARY_SPHERE) || defined(_GIMMICK_FOG_00_BOUNDARY_CYLINDER) 458 if (dot(p.xz, p.xz) > _Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius) { 459 break; 460 } 461#endif 462#endif 463 } 464 if (acc.a > _Gimmick_Fog_00_Alpha_Cutoff || ii == FOG_MAX_LOOP) { 465 acc /= acc.a; 466 } 467 acc.rgb = LRGBtoOKLAB(acc.rgb); 468 acc.x = smooth_min(acc.x, _Gimmick_Fog_00_Max_Brightness * .85, _Gimmick_Fog_00_Max_Brightness); 469 acc.rgb = OKLABtoLRGB(acc.rgb); 470 471 Fog00PBR pbr; 472 pbr.albedo = acc; 473 pbr.albedo.a = smooth_min(pbr.albedo.a, .999, 1); 474 475 // Add some dithering to lit color to break up banding 476 //const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x); 477 //pbr.albedo.rgb += ign_anim(dither * 1000, frame, /*speed=*/1.0) * .00390625; 478 479 // Remap onto [0, 1] 480 pbr.albedo.rgb = aces_filmic(pbr.albedo.rgb); 481 // Clamp so max brightness is comfortable. Do it in perceptually uniform 482 // space to avoid affecting saturation. 483 //pbr.albedo.rgb = LRGBtoOKLAB(pbr.albedo.rgb); 484 //pbr.albedo.x = smooth_min(pbr.albedo.x, _Gimmick_Fog_00_Max_Brightness * .9, _Gimmick_Fog_00_Max_Brightness); 485 //pbr.albedo.rgb = OKLABtoLRGB(pbr.albedo.rgb); 486 487 float4 clip_pos = mul(UNITY_MATRIX_VP, float4(mul(unity_ObjectToWorld, float4(ro, 1.0)))); 488 pbr.depth = clip_pos.z / clip_pos.w; 489 490#if 0 491 //pbr.albedo.rgb = eye_depth_world / 100; 492 pbr.albedo.rgb = dither_seed; 493 pbr.albedo.a = 1; 494#endif 495 496 return pbr; 497} 498 499#endif // _GIMMICK_FOG_00 500 501#if defined(_GIMMICK_FOG_01) || defined(_GIMMICK_DS2) 502 503struct Fog01PBR { 504 float4 albedo; 505 float depth; 506}; 507 508float4 apply_fog( 509 float t, 510 float density, 511 float3 rd, 512 float3 sun_dir, 513 float4 sun_color, 514 float sun_exponent, 515 float sun_color_2_enable, 516 float4 sun_color_2, 517 float sun_exponent_2, 518 float4 fog_color) { 519 float fog_amount = 1 - exp(-t * density); 520 float4 color = fog_color; 521 float ndotl = dot(rd, sun_dir); 522 // Wrap ndotl 523 ndotl = (ndotl + 1) / (2); 524 ndotl *= ndotl; 525 ndotl = max(ndotl, 0); 526 [branch] 527 if (sun_color_2_enable) { 528 float sun_amount_2 = saturate(pow(ndotl, sun_exponent_2) * fog_amount); 529 color = lerp(color, sun_color_2, sun_amount_2); 530 } 531 float sun_amount = saturate(pow(ndotl, sun_exponent) * fog_amount); 532 color = lerp(color, sun_color, sun_amount); 533 //return float4(color.rgb, fog_amount * color.a); 534 return float4(color.rgb, fog_amount * color.a); 535} 536 537Fog01PBR getFog01(v2f i, ToonerData tdata) { 538 float3 cam_pos = _WorldSpaceCameraPos; 539 float3 obj_pos = i.worldPos; 540 541 if (_Gimmick_Fog_01_Distance_Culling_Enable) { 542 float3 activation_center = _Gimmick_Fog_01_Activation_Center; 543 float activation_radius = _Gimmick_Fog_01_Activation_Radius; 544 float cur_radius = length(_WorldSpaceCameraPos - activation_center); 545 [branch] 546 if (getCenterCamPos().y > activation_center.y + activation_radius) { 547 return (Fog01PBR)0; 548 } 549 } 550 551 float3 world_pos_depth_hit; 552 float2 screen_uv; 553 float eye_depth_world; 554 { 555 float3 full_vec_eye_to_geometry = i.worldPos - _WorldSpaceCameraPos; 556 float3 world_dir = normalize(i.worldPos - _WorldSpaceCameraPos); 557 float perspective_divide = 1.0 / i.pos.w; 558 float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide); 559 screen_uv = i.screenPos.xy * perspective_divide; 560 eye_depth_world = 561 GetLinearZFromZDepth_WorksWithMirrors( 562 SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, tdata.screen_uv), 563 screen_uv) * perspective_factor; 564 world_pos_depth_hit = _WorldSpaceCameraPos + eye_depth_world * world_dir; 565 } 566 567 const float3 rd = normalize(obj_pos - cam_pos); 568 float3 ro = cam_pos + rd * 1E-5; 569 570 Fog01PBR pbr; 571 pbr.albedo = apply_fog(eye_depth_world, 572 _Gimmick_Fog_01_Density, rd, 573 normalize(_Gimmick_Fog_01_Sun_Direction), 574 _Gimmick_Fog_01_Sun_Color, 575 _Gimmick_Fog_01_Sun_Exponent, 576 _Gimmick_Fog_01_Sun_Color_2_Enable, 577 _Gimmick_Fog_01_Sun_Color_2, 578 _Gimmick_Fog_01_Sun_Exponent_2, 579 _Gimmick_Fog_01_Color); 580 pbr.albedo.rgb = aces_filmic(pbr.albedo.rgb); 581 582 //pbr.albedo.rgb = eye_depth_world / 100000; 583 //pbr.albedo.a = 1; 584 585 float4 clip_pos = mul(UNITY_MATRIX_VP, float4(ro, 1)); 586 pbr.depth = clip_pos.z / clip_pos.w; 587 588 return pbr; 589} 590 591#endif // _GIMMICK_FOG_01 592 593#endif // __FOG_INC 594