XRoom_Unity/Assets/beantowel/Aerosol/Shaders/Skybox.shader
2025-05-31 10:20:20 +03:30

124 lines
5.1 KiB
GLSL

Shader "Aerosol/Skybox"
{
Properties
{
transmittance_texture("Transimittance Texture", 2D) = "" {}
scattering_texture("Scattering Texture", 3D) = "" {}
single_mie_scattering_texture("Single Mie Scattering Texture", 3D) = "" {}
irradiance_texture("Irradiance Texture", 2D) = "" {}
unit_scale("Unit Scale", Float) = 0.001
white_point("White Point", Vector) = (1, 1, 1, 0)
exposure("Exposure", Float) = 0.0001
ground_albedo("Ground Albedo", Vector) = (0.1, 0.1, 0.1, 0)
}
SubShader
{
Tags {"Queue"="Background" "RenderType"="Background"}
Cull Off ZWrite Off ZTest Less
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#include "atmosphere.hlsl"
const static float3 earth_center = float3(0, -ATMOSPHERE.bottom_radius, 0);
const static float2 sun_size = float2(
tan(ATMOSPHERE.sun_angular_radius), cos(ATMOSPHERE.sun_angular_radius));
float unit_scale;
float3 white_point;
float exposure;
float3 ground_albedo;
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 view_ray : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f output;
output.pos = UnityObjectToClipPos(v.vertex);
output.view_ray = mul((float3x3)unity_ObjectToWorld, v.vertex.xyz);
return output;
}
half4 frag (v2f i) : SV_Target
{
float3 view_direction = normalize(i.view_ray);
float3 sun_direction = normalize(_WorldSpaceLightPos0.xyz);
float3 camera = _WorldSpaceCameraPos * unit_scale;
float3 p = camera - earth_center;
float lightshaft_fadein_hack = smoothstep(
0.02, 0.04, dot(normalize(p), sun_direction));
// TODO: shadow
float shadow_out = 0;
float shadow_in = 0;
// Compute the radiance reflected by the ground, if the ray intersects it.
// Compute the distance between the view ray line and the Earth center,
// and the distance between the camera and the intersection of the view
// ray with the ground (or NaN if there is no intersection).
float ground_alpha = 0.0;
float3 ground_luminance = 0.0;
float p_dot_v = dot(p, view_direction);
float p_dot_p = dot(p, p);
float ray_earth_center_squared_distance = p_dot_p - p_dot_v * p_dot_v;
float delta_intersection_square = earth_center.y * earth_center.y - ray_earth_center_squared_distance;
float distance_to_intersection = -p_dot_v - sqrt(delta_intersection_square);
if (delta_intersection_square > 0 && distance_to_intersection > 0) {
float3 pnt = p + view_direction * distance_to_intersection;
float3 normal = normalize(pnt);
// Compute the radiance reflected by the ground.
float3 sky_illuminance;
float3 sun_illuminance = GetSunAndSkyIlluminance(
pnt, normal, sun_direction, sky_illuminance);
// TODO: visibility term
float visibility = 1;
ground_luminance = ground_albedo * (1.0 / PI) *
(sun_illuminance + sky_illuminance) * visibility;
float shadow_length =
max(0.0, min(shadow_out, distance_to_intersection) - shadow_in) *
lightshaft_fadein_hack;
float3 transmittance;
float3 in_scatter = GetSkyLuminanceToPoint(p, pnt,
shadow_length, sun_direction, transmittance);
ground_luminance = ground_luminance * transmittance + in_scatter;
ground_alpha = 1.0;
}
// Compute the radiance of the sky.
float shadow_length = max(0, shadow_out - shadow_in) * lightshaft_fadein_hack;
float3 transmittance;
float3 luminance = GetSkyLuminance(
p, view_direction, shadow_length, sun_direction, transmittance);
// If the view ray intersects the Sun, add the Sun radiance.
if (dot(view_direction, sun_direction) > sun_size.y) {
luminance = luminance + transmittance * GetSolarLuminance();
}
luminance = lerp(luminance, ground_luminance, ground_alpha);
// tone mapping & sRGB -> linearRGB (gamma)
float3 rgb = pow(1 - exp(-luminance / white_point * exposure), 2.2);
return half4(rgb , 1);
}
ENDHLSL
}
}
}