-
-
Save baukeJansen/e2cf05f734a910aa13175b490942b4e6 to your computer and use it in GitHub Desktop.
// Warning, because of a bug the code below marks UnityInput.hlsl and Lighting.hlsl as imported but only adds the required functionality | |
// Reason = error with redefined variables | |
//=============================================================================================================================================================================== | |
// Stripped down version of: https://github.com/Unity-Technologies/ScriptableRenderPipeline/blob/master/com.unity.render-pipelines.lightweight/ShaderLibrary/UnityInput.hlsl | |
//=============================================================================================================================================================================== | |
#ifndef LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED | |
#define LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED | |
// Light Indices block feature | |
// These are set internally by the engine upon request by RendererConfiguration. | |
real4 unity_LightData; | |
real4 unity_LightIndices[2]; | |
#endif // LIGHTWEIGHT_SHADER_VARIABLES_INCLUDED | |
//=============================================================================================================================================================================== | |
// Stripped down version of: https://github.com/Unity-Technologies/ScriptableRenderPipeline/blob/master/com.unity.render-pipelines.lightweight/ShaderLibrary/Lighting.hlsl | |
//=============================================================================================================================================================================== | |
#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED | |
#define LIGHTWEIGHT_LIGHTING_INCLUDED | |
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl" | |
#include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Shadows.hlsl" | |
/////////////////////////////////////////////////////////////////////////////// | |
// Light Helpers // | |
/////////////////////////////////////////////////////////////////////////////// | |
// Abstraction over Light shading data. | |
struct Light | |
{ | |
half3 direction; | |
half3 color; | |
half distanceAttenuation; | |
half shadowAttenuation; | |
}; | |
int GetPerObjectLightIndex(int index) | |
{ | |
// The following code is more optimal than indexing unity_4LightIndices0. | |
// Conditional moves are branch free even on mali-400 | |
half2 lightIndex2 = (index < 2.0h) ? unity_LightIndices[0].xy : unity_LightIndices[0].zw; | |
half i_rem = (index < 2.0h) ? index : index - 2.0h; | |
return (i_rem < 1.0h) ? lightIndex2.x : lightIndex2.y; | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Attenuation Functions / | |
/////////////////////////////////////////////////////////////////////////////// | |
// Matches Unity Vanila attenuation | |
// Attenuation smoothly decreases to light range. | |
float DistanceAttenuation(float distanceSqr, half2 distanceAttenuation) | |
{ | |
// We use a shared distance attenuation for additional directional and puctual lights | |
// for directional lights attenuation will be 1 | |
float lightAtten = rcp(distanceSqr); | |
#if SHADER_HINT_NICE_QUALITY | |
// Use the smoothing factor also used in the Unity lightmapper. | |
half factor = distanceSqr * distanceAttenuation.x; | |
half smoothFactor = saturate(1.0h - factor * factor); | |
smoothFactor = smoothFactor * smoothFactor; | |
#else | |
// We need to smoothly fade attenuation to light range. We start fading linearly at 80% of light range | |
// Therefore: | |
// fadeDistance = (0.8 * 0.8 * lightRangeSq) | |
// smoothFactor = (lightRangeSqr - distanceSqr) / (lightRangeSqr - fadeDistance) | |
// We can rewrite that to fit a MAD by doing | |
// distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr) | |
// distanceSqr * distanceAttenuation.y + distanceAttenuation.z | |
half smoothFactor = saturate(distanceSqr * distanceAttenuation.x + distanceAttenuation.y); | |
#endif | |
return lightAtten * smoothFactor; | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Light Abstraction // | |
/////////////////////////////////////////////////////////////////////////////// | |
Light GetMainLight() | |
{ | |
Light light; | |
light.direction = _MainLightPosition.xyz; | |
light.distanceAttenuation = unity_LightData.z; | |
#if defined(LIGHTMAP_ON) | |
light.distanceAttenuation *= unity_ProbesOcclusion.x; | |
#endif | |
light.shadowAttenuation = 1.0; | |
light.color = _MainLightColor.rgb; | |
return light; | |
} | |
Light GetMainLight(float4 shadowCoord) | |
{ | |
Light light = GetMainLight(); | |
light.shadowAttenuation = MainLightRealtimeShadow(shadowCoord); | |
return light; | |
} | |
Light GetAdditionalLight(int i, float3 positionWS) | |
{ | |
int perObjectLightIndex = GetPerObjectLightIndex(i); | |
// The following code will turn into a branching madhouse on platforms that don't support | |
// dynamic indexing. Ideally we need to configure light data at a cluster of | |
// objects granularity level. We will only be able to do that when scriptable culling kicks in. | |
// TODO: Use StructuredBuffer on PC/Console and profile access speed on mobile that support it. | |
// Abstraction over Light input constants | |
float3 lightPositionWS = _AdditionalLightsPosition[perObjectLightIndex].xyz; | |
half4 distanceAndSpotAttenuation = _AdditionalLightsAttenuation[perObjectLightIndex]; | |
half4 spotDirection = _AdditionalLightsSpotDir[perObjectLightIndex]; | |
float3 lightVector = lightPositionWS - positionWS; | |
float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN); | |
half3 lightDirection = half3(lightVector * rsqrt(distanceSqr)); | |
half attenuation = DistanceAttenuation(distanceSqr, distanceAndSpotAttenuation.xy) * AngleAttenuation(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw); | |
Light light; | |
light.direction = lightDirection; | |
light.distanceAttenuation = attenuation; | |
light.shadowAttenuation = AdditionalLightRealtimeShadow(perObjectLightIndex, positionWS); | |
light.color = _AdditionalLightsColor[perObjectLightIndex].rgb; | |
// In case we're using light probes, we can sample the attenuation from the `unity_ProbesOcclusion` | |
#if defined(LIGHTMAP_ON) | |
// First find the probe channel from the light. | |
// Then sample `unity_ProbesOcclusion` for the baked occlusion. | |
// If the light is not baked, the channel is -1, and we need to apply no occlusion. | |
half4 lightOcclusionProbeInfo = _AdditionalLightsOcclusionProbes[perObjectLightIndex]; | |
// probeChannel is the index in 'unity_ProbesOcclusion' that holds the proper occlusion value. | |
int probeChannel = lightOcclusionProbeInfo.x; | |
// lightProbeContribution is set to 0 if we are indeed using a probe, otherwise set to 1. | |
half lightProbeContribution = lightOcclusionProbeInfo.y; | |
half probeOcclusionValue = unity_ProbesOcclusion[probeChannel]; | |
light.distanceAttenuation *= max(probeOcclusionValue, lightProbeContribution); | |
#endif | |
return light; | |
} | |
#endif //LIGHTWEIGHT_LIGHTING_INCLUDED | |
//============================================================================================================================= | |
// Original MainLightNode script by 'Ciro Continisio': https://gist.github.com/ciro-unity/a55d73bcda93ca149cf7fd7e407f8812 | |
//============================================================================================================================= | |
void MainLightNode_float(float3 worldPos, out float3 direction, out float attenuation, out float3 color) | |
{ | |
Light mainLight = GetMainLight(); | |
color = mainLight.color; | |
direction = mainLight.direction; | |
float4 shadowCoord; | |
#ifdef LIGHTWEIGHT_SHADOWS_INCLUDED | |
#if SHADOWS_SCREEN | |
float4 clipPos = TransformWorldToHClip(worldPos); | |
shadowCoord = ComputeScreenPos(clipPos); | |
#else | |
shadowCoord = TransformWorldToShadowCoord(worldPos); | |
#endif | |
#endif | |
attenuation = MainLightRealtimeShadow(shadowCoord); | |
} |
Works, nice job -- but seems to only detect a light if it's set to be a directional light, which isn't incredibly useful. Looks like I'd need to invoke the other methods to get additional lights....
off into the deep to do so I go
I've done it, because i had to get every light's position saturated to get my translucency algo working, there is example in the code below on how to get additionnal light in lighting (it use a for loop with the index [i = light count] to found which punctual light it is
.
Light GetAdditionalLight(int i, float3 positionWS)
{
int perObjectLightIndex = GetPerObjectLightIndex(i);
etc }
So basically you can enhance the code here to get your properties, here i tryed :
float3 WorldSpacePosition = // found something like "worldPos", i have a different name;
float lightAtten = 0;
#ifdef _ADDITIONAL_LIGHTS // lightAtten_frag
int lightAtten_pixelLightCount = GetAdditionalLightsCount();
for (int i = 0; i < lightAtten_pixelLightCount; ++i)
{//lightAtten_frag
Light lightAtten_pointLight = GetAdditionalLight( i, WorldSpacePosition );
lightAtten += lightAtten_pointLight.distanceAttenuation * lightAtten_pointLight.shadowAttenuation;
}//lightAtten_frag
#endif
//lightAtten_frag
PoncutalLightAtten = saturate( lightAtten );
}
Voilà you can get additionnal light's attenuation, and you can add direction, color etc if want to
I'm getting an error: Shader error in 'hidden/preview/CustomFunction_38565C48': undeclared identifier 'unity_LightIndices' at line 73 (on d3d11)
. Any ideas?
Using Unity 2019.2.0.f1 currently.
I've tried reorganizing the content, but nothing seems to get around the issue. :-/ Thanks.
@Snakenjah,
I know it's a bit of an ask, but could you show how referencing additional lights this is inserted within the existing code - or make an easily-downloadable repository?
I'm still a beginner, so still struggling with wrapping my head around such things.
Does this work in latestet unity (universal render pipeline)?
I renamed #include "Packages/com.unity.render-pipelines.lightweight/ShaderLibrary/Shadows.hlsl" to #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
to
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
i get redefinition of _Time error
Works, nice job -- but seems to only detect a light if it's set to be a directional light, which isn't incredibly useful. Looks like I'd need to invoke the other methods to get additional lights....
off into the deep to do so I go