You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.4 KiB
141 lines
3.4 KiB
1 year ago
|
#include "UnityCG.cginc"
|
||
|
#include "Lighting.cginc"
|
||
|
#include "UnityPBSLighting.cginc"
|
||
|
#include "AutoLight.cginc"
|
||
|
|
||
|
struct PointLight
|
||
|
{
|
||
|
float4 color;
|
||
|
float range;
|
||
|
float3 position;
|
||
|
};
|
||
|
|
||
|
StructuredBuffer<PointLight> _PointLights;
|
||
|
int _PointLightsNumber;
|
||
|
|
||
|
struct SpotLight
|
||
|
{
|
||
|
float4 color;
|
||
|
float3 position;
|
||
|
float4 direction;
|
||
|
float4 params;
|
||
|
};
|
||
|
|
||
|
StructuredBuffer<SpotLight> _SpotLights;
|
||
|
int _SpotLightsNumber;
|
||
|
|
||
|
float _Metallic;
|
||
|
|
||
|
|
||
|
UnityLight CreateUnityLight(float3 pos, float4 color, float3 worldPos, float3 normal)
|
||
|
{
|
||
|
UnityLight light;
|
||
|
|
||
|
light.dir = pos;
|
||
|
light.color = color;
|
||
|
light.ndotl = DotClamped(normal, light.dir);
|
||
|
|
||
|
return light;
|
||
|
}
|
||
|
|
||
|
float GetAttenuation(float dist, float inverseRange, float coeff)
|
||
|
{
|
||
|
return lerp(1.0, (1.0 - pow(dist * inverseRange * inverseRange, coeff)), 1);
|
||
|
}
|
||
|
|
||
|
half4 ApplyLighting(float3 albedo, float3 normals, float3 worldPos, float alpha)
|
||
|
{
|
||
|
fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
|
||
|
|
||
|
#ifdef UNITY_COMPILER_HLSL
|
||
|
SurfaceOutputStandard o = (SurfaceOutputStandard)0;
|
||
|
#else
|
||
|
SurfaceOutputStandard o;
|
||
|
#endif
|
||
|
|
||
|
o.Albedo.rgb = albedo;
|
||
|
o.Emission = 0.0;
|
||
|
o.Alpha = 1.0;
|
||
|
o.Occlusion = 1.0;
|
||
|
o.Metallic = _Metallic;
|
||
|
o.Normal.rgb = mul((float3x3)unity_CameraToWorld, normals);
|
||
|
|
||
|
float3 specularTint;
|
||
|
float oneMinusReflectivity;
|
||
|
o.Albedo.rgb = DiffuseAndSpecularFromMetallic(albedo, o.Metallic, specularTint, oneMinusReflectivity);
|
||
|
|
||
|
float4 c = 0;
|
||
|
|
||
|
// Setup lighting environment
|
||
|
UnityGI gi;
|
||
|
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
|
||
|
gi.indirect.diffuse = 0;
|
||
|
gi.indirect.specular = 0;
|
||
|
|
||
|
// point light
|
||
|
UNITY_LOOP
|
||
|
for (int pi = 0; pi < _PointLightsNumber; pi++)
|
||
|
{
|
||
|
float3 lightVec = _PointLights[pi].position - worldPos;
|
||
|
|
||
|
|
||
|
if (_PointLights[pi].range - length(lightVec) < 0)
|
||
|
continue;
|
||
|
|
||
|
float att = GetAttenuation(dot(lightVec, lightVec), 1 / _PointLights[pi].range, 0.2);
|
||
|
float v = dot(lightVec, float3(o.Normal.x, o.Normal.y, o.Normal.z));
|
||
|
|
||
|
//Remove light from backward
|
||
|
if (dot(lightVec, float3(o.Normal.x, o.Normal.y, o.Normal.z)) <= 0.0)
|
||
|
continue;
|
||
|
|
||
|
UnityLight p = CreateUnityLight(lightVec, _PointLights[pi].color * att * alpha, worldPos, o.Normal.rgb);
|
||
|
|
||
|
gi.light = p;
|
||
|
c += UNITY_BRDF_PBS(o.Albedo.rgb, specularTint, oneMinusReflectivity, 0, o.Normal.rgb, normalize(_WorldSpaceCameraPos - worldPos), p, gi.indirect);
|
||
|
c.a = 1.0;
|
||
|
}
|
||
|
|
||
|
c.a = 1.0;
|
||
|
|
||
|
// spot light
|
||
|
UNITY_LOOP
|
||
|
for (int si = 0; si < _SpotLightsNumber; si++)
|
||
|
{
|
||
|
float3 lightVec = _SpotLights[si].position - worldPos;
|
||
|
float att = GetAttenuation(dot(lightVec, lightVec), _SpotLights[si].params.z, 0.8);
|
||
|
|
||
|
float3 dirSpotToWorld = -lightVec;
|
||
|
float dotDirectionWorld = dot(normalize(dirSpotToWorld), _SpotLights[si].direction.xyz);
|
||
|
float angleWorld = degrees(acos(dotDirectionWorld));
|
||
|
float angleMax = _SpotLights[si].params.x / 2.0;
|
||
|
|
||
|
UNITY_BRANCH
|
||
|
if (dotDirectionWorld < 0 || dotDirectionWorld < _SpotLights[si].direction.w)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
float angleP = angleMax * (1 - _SpotLights[si].params.w);
|
||
|
|
||
|
UNITY_BRANCH
|
||
|
if (angleP < angleWorld && angleWorld < angleMax)
|
||
|
{
|
||
|
att *= (angleMax - angleWorld) / (angleMax - angleP);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
att = saturate(att);
|
||
|
UnityLight p = CreateUnityLight(lightVec, (_SpotLights[si].color) * att * alpha, worldPos, o.Normal.rgb);
|
||
|
|
||
|
gi.light = p;
|
||
|
c += UNITY_BRDF_PBS(o.Albedo.rgb, specularTint, oneMinusReflectivity, 1, o.Normal.rgb, normalize(_WorldSpaceCameraPos - worldPos), p, gi.indirect);
|
||
|
c.a = 1.0;
|
||
|
}
|
||
|
|
||
|
return c;
|
||
|
}
|
||
|
|