284 lines
10 KiB
HLSL
284 lines
10 KiB
HLSL
// OpenLit Library 1.0.2
|
|
// This code is licensed under CC0 1.0 Universal.
|
|
// https://creativecommons.org/publicdomain/zero/1.0/
|
|
|
|
#if !defined(OPENLIT_CORE_INCLUDED)
|
|
#define OPENLIT_CORE_INCLUDED
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Macro
|
|
#define OPENLIT_LIGHT_COLOR _LightColor0.rgb
|
|
#define OPENLIT_LIGHT_DIRECTION _WorldSpaceLightPos0.xyz
|
|
#define OPENLIT_MATRIX_M unity_ObjectToWorld
|
|
#define OPENLIT_FALLBACK_DIRECTION float4(0.001,0.002,0.001,0)
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// SRGB <-> Linear
|
|
float3 OpenLitLinearToSRGB(float3 col)
|
|
{
|
|
return LinearToGammaSpace(col);
|
|
}
|
|
|
|
float3 OpenLitSRGBToLinear(float3 col)
|
|
{
|
|
return GammaToLinearSpace(col);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Color
|
|
float OpenLitLuminance(float3 rgb)
|
|
{
|
|
#if defined(UNITY_COLORSPACE_GAMMA)
|
|
return dot(rgb, float3(0.22, 0.707, 0.071));
|
|
#else
|
|
return dot(rgb, float3(0.0396819152, 0.458021790, 0.00609653955));
|
|
#endif
|
|
}
|
|
|
|
float OpenLitGray(float3 rgb)
|
|
{
|
|
return dot(rgb, float3(1.0/3.0, 1.0/3.0, 1.0/3.0));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Structure
|
|
struct OpenLitLightDatas
|
|
{
|
|
float3 lightDirection;
|
|
float3 directLight;
|
|
float3 indirectLight;
|
|
};
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Light Direction
|
|
// Use `UnityWorldSpaceLightDir(float3 positionWS)` for ForwardAdd passes
|
|
float3 ComputeCustomLightDirection(float4 lightDirectionOverride)
|
|
{
|
|
float3 customDir = length(lightDirectionOverride.xyz) * normalize(mul((float3x3)OPENLIT_MATRIX_M, lightDirectionOverride.xyz));
|
|
return lightDirectionOverride.w ? customDir : lightDirectionOverride.xyz;
|
|
}
|
|
|
|
void ComputeLightDirection(out float3 lightDirection, out float3 lightDirectionForSH9, float4 lightDirectionOverride)
|
|
{
|
|
float3 mainDir = OPENLIT_LIGHT_DIRECTION * OpenLitLuminance(OPENLIT_LIGHT_COLOR);
|
|
#if !defined(LIGHTMAP_ON) && UNITY_SHOULD_SAMPLE_SH
|
|
float3 sh9Dir = unity_SHAr.xyz * 0.333333 + unity_SHAg.xyz * 0.333333 + unity_SHAb.xyz * 0.333333;
|
|
float3 sh9DirAbs = float3(sh9Dir.x, abs(sh9Dir.y), sh9Dir.z);
|
|
#else
|
|
float3 sh9Dir = 0;
|
|
float3 sh9DirAbs = 0;
|
|
#endif
|
|
float3 customDir = ComputeCustomLightDirection(lightDirectionOverride);
|
|
|
|
lightDirection = normalize(sh9DirAbs + mainDir + customDir);
|
|
lightDirectionForSH9 = sh9Dir + mainDir;
|
|
lightDirectionForSH9 = dot(lightDirectionForSH9,lightDirectionForSH9) < 0.000001 ? 0 : normalize(lightDirectionForSH9);
|
|
}
|
|
|
|
void ComputeLightDirection(out float3 lightDirection, out float3 lightDirectionForSH9)
|
|
{
|
|
ComputeLightDirection(lightDirection, lightDirectionForSH9, OPENLIT_FALLBACK_DIRECTION);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// ShadeSH9
|
|
void ShadeSH9ToonDouble(float3 lightDirection, out float3 shMax, out float3 shMin)
|
|
{
|
|
#if !defined(LIGHTMAP_ON) && UNITY_SHOULD_SAMPLE_SH
|
|
float3 N = lightDirection * 0.666666;
|
|
float4 vB = N.xyzz * N.yzzx;
|
|
// L0 L2
|
|
float3 res = float3(unity_SHAr.w,unity_SHAg.w,unity_SHAb.w);
|
|
res.r += dot(unity_SHBr, vB);
|
|
res.g += dot(unity_SHBg, vB);
|
|
res.b += dot(unity_SHBb, vB);
|
|
res += unity_SHC.rgb * (N.x * N.x - N.y * N.y);
|
|
// L1
|
|
float3 l1;
|
|
l1.r = dot(unity_SHAr.rgb, N);
|
|
l1.g = dot(unity_SHAg.rgb, N);
|
|
l1.b = dot(unity_SHAb.rgb, N);
|
|
shMax = res + l1;
|
|
shMin = res - l1;
|
|
#if defined(UNITY_COLORSPACE_GAMMA)
|
|
shMax = OpenLitLinearToSRGB(shMax);
|
|
shMin = OpenLitLinearToSRGB(shMin);
|
|
#endif
|
|
#else
|
|
shMax = 0.0;
|
|
shMin = 0.0;
|
|
#endif
|
|
}
|
|
|
|
void ShadeSH9ToonDouble(out float3 shMax, out float3 shMin)
|
|
{
|
|
float3 lightDirection, lightDirectionForSH9;
|
|
ComputeLightDirection(lightDirection, lightDirectionForSH9, OPENLIT_FALLBACK_DIRECTION);
|
|
ShadeSH9ToonDouble(lightDirectionForSH9, shMax, shMin);
|
|
}
|
|
|
|
float3 ShadeSH9Toon()
|
|
{
|
|
float3 shMax, shMin;
|
|
ShadeSH9ToonDouble(shMax, shMin);
|
|
return shMax;
|
|
}
|
|
|
|
float3 ShadeSH9ToonIndirect()
|
|
{
|
|
float3 shMax, shMin;
|
|
ShadeSH9ToonDouble(shMax, shMin);
|
|
return shMin;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Lighting
|
|
void ComputeSHLightsAndDirection(out float3 lightDirection, out float3 directLight, out float3 indirectLight, float4 lightDirectionOverride)
|
|
{
|
|
float3 lightDirectionForSH9;
|
|
ComputeLightDirection(lightDirection, lightDirectionForSH9, lightDirectionOverride);
|
|
ShadeSH9ToonDouble(lightDirectionForSH9, directLight, indirectLight);
|
|
}
|
|
|
|
void ComputeSHLightsAndDirection(out float3 lightDirection, out float3 directLight, out float3 indirectLight)
|
|
{
|
|
ComputeSHLightsAndDirection(lightDirection, directLight, indirectLight, OPENLIT_FALLBACK_DIRECTION);
|
|
}
|
|
|
|
void ComputeLights(out float3 lightDirection, out float3 directLight, out float3 indirectLight, float4 lightDirectionOverride)
|
|
{
|
|
ComputeSHLightsAndDirection(lightDirection, directLight, indirectLight, lightDirectionOverride);
|
|
directLight += OPENLIT_LIGHT_COLOR;
|
|
}
|
|
|
|
void ComputeLights(out float3 lightDirection, out float3 directLight, out float3 indirectLight)
|
|
{
|
|
ComputeSHLightsAndDirection(lightDirection, directLight, indirectLight);
|
|
directLight += OPENLIT_LIGHT_COLOR;
|
|
}
|
|
|
|
void ComputeLights(out OpenLitLightDatas lightDatas, float4 lightDirectionOverride)
|
|
{
|
|
ComputeLights(lightDatas.lightDirection, lightDatas.directLight, lightDatas.indirectLight, lightDirectionOverride);
|
|
}
|
|
|
|
void ComputeLights(out OpenLitLightDatas lightDatas)
|
|
{
|
|
ComputeLights(lightDatas.lightDirection, lightDatas.directLight, lightDatas.indirectLight);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Correct
|
|
void CorrectLights(inout OpenLitLightDatas lightDatas, float lightMinLimit, float lightMaxLimit, float monochromeLighting, float asUnlit)
|
|
{
|
|
lightDatas.directLight = clamp(lightDatas.directLight, lightMinLimit, lightMaxLimit);
|
|
lightDatas.directLight = lerp(lightDatas.directLight, OpenLitGray(lightDatas.directLight), monochromeLighting);
|
|
lightDatas.directLight = lerp(lightDatas.directLight, 1.0, asUnlit);
|
|
lightDatas.indirectLight = clamp(lightDatas.indirectLight, 0.0, lightMaxLimit);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Vertex Lighting
|
|
float3 ComputeAdditionalLights(float3 positionWS, float3 positionCS)
|
|
{
|
|
float4 toLightX = unity_4LightPosX0 - positionWS.x;
|
|
float4 toLightY = unity_4LightPosY0 - positionWS.y;
|
|
float4 toLightZ = unity_4LightPosZ0 - positionWS.z;
|
|
|
|
float4 lengthSq = toLightX * toLightX + 0.000001;
|
|
lengthSq += toLightY * toLightY;
|
|
lengthSq += toLightZ * toLightZ;
|
|
|
|
//float4 atten = 1.0 / (1.0 + lengthSq * unity_4LightAtten0);
|
|
float4 atten = saturate(saturate((25.0 - lengthSq * unity_4LightAtten0) * 0.111375) / (0.987725 + lengthSq * unity_4LightAtten0));
|
|
|
|
float3 additionalLightColor;
|
|
additionalLightColor = unity_LightColor[0].rgb * atten.x;
|
|
additionalLightColor = additionalLightColor + unity_LightColor[1].rgb * atten.y;
|
|
additionalLightColor = additionalLightColor + unity_LightColor[2].rgb * atten.z;
|
|
additionalLightColor = additionalLightColor + unity_LightColor[3].rgb * atten.w;
|
|
|
|
return additionalLightColor;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Encode and decode
|
|
#if !defined(SHADER_API_GLES)
|
|
// -1 - 1
|
|
uint EncodeNormalizedFloat3ToUint(float3 vec)
|
|
{
|
|
uint valx = abs(vec.x) >= 1 ? 511 : abs(vec.x) * 511;
|
|
uint valy = abs(vec.y) >= 1 ? 511 : abs(vec.y) * 511;
|
|
uint valz = abs(vec.z) >= 1 ? 511 : abs(vec.z) * 511;
|
|
valx = valx & 0x000001ffu;
|
|
valy = valy & 0x000001ffu;
|
|
valz = valz & 0x000001ffu;
|
|
valx += vec.x > 0 ? 0 : 512;
|
|
valy += vec.y > 0 ? 0 : 512;
|
|
valz += vec.z > 0 ? 0 : 512;
|
|
|
|
valy = valy << 10;
|
|
valz = valz << 20;
|
|
return valx | valy | valz;
|
|
}
|
|
|
|
float3 DecodeNormalizedFloat3FromUint(uint val)
|
|
{
|
|
// 5 math in target 5.0
|
|
uint3 val3 = val >> uint3(0,10,20);
|
|
float3 vec = val3 & 0x000001ffu;
|
|
vec /= (val3 & 0x00000200u) == 0x00000200u ? -511.0 : 511.0;
|
|
return vec;
|
|
}
|
|
|
|
// 0 - 999
|
|
uint EncodeHDRColorToUint(float3 col)
|
|
{
|
|
col = clamp(col, 0, 999);
|
|
float maxcol = max(col.r,max(col.g,col.b));
|
|
|
|
float floatDigit = maxcol == 0 ? 0 : log10(maxcol);
|
|
uint digit = floatDigit >= 0 ? floatDigit + 1 : 0;
|
|
if(digit > 3) digit = 3;
|
|
float scale = pow(10,digit);
|
|
col /= scale;
|
|
|
|
uint R = col.r * 1023;
|
|
uint G = col.g * 1023;
|
|
uint B = col.b * 1023;
|
|
uint M = digit;
|
|
R = R & 0x000003ffu;
|
|
G = G & 0x000003ffu;
|
|
B = B & 0x000003ffu;
|
|
|
|
G = G << 10;
|
|
B = B << 20;
|
|
M = M << 30;
|
|
return R | G | B | M;
|
|
}
|
|
|
|
float3 DecodeHDRColorFromUint(uint val)
|
|
{
|
|
// 5 math in target 5.0
|
|
uint4 RGBM = val >> uint4(0,10,20,30);
|
|
return float3(RGBM.rgb & 0x000003ffu) / 1023.0 * pow(10,RGBM.a);
|
|
}
|
|
|
|
void PackLightDatas(out uint3 pack, OpenLitLightDatas lightDatas)
|
|
{
|
|
pack = uint3(
|
|
EncodeNormalizedFloat3ToUint(lightDatas.lightDirection),
|
|
EncodeHDRColorToUint(lightDatas.directLight),
|
|
EncodeHDRColorToUint(lightDatas.indirectLight)
|
|
);
|
|
}
|
|
|
|
void UnpackLightDatas(out OpenLitLightDatas lightDatas, uint3 pack)
|
|
{
|
|
lightDatas.lightDirection = DecodeNormalizedFloat3FromUint(pack.x);
|
|
lightDatas.directLight = DecodeHDRColorFromUint(pack.y);
|
|
lightDatas.indirectLight = DecodeHDRColorFromUint(pack.z);
|
|
}
|
|
#endif // #if !defined(SHADER_API_GLES)
|
|
|
|
#endif // #if !defined(OPENLIT_CORE_INCLUDED) |