Files
pelpanagiotisandClaude Opus 5.5 5fc9ebf1e6 Add practice range: shooting, AK47, intro cinematic, dressed warehouse scene
- PortalTestDestination practice range: Valorant-style hitscan rifle (recoil,
  spray/bloom, reload, controller support), debug HUD, practice-dummy targets
  with head/body hitboxes, hit/death/respawn animations, procedural SFX/FX
- AK47 model (Quaternius, CC0) held via Animator IK, with fire/reload/equip anims
- Intro cinematic (camera shots, title card, target beam-in, GO hand-off)
- Scene dressing editor pass: CC0 textures, props, warehouse roof, lighting and
  post-processing; custom stylized skybox shader
- CharacterMovement: camera recoil, shoulder offset, cinematic control lock
- Unity CLI pipeline package; plus in-progress chat/Rive/player changes

Asset credits: Assets/Models/Props/PROPS_CREDITS.txt (3 CC-BY 3.0 props),
Assets/Textures/Range/TEXTURES_LICENSE.txt, Assets/Resources/*/..._LICENSE.txt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 08:56:35 +03:00

164 lines
7.2 KiB
GLSL

// Stylized dusk skybox for the practice range (URP).
// Gradient sky (zenith -> horizon band -> ground), a sun disc + glow that tracks the scene's
// main directional light, procedural fbm clouds projected on a sky plane and drifting over
// time (lit warmer on the sun side), and faint twinkling stars toward the zenith.
Shader "Skybox/RangeStylizedSky"
{
Properties
{
[Header(Gradient)]
_ZenithColor ("Zenith", Color) = (0.10, 0.11, 0.32, 1)
_SkyColor ("Upper Sky", Color) = (0.27, 0.25, 0.55, 1)
_HorizonColor ("Horizon", Color) = (1.00, 0.52, 0.36, 1)
_GroundColor ("Below Horizon", Color) = (0.34, 0.26, 0.34, 1)
_HorizonSharpness ("Horizon Sharpness", Range(1, 20)) = 6
_HorizonGlow ("Horizon Glow", Range(0, 2)) = 0.6
[Header(Sun)]
_SunColor ("Sun Color", Color) = (1.00, 0.80, 0.55, 1)
_SunSize ("Sun Size", Range(0.001, 0.1)) = 0.025
_SunGlow ("Sun Glow", Range(0, 4)) = 1.2
_SunGlowFalloff ("Sun Glow Falloff", Range(1, 64)) = 10
[Header(Clouds)]
_CloudColor ("Cloud Color", Color) = (0.95, 0.72, 0.70, 1)
_CloudShadowColor ("Cloud Shadow", Color) = (0.32, 0.26, 0.45, 1)
_CloudCoverage ("Coverage", Range(0, 1)) = 0.48
_CloudSoftness ("Softness", Range(0.01, 0.5)) = 0.18
_CloudScale ("Scale", Range(0.1, 5)) = 1.4
_CloudSpeed ("Drift Speed", Range(0, 0.1)) = 0.012
[Header(Stars)]
_StarDensity ("Density", Range(50, 600)) = 280
_StarBrightness ("Brightness", Range(0, 3)) = 1.1
}
SubShader
{
Tags { "Queue" = "Background" "RenderType" = "Background" "PreviewType" = "Skybox" "RenderPipeline" = "UniversalPipeline" }
Cull Off
ZWrite Off
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
half4 _ZenithColor, _SkyColor, _HorizonColor, _GroundColor;
half _HorizonSharpness, _HorizonGlow;
half4 _SunColor;
half _SunSize, _SunGlow, _SunGlowFalloff;
half4 _CloudColor, _CloudShadowColor;
half _CloudCoverage, _CloudSoftness, _CloudScale, _CloudSpeed;
half _StarDensity, _StarBrightness;
CBUFFER_END
struct Attributes { float4 positionOS : POSITION; };
struct Varyings { float4 positionCS : SV_POSITION; float3 dir : TEXCOORD0; };
Varyings vert(Attributes v)
{
Varyings o;
o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
o.dir = v.positionOS.xyz; // skybox mesh: object position == view direction
return o;
}
float hash21(float2 p)
{
p = frac(p * float2(123.34, 456.21));
p += dot(p, p + 45.32);
return frac(p.x * p.y);
}
float valueNoise(float2 p)
{
float2 i = floor(p);
float2 f = frac(p);
float2 u = f * f * (3.0 - 2.0 * f);
float a = hash21(i);
float b = hash21(i + float2(1, 0));
float c = hash21(i + float2(0, 1));
float d = hash21(i + float2(1, 1));
return lerp(lerp(a, b, u.x), lerp(c, d, u.x), u.y);
}
float fbm(float2 p)
{
float sum = 0.0;
float amp = 0.5;
for (int i = 0; i < 5; i++)
{
sum += valueNoise(p) * amp;
p = p * 2.03 + float2(17.1, 9.2);
amp *= 0.5;
}
return sum;
}
half4 frag(Varyings i) : SV_Target
{
float3 dir = normalize(i.dir);
float y = dir.y;
float3 sunDir = normalize(_MainLightPosition.xyz);
float sunDot = dot(dir, sunDir);
// --- Gradient: ground -> horizon band -> upper sky -> zenith.
float up = saturate(y);
float3 sky = lerp(_SkyColor.rgb, _ZenithColor.rgb, smoothstep(0.25, 1.0, up));
float horizonBand = pow(1.0 - up, _HorizonSharpness);
sky = lerp(sky, _HorizonColor.rgb, horizonBand);
// The horizon glows brighter on the sun's side.
float sunSide = saturate(dot(normalize(float3(dir.x, 0, dir.z) + 1e-5), normalize(float3(sunDir.x, 0, sunDir.z) + 1e-5)) * 0.5 + 0.5);
sky += _HorizonColor.rgb * horizonBand * _HorizonGlow * sunSide * sunSide;
// Soft haze below the horizon (reads as distant fog from high camera angles, not a void).
float below = smoothstep(0.0, -0.35, y);
float3 col = lerp(sky, _GroundColor.rgb, below);
// --- Stars: sparse cells on a sphere-ish projection, fading in toward the zenith.
float2 starUV = dir.xz / (abs(y) + 0.35) * _StarDensity * 0.1;
float2 cell = floor(starUV);
float starSeed = hash21(cell);
float2 starPos = frac(starUV) - (0.25 + 0.5 * float2(hash21(cell + 3.1), hash21(cell + 7.7)));
float star = step(0.93, starSeed) * smoothstep(0.08, 0.0, length(starPos));
float twinkle = 0.6 + 0.4 * sin(_Time.y * (2.0 + starSeed * 5.0) + starSeed * 40.0);
col += star * twinkle * _StarBrightness * smoothstep(0.35, 0.9, y);
// --- Sun: hard-ish disc plus a wide soft glow.
float disc = smoothstep(1.0 - _SunSize, 1.0 - _SunSize * 0.6, sunDot);
float glow = pow(saturate(sunDot), _SunGlowFalloff) * _SunGlow;
col += _SunColor.rgb * (disc * 6.0 + glow) * (1.0 - below);
// --- Clouds: fbm on a plane above the camera, thinning out toward the horizon.
if (y > 0.0)
{
float2 cloudUV = dir.xz / (y + 0.12) * _CloudScale;
float2 drift = float2(_Time.y * _CloudSpeed, _Time.y * _CloudSpeed * 0.37);
float n = fbm(cloudUV + drift);
float n2 = fbm(cloudUV * 1.9 - drift * 1.6 + 5.0);
float density = n * 0.75 + n2 * 0.25;
float threshold = 1.0 - _CloudCoverage;
float cloud = smoothstep(threshold - _CloudSoftness, threshold + _CloudSoftness, density);
cloud *= smoothstep(0.0, 0.18, y); // fade near horizon
// Lighter where the cloud is thin and on the sun side; shadowed where thick.
float thickness = saturate((density - threshold) * 3.0);
float3 cloudCol = lerp(_CloudColor.rgb, _CloudShadowColor.rgb, thickness * 0.7);
cloudCol += _SunColor.rgb * pow(saturate(sunDot), 6.0) * 0.8;
col = lerp(col, cloudCol, cloud * 0.9);
}
return half4(col, 1.0);
}
ENDHLSL
}
}
Fallback Off
}