211 lines
6.2 KiB
GLSL
211 lines
6.2 KiB
GLSL
Shader "Hidden/HDRP/Sky/PbrSky"
|
|
{
|
|
HLSLINCLUDE
|
|
|
|
#pragma vertex Vert
|
|
|
|
// #pragma enable_d3d11_debug_symbols
|
|
#pragma editor_sync_compilation
|
|
#pragma target 4.5
|
|
#pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
|
|
|
|
#pragma multi_compile_fragment _ LOCAL_SKY
|
|
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyRendering.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyEvaluation.hlsl"
|
|
|
|
int _HasGroundAlbedoTexture; // bool...
|
|
int _HasGroundEmissionTexture; // bool...
|
|
int _HasSpaceEmissionTexture; // bool...
|
|
|
|
float _GroundEmissionMultiplier;
|
|
float _SpaceEmissionMultiplier;
|
|
|
|
// 3x3, but Unity can only set 4x4...
|
|
float4x4 _PlanetRotation;
|
|
float4x4 _SpaceRotation;
|
|
|
|
TEXTURECUBE(_GroundAlbedoTexture);
|
|
TEXTURECUBE(_GroundEmissionTexture);
|
|
TEXTURECUBE(_SpaceEmissionTexture);
|
|
|
|
struct Attributes
|
|
{
|
|
uint vertexID : SV_VertexID;
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
UNITY_VERTEX_OUTPUT_STEREO
|
|
};
|
|
|
|
Varyings Vert(Attributes input)
|
|
{
|
|
Varyings output;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
|
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID, UNITY_RAW_FAR_CLIP_VALUE);
|
|
return output;
|
|
}
|
|
|
|
float4 RenderSky(Varyings input)
|
|
{
|
|
const float R = _PlanetaryRadius;
|
|
const float3 V = GetSkyViewDirWS(input.positionCS.xy);
|
|
const bool renderSunDisk = _RenderSunDisk != 0;
|
|
float3 N; float r; // These params correspond to the entry point
|
|
|
|
#ifdef LOCAL_SKY
|
|
const float3 O = _PBRSkyCameraPosPS;
|
|
|
|
float tEntry = IntersectAtmosphere(O, V, N, r).x;
|
|
float tExit = IntersectAtmosphere(O, V, N, r).y;
|
|
|
|
float cosChi = -dot(N, V);
|
|
float cosHor = ComputeCosineOfHorizonAngle(r);
|
|
#else
|
|
N = float3(0, 1, 0);
|
|
r = _PlanetaryRadius;
|
|
float cosChi = -dot(N, V);
|
|
float cosHor = 0.0f;
|
|
const float3 O = N * r;
|
|
|
|
float tEntry = 0.0f;
|
|
float tExit = IntersectSphere(_AtmosphericRadius, -dot(N, V), r).y;
|
|
#endif
|
|
|
|
bool rayIntersectsAtmosphere = (tEntry >= 0);
|
|
bool lookAboveHorizon = (cosChi >= cosHor);
|
|
|
|
float tFrag = FLT_INF;
|
|
float3 radiance = 0;
|
|
|
|
if (renderSunDisk)
|
|
radiance = RenderSunDisk(tFrag, tExit, V);
|
|
|
|
if (rayIntersectsAtmosphere && !lookAboveHorizon) // See the ground?
|
|
{
|
|
float tGround = tEntry + IntersectSphere(R, cosChi, r).x;
|
|
|
|
if (tGround < tFrag)
|
|
{
|
|
// Closest so far.
|
|
// Make it negative to communicate to EvaluatePbrAtmosphere that we intersected the ground.
|
|
tFrag = -tGround;
|
|
|
|
radiance = 0;
|
|
|
|
float3 gP = O + tGround * -V;
|
|
float3 gN = normalize(gP);
|
|
|
|
if (_HasGroundEmissionTexture)
|
|
{
|
|
float4 ts = SAMPLE_TEXTURECUBE(_GroundEmissionTexture, s_trilinear_clamp_sampler, mul(gN, (float3x3)_PlanetRotation));
|
|
radiance += _GroundEmissionMultiplier * ts.rgb;
|
|
}
|
|
|
|
float3 albedo = _GroundAlbedo.xyz;
|
|
|
|
if (_HasGroundAlbedoTexture)
|
|
{
|
|
albedo *= SAMPLE_TEXTURECUBE(_GroundAlbedoTexture, s_trilinear_clamp_sampler, mul(gN, (float3x3)_PlanetRotation)).rgb;
|
|
}
|
|
|
|
float3 gBrdf = INV_PI * albedo;
|
|
|
|
// Shade the ground.
|
|
for (uint i = 0; i < _CelestialLightCount; i++)
|
|
{
|
|
CelestialBodyData light = _CelestialBodyDatas[i];
|
|
|
|
float3 L = -light.forward.xyz;
|
|
float3 intensity = light.color.rgb;
|
|
|
|
#ifdef LOCAL_SKY
|
|
intensity *= SampleGroundIrradianceTexture(dot(gN, L));
|
|
#else
|
|
float3 opticalDepth = ComputeAtmosphericOpticalDepth(r, dot(N, L), true);
|
|
intensity *= TransmittanceFromOpticalDepth(opticalDepth) * saturate(dot(N, L));
|
|
#endif
|
|
|
|
radiance += gBrdf * intensity;
|
|
}
|
|
}
|
|
}
|
|
else if (tFrag == FLT_INF) // See the stars?
|
|
{
|
|
if (_HasSpaceEmissionTexture)
|
|
{
|
|
// V points towards the camera.
|
|
float4 ts = SAMPLE_TEXTURECUBE(_SpaceEmissionTexture, s_trilinear_clamp_sampler, mul(-V, (float3x3)_SpaceRotation));
|
|
radiance += _SpaceEmissionMultiplier * ts.rgb;
|
|
}
|
|
}
|
|
|
|
float3 skyColor = 0, skyOpacity = 0;
|
|
|
|
#ifdef LOCAL_SKY
|
|
if (rayIntersectsAtmosphere)
|
|
EvaluatePbrAtmosphere(_PBRSkyCameraPosPS, V, tFrag, renderSunDisk, skyColor, skyOpacity);
|
|
#else
|
|
if (lookAboveHorizon)
|
|
EvaluateDistantAtmosphere(-V, skyColor, skyOpacity);
|
|
#endif
|
|
|
|
skyColor += radiance * (1 - skyOpacity);
|
|
skyColor *= _IntensityMultiplier;
|
|
|
|
return float4(skyColor, 1.0);
|
|
}
|
|
|
|
float4 FragBaking(Varyings input) : SV_Target
|
|
{
|
|
return RenderSky(input); // The cube map is not pre-exposed
|
|
}
|
|
|
|
float4 FragRender(Varyings input) : SV_Target
|
|
{
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
float4 value = RenderSky(input);
|
|
value.rgb *= GetCurrentExposureMultiplier(); // Only the full-screen pass is pre-exposed
|
|
return value;
|
|
}
|
|
|
|
ENDHLSL
|
|
|
|
SubShader
|
|
{
|
|
Tags{ "RenderPipeline" = "HDRenderPipeline" }
|
|
Pass
|
|
{
|
|
Name "PBRSky Cubemap"
|
|
|
|
ZWrite Off
|
|
ZTest Always
|
|
Blend Off
|
|
Cull Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma fragment FragBaking
|
|
ENDHLSL
|
|
}
|
|
|
|
Pass
|
|
{
|
|
Name "PBRSky"
|
|
|
|
ZWrite Off
|
|
ZTest LEqual
|
|
Blend Off
|
|
Cull Off
|
|
|
|
HLSLPROGRAM
|
|
#pragma fragment FragRender
|
|
ENDHLSL
|
|
}
|
|
}
|
|
Fallback Off
|
|
}
|