E:\OGL\custom-srp-09-point-and-spot-lights\Assets\Custom RP\ShaderLibrary\Light.hlsl
#ifndef CUSTOM_LIGHT_INCLUDED
#define CUSTOM_LIGHT_INCLUDED
#define MAX_DIRECTIONAL_LIGHT_COUNT 4
#define MAX_OTHER_LIGHT_COUNT 64
CBUFFER_START(_CustomLight)
int _DirectionalLightCount;
float4 _DirectionalLightColors[MAX_DIRECTIONAL_LIGHT_COUNT];
float4 _DirectionalLightDirections[MAX_DIRECTIONAL_LIGHT_COUNT];
float4 _DirectionalLightShadowData[MAX_DIRECTIONAL_LIGHT_COUNT];
int _OtherLightCount;
float4 _OtherLightColors[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightPositions[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightDirections[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightSpotAngles[MAX_OTHER_LIGHT_COUNT];
float4 _OtherLightShadowData[MAX_OTHER_LIGHT_COUNT];
CBUFFER_END
struct Light {
float3 color;
float3 direction;
float attenuation;
};
int GetDirectionalLightCount () {
return _DirectionalLightCount;
}
DirectionalShadowData GetDirectionalShadowData (
int lightIndex, ShadowData shadowData
) {
DirectionalShadowData data;
data.strength = _DirectionalLightShadowData[lightIndex].x;
data.tileIndex =
_DirectionalLightShadowData[lightIndex].y + shadowData.cascadeIndex;
data.normalBias = _DirectionalLightShadowData[lightIndex].z;
data.shadowMaskChannel = _DirectionalLightShadowData[lightIndex].w;
return data;
}
Light GetDirectionalLight (int index, Surface surfaceWS, ShadowData shadowData) {
Light light;
light.color = _DirectionalLightColors[index].rgb;
light.direction = _DirectionalLightDirections[index].xyz;
DirectionalShadowData dirShadowData =
GetDirectionalShadowData(index, shadowData);
light.attenuation =
GetDirectionalShadowAttenuation(dirShadowData, shadowData, surfaceWS);
return light;
}
int GetOtherLightCount () {
return _OtherLightCount;
}
OtherShadowData GetOtherShadowData (int lightIndex) {
OtherShadowData data;
data.strength = _OtherLightShadowData[lightIndex].x;
data.shadowMaskChannel = _OtherLightShadowData[lightIndex].w;
return data;
}
Light GetOtherLight (int index, Surface surfaceWS, ShadowData shadowData)
{
Light light;
light.color = _OtherLightColors[index].rgb;
float3 ray = _OtherLightPositions[index].xyz - surfaceWS.position;
light.direction = normalize(ray);
float distanceSqr = max(dot(ray, ray), 0.00001);
float rangeAttenuation = Square(
saturate(1.0 - Square(distanceSqr * _OtherLightPositions[index].w))
);
float4 spotAngles = _OtherLightSpotAngles[index];
float spotAttenuation = Square(
saturate(dot(_OtherLightDirections[index].xyz, light.direction) *
spotAngles.x + spotAngles.y)
);
OtherShadowData otherShadowData = GetOtherShadowData(index);
light.attenuation =
GetOtherShadowAttenuation(otherShadowData, shadowData, surfaceWS) *
spotAttenuation * rangeAttenuation / distanceSqr;
return light;
}
#endif
E:\OGL\custom-srp-09-point-and-spot-lights\Assets\Custom RP\ShaderLibrary\Lighting.hlsl
#ifndef CUSTOM_LIGHTING_INCLUDED
#define CUSTOM_LIGHTING_INCLUDED
float3 IncomingLight (Surface surface, Light light) {
return
saturate(dot(surface.normal, light.direction) * light.attenuation) *
light.color;
}
float3 GetLighting (Surface surface, BRDF brdf, Light light) {
return IncomingLight(surface, light) * DirectBRDF(surface, brdf, light);
}
float3 GetLighting (Surface surfaceWS, BRDF brdf, GI gi) {
ShadowData shadowData = GetShadowData(surfaceWS);
shadowData.shadowMask = gi.shadowMask;
float3 color = IndirectBRDF(surfaceWS, brdf, gi.diffuse, gi.specular);
for (int i = 0; i < GetDirectionalLightCount(); i++) {
Light light = GetDirectionalLight(i, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#if defined(_LIGHTS_PER_OBJECT)
for (int j = 0; j < min(unity_LightData.y, 8); j++) {
int lightIndex = unity_LightIndices[j / 4][j % 4];
Light light = GetOtherLight(lightIndex, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#else
for (int j = 0; j < GetOtherLightCount(); j++) {
Light light = GetOtherLight(j, surfaceWS, shadowData);
color += GetLighting(surfaceWS, brdf, light);
}
#endif
return color;
}
#endif
E:\OGL\custom-srp-09-point-and-spot-lights\Assets\Custom RP\Shaders\LitPass.hlsl
#ifndef CUSTOM_LIT_PASS_INCLUDED
#define CUSTOM_LIT_PASS_INCLUDED
#include "../ShaderLibrary/Surface.hlsl"
#include "../ShaderLibrary/Shadows.hlsl"
#include "../ShaderLibrary/Light.hlsl"
#include "../ShaderLibrary/BRDF.hlsl"
#include "../ShaderLibrary/GI.hlsl"
#include "../ShaderLibrary/Lighting.hlsl"
struct Attributes {
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 baseUV : TEXCOORD0;
GI_ATTRIBUTE_DATA
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings {
float4 positionCS : SV_POSITION;
float3 positionWS : VAR_POSITION;
float3 normalWS : VAR_NORMAL;
#if defined(_NORMAL_MAP)
float4 tangentWS : VAR_TANGENT;
#endif
float2 baseUV : VAR_BASE_UV;
#if defined(_DETAIL_MAP)
float2 detailUV : VAR_DETAIL_UV;
#endif
GI_VARYINGS_DATA
UNITY_VERTEX_INPUT_INSTANCE_ID
};
Varyings LitPassVertex (Attributes input) {
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
TRANSFER_GI_DATA(input, output);
output.positionWS = TransformObjectToWorld(input.positionOS);
output.positionCS = TransformWorldToHClip(output.positionWS);
output.normalWS = TransformObjectToWorldNormal(input.normalOS);
#if defined(_NORMAL_MAP)
output.tangentWS = float4(
TransformObjectToWorldDir(input.tangentOS.xyz), input.tangentOS.w
);
#endif
output.baseUV = TransformBaseUV(input.baseUV);
#if defined(_DETAIL_MAP)
output.detailUV = TransformDetailUV(input.baseUV);
#endif
return output;
}
float4 LitPassFragment (Varyings input) : SV_TARGET {
UNITY_SETUP_INSTANCE_ID(input);
ClipLOD(input.positionCS.xy, unity_LODFade.x);
InputConfig config = GetInputConfig(input.baseUV);
#if defined(_MASK_MAP)
config.useMask = true;
#endif
#if defined(_DETAIL_MAP)
config.detailUV = input.detailUV;
config.useDetail = true;
#endif
float4 base = GetBase(config);
#if defined(_CLIPPING)
clip(base.a - GetCutoff(config));
#endif
Surface surface;
surface.position = input.positionWS;
#if defined(_NORMAL_MAP)
surface.normal = NormalTangentToWorld(
GetNormalTS(config), input.normalWS, input.tangentWS
);
#else
surface.normal = normalize(input.normalWS);
#endif
surface.interpolatedNormal = surface.normal;
surface.viewDirection = normalize(_WorldSpaceCameraPos - input.positionWS);
surface.depth = -TransformWorldToView(input.positionWS).z;
surface.color = base.rgb;
surface.alpha = base.a;
surface.metallic = GetMetallic(config);
surface.occlusion = GetOcclusion(config);
surface.smoothness = GetSmoothness(config);
surface.fresnelStrength = GetFresnel(config);
surface.dither = InterleavedGradientNoise(input.positionCS.xy, 0);
#if defined(_PREMULTIPLY_ALPHA)
BRDF brdf = GetBRDF(surface, true);
#else
BRDF brdf = GetBRDF(surface);
#endif
GI gi = GetGI(GI_FRAGMENT_DATA(input), surface, brdf);
float3 color = GetLighting(surface, brdf, gi);
color += GetEmission(config);
return float4(color, surface.alpha);
}
#endif