浏览代码

Removed Attenuation texture dependency due to precision issues with an alpha8. Optimized attenuation function to use 1 MAD instruction for the smooth factor.

/Add-support-for-light-specular-color-tint
Felipe Lira 7 年前
当前提交
8f6a326d
共有 7 个文件被更改,包括 91 次插入90 次删除
  1. 5
      ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs
  2. 1
      ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardParticlesShaderGUI.cs
  3. 7
      ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs
  4. 70
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
  5. 2
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
  6. 7
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs
  7. 89
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc

5
ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs


"Shader to use when creating materials");
public static GUIContent msaaContent = new GUIContent("Anti Aliasing (MSAA)", "Controls the global anti aliasing quality. When set to disabled, MSAA will not be performed even if the camera allows it.");
public static GUIContent attenuationTextureLabel = new GUIContent("Attenuation Texture", "Light attenuation falloff texture");
}
private int kMaxSupportedAdditionalPixelLights = 8;

private SerializedProperty m_DefaultUIMaterial;
private SerializedProperty m_DefaultShader;
private SerializedProperty m_MSAA;
private SerializedProperty m_AttenuationTexture;
void OnEnable()
{

m_DefaultUIMaterial = serializedObject.FindProperty("m_DefaultUIMaterial");
m_DefaultShader = serializedObject.FindProperty("m_DefaultShader");
m_MSAA = serializedObject.FindProperty("m_MSAA");
m_AttenuationTexture = serializedObject.FindProperty("m_AttenuationTexture");
}
public override void OnInspectorGUI()

EditorGUILayout.PropertyField(m_SupportsVertexLightProp, Styles.enableVertexLightLabel);
EditorGUILayout.PropertyField(m_SupportSoftParticlesProp, Styles.enableSoftParticles);
EditorGUILayout.PropertyField(m_MSAA, Styles.msaaContent);
EditorGUILayout.PropertyField(m_AttenuationTexture, Styles.attenuationTextureLabel);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUILayout.Space();

1
ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardParticlesShaderGUI.cs


void DoNormalMapArea(Material material)
{
bool hasZWrite = (material.GetInt("_ZWrite") != 0);
bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f);
if (useLighting)
{

7
ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs


public static class PerFrameBuffer
{
public static int _GlossyEnvironmentColor;
public static int _AttenuationTexture;
}
public static class PerCameraBuffer

public static int _MainLightAttenuationParams;
public static int _MainLightDistanceAttenuation;
public static int _MainLightSpotAttenuation;
public static int _MainLightCookie;
public static int _WorldToLight;

public static int _AdditionalLightAttenuationParams;
public static int _AdditionalLightDistanceAttenuation;
public static int _AdditionalLightSpotAttenuation;
}
}

70
ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs


private Vector4[] m_LightPositions = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightAttenuations = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightDistanceAttenuations = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightSpotAttenuations = new Vector4[kMaxVisibleAdditionalLights];
private Camera m_CurrCamera = null;

BuildShadowSettings();
PerFrameBuffer._GlossyEnvironmentColor = Shader.PropertyToID("_GlossyEnvironmentColor");
PerFrameBuffer._AttenuationTexture = Shader.PropertyToID("_AttenuationTexture");
PerCameraBuffer._MainLightAttenuationParams = Shader.PropertyToID("_MainLightAttenuationParams");
PerCameraBuffer._MainLightDistanceAttenuation = Shader.PropertyToID("_MainLightDistanceAttenuation");
PerCameraBuffer._MainLightSpotAttenuation = Shader.PropertyToID("_MainLightSpotAttenuation");
PerCameraBuffer._AdditionalLightAttenuationParams = Shader.PropertyToID("_AdditionalLightAttenuationParams");
PerCameraBuffer._AdditionalLightDistanceAttenuation = Shader.PropertyToID("_AdditionalLightDistanceAttenuation");
PerCameraBuffer._AdditionalLightSpotAttenuation = Shader.PropertyToID("_AdditionalLightSpotAttenuation");
m_ShadowMapTexture = Shader.PropertyToID("_ShadowMap");
m_CameraColorTexture = Shader.PropertyToID("_CameraColorTexture");

return (lightIndex < totalVisibleLights && visibleLights[lightIndex].light.shadows != LightShadows.None) ? lightIndex : 0;
}
private void InitializeLightConstants(VisibleLight[] lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightSpotDir,
out Vector4 lightAttenuationParams)
private void InitializeLightConstants(VisibleLight[] lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
lightAttenuationParams = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
lightDistanceAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
lightSpotAttenuation = new Vector4(0.0f, 1.0f, 0.0f, 0.0f);
// When no lights are visible, main light will be set to -1.
// In this case we initialize it to default values and return

lightColor = light.finalColor;
float rangeSq = light.range * light.range;
float quadAtten = 0.0f;
// Directional Light attenuation is initialize so distance attenuation always be 1.0
quadAtten = (m_Asset.AttenuationTexture != null) ? 1.0f : 25.0f / rangeSq;
{
// Light attenuation in lightweight matches the unity vanilla one.
// attenuation = 1.0 / 1.0 + distanceToLightSqr * quadraticAttenuation
// then a smooth factor is applied to linearly fade attenuation to light range
// the attenuation smooth factor starts having effect at 80% of light range
// smoothFactor = (lightRangeSqr - distanceToLightSqr) / (lightRangeSqr - fadeStartDistanceSqr)
// We rewrite smoothFactor to be able to pre compute the constant terms below and apply the smooth factor
// with one MAD instruction
// smoothFactor = distanceSqr * (1.0 / (fadeDistanceSqr - lightRangeSqr)) + (-lightRangeSqr / (fadeDistanceSqr - lightRangeSqr)
// distanceSqr * oneOverFadeRangeSqr + lightRangeSqrOverFadeRangeSqr
float lightRangeSqr = light.range * light.range;
float fadeStartDistanceSqr = 0.8f * 0.8f * lightRangeSqr;
float fadeRangeSqr = (fadeStartDistanceSqr - lightRangeSqr);
float oneOverFadeRangeSqr = 1.0f / fadeRangeSqr;
float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
float quadAtten = 25.0f / lightRangeSqr;
lightDistanceAttenuation = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 0.0f);
}
if (light.lightType == LightType.Spot)
{

float invAngleRange = 1.0f / smoothAngleRange;
float add = -cosOuterAngle * invAngleRange;
lightAttenuationParams = new Vector4(invAngleRange, add, quadAtten, rangeSq);
}
else
{
lightSpotDir = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
lightAttenuationParams = new Vector4(0.0f, 1.0f, quadAtten, rangeSq);
lightSpotAttenuation = new Vector4(invAngleRange, add, 0.0f);
}
}

SphericalHarmonicsL2 ambientSH = RenderSettings.ambientProbe;
Vector4 glossyEnvColor = new Vector4(ambientSH[0, 0], ambientSH[1, 0], ambientSH[2, 0]) * RenderSettings.reflectionIntensity;
CommandBuffer cmd = CommandBufferPool.Get("SetupPerFrameConstants");
cmd.SetGlobalVector(PerFrameBuffer._GlossyEnvironmentColor, glossyEnvColor);
if (m_Asset.AttenuationTexture != null) cmd.SetGlobalTexture(PerFrameBuffer._AttenuationTexture, m_Asset.AttenuationTexture);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release (cmd);
Shader.SetGlobalVector(PerFrameBuffer._GlossyEnvironmentColor, glossyEnvColor);
}
private void SetupShaderLightConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData)

private void SetupMainLightConstants(CommandBuffer cmd, VisibleLight[] lights, int lightIndex)
{
Vector4 lightPos, lightColor, lightSpotDir, lightAttenuationParams;
InitializeLightConstants(lights, lightIndex, out lightPos, out lightColor, out lightSpotDir, out lightAttenuationParams);
Vector4 lightPos, lightColor, lightDistanceAttenuation, lightSpotDir, lightSpotAttenuation;
InitializeLightConstants(lights, lightIndex, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
cmd.SetGlobalVector(PerCameraBuffer._MainLightDistanceAttenuation, lightDistanceAttenuation);
cmd.SetGlobalVector(PerCameraBuffer._MainLightAttenuationParams, lightAttenuationParams);
cmd.SetGlobalVector(PerCameraBuffer._MainLightSpotAttenuation, lightSpotAttenuation);
if (lightIndex >= 0 && LightweightUtils.IsSupportedCookieType(lights[lightIndex].lightType) && lights[lightIndex].light.cookie != null)
{

perObjectLightIndexMap[GetLightUnsortedIndex(i)] = additionalLightIndex;
InitializeLightConstants(lights, i, out m_LightPositions[additionalLightIndex],
out m_LightColors[additionalLightIndex],
out m_LightDistanceAttenuations[additionalLightIndex],
out m_LightAttenuations[additionalLightIndex]);
out m_LightSpotAttenuations[additionalLightIndex]);
additionalLightIndex++;
}
}

lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightPosition, m_LightPositions);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightColor, m_LightColors);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightAttenuationParams, m_LightAttenuations);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightDistanceAttenuation, m_LightDistanceAttenuations);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightSpotAttenuation, m_LightSpotAttenuations);
}
private void SetupShadowShaderConstants(CommandBuffer cmd, ref VisibleLight shadowLight, int cascadeCount)

{
int depthSlice = (m_IntermediateTextureArray) ? -1 : 0;
if (depthRT != BuiltinRenderTextureType.None)
cmd.SetRenderTarget(colorRT, depthRT/*, 0, CubemapFace.Unknown, depthSlice*/);
cmd.SetRenderTarget(colorRT, depthRT, 0, CubemapFace.Unknown, depthSlice);
cmd.SetRenderTarget(colorRT/*, 0, CubemapFace.Unknown, depthSlice*/);
cmd.SetRenderTarget(colorRT, 0, CubemapFace.Unknown, depthSlice);
}
private void RenderPostProcess(CommandBuffer cmd, bool opaqueOnly)

2
ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset


m_ShadowCascades: 1
m_Cascade2Split: 0.25
m_Cascade4Split: {x: 0.067, y: 0.2, z: 0.467}
m_AttenuationTexture: {fileID: 2800000, guid: ee420ad43ff580149a07f10ad66c49ff,
type: 3}
m_DefaultDiffuseMaterial: {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d,
type: 2}
m_DefaultParticleMaterial: {fileID: 2100000, guid: e823cd5b5d27c0f4b8256e7c12ee3e6d,

7
ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs


[SerializeField] private ShadowCascades m_ShadowCascades = ShadowCascades.NO_CASCADES;
[SerializeField] private float m_Cascade2Split = 0.25f;
[SerializeField] private Vector3 m_Cascade4Split = new Vector3(0.067f, 0.2f, 0.467f);
[SerializeField] private Texture2D m_AttenuationTexture;
[SerializeField] private Material m_DefaultDiffuseMaterial;
[SerializeField] private Material m_DefaultParticleMaterial;

{
get { return m_Cascade4Split; }
private set { m_Cascade4Split = value; }
}
public Texture2D AttenuationTexture
{
get { return m_AttenuationTexture; }
set { m_AttenuationTexture = value; }
}
public override Material GetDefaultMaterial()

89
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc


#define INITIALIZE_MAIN_LIGHT(light) \
light.pos = _MainLightPosition; \
light.color = _MainLightColor; \
light.atten = _MainLightAttenuationParams; \
light.spotDir = _MainLightSpotDir;
light.distanceAttenuation = _MainLightDistanceAttenuation; \
light.spotDirection = _MainLightSpotDir; \
light.spotAttenuation = _MainLightSpotAttenuation
// Indexing might have a performance hit for old mobile hardware
#define INITIALIZE_LIGHT(light, i) \

light.pos = _AdditionalLightPosition[lightIndex]; \
light.color = _AdditionalLightColor[lightIndex]; \
light.atten = _AdditionalLightAttenuationParams[lightIndex]; \
light.spotDir = _AdditionalLightSpotDir[lightIndex]
light.distanceAttenuation = _AdditionalLightDistanceAttenuation[lightIndex]; \
light.spotDirection = _AdditionalLightSpotDir[lightIndex]; \
light.spotAttenuation = _AdditionalLightSpotAttenuation[lightIndex]
CBUFFER_START(_PerObject)
half4 unity_LightIndicesOffsetAndCount;

sampler2D _MainLightCookie;
float4 _MainLightPosition;
half4 _MainLightColor;
float4 _MainLightAttenuationParams;
half4 _MainLightDistanceAttenuation;
half4 _MainLightSpotAttenuation;
float4 _AdditionalLightAttenuationParams[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightDistanceAttenuation[MAX_VISIBLE_LIGHTS];
half4 _AdditionalLightSpotAttenuation[MAX_VISIBLE_LIGHTS];
sampler2D _AttenuationTexture;
CBUFFER_END
// Must match Lightweigth ShaderGraph master node

{
float4 pos;
half4 color;
float4 atten;
half4 spotDir;
half4 distanceAttenuation;
half4 spotDirection;
half4 spotAttenuation;
};
struct BRDFData

return 1;
}
half SpotAttenuation(half3 spotDirection, half3 lightDirection, float4 attenuationParams)
// Matches Unity Vanila attenuation
half DistanceAttenuation(half3 distanceSqr, half4 distanceAttenuation)
{
// We use a shared distance attenuation for additional directional and puctual lights
// for directional lights attenuation will be 1
half quadFalloff = distanceAttenuation.x;
half denom = distanceSqr * quadFalloff + 1.0;
half lightAtten = 1.0 / denom;
// 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.y + distanceAttenuation.z);
return lightAtten * smoothFactor;
}
half SpotAttenuation(half3 spotDirection, half3 lightDirection, half4 spotAttenuation)
{
// Spot Attenuation with a linear falloff can be defined as
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle)

// SdotL * spotAttenuation.x + spotAttenuation.y
// attenuationParams.x = invAngleRange
// attenuationParams.y = (-cosOuterAngle invAngleRange)
return saturate(SdotL * attenuationParams.x + attenuationParams.y);
}
// In per-vertex falloff there's no smooth falloff to light range. A hard cut will be noticed
inline half ComputeVertexLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
{
float4 attenuationParams = lightInput.atten;
float3 posToLightVec = lightInput.pos - worldPos * lightInput.pos.w;
float distanceSqr = max(dot(posToLightVec, posToLightVec), 0.001);
// normalized light dir
lightDirection = half3(posToLightVec * rsqrt(distanceSqr));
// attenuationParams.z = kQuadFallOff = (25.0) / (lightRange * lightRange)
// attenuationParams.w = lightRange * lightRange
half lightAtten = half(1.0 / (1.0 + distanceSqr * attenuationParams.z));
lightAtten *= SpotAttenuation(lightInput.spotDir.xyz, lightDirection, attenuationParams);
return lightAtten;
return saturate(SdotL * spotAttenuation.x + spotAttenuation.y);
// In per-pixel falloff attenuation smoothly decreases to light range.
inline half ComputePixelLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
// Attenuation smoothly decreases to light range.
inline half ComputeLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
float4 attenuationParams = lightInput.atten;
float u = (distanceSqr * attenuationParams.z) / attenuationParams.w;
half lightAtten = tex2D(_AttenuationTexture, float2(u, 0.0)).a;
lightAtten *= SpotAttenuation(lightInput.spotDir.xyz, lightDirection, attenuationParams);
half lightAtten = DistanceAttenuation(distanceSqr, lightInput.distanceAttenuation);
lightAtten *= SpotAttenuation(lightInput.spotDirection.xyz, lightDirection, lightInput.spotAttenuation);
return lightAtten;
}

lightDirection = lightInput.pos;
half attenuation = 1.0;
#else
half attenuation = ComputePixelLightAttenuation(lightInput, normalWS, positionWS, lightDirection);
half attenuation = ComputeLightAttenuation(lightInput, normalWS, positionWS, lightDirection);
#endif
// Cookies and shadows are only computed for main light

INITIALIZE_LIGHT(light, lightIter);
half3 lightDirection;
half atten = ComputeVertexLightAttenuation(light, normalWS, positionWS, lightDirection);
half atten = ComputeLightAttenuation(light, normalWS, positionWS, lightDirection);
half lightColor = light.color * atten;
vertexLightColor += LightingLambert(lightColor, lightDirection, normalWS);
}

{
LightInput light;
INITIALIZE_LIGHT(light, lightIter);
half lightAtten = ComputePixelLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half lightAtten = ComputeLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = light.color * (lightAtten * NdotL);

{
LightInput lightData;
INITIALIZE_LIGHT(lightData, lightIter);
lightAtten = ComputePixelLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightAtten = ComputeLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightColor = lightData.color * lightAtten;
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);

{
LightInput lightData;
INITIALIZE_LIGHT(lightData, lightIter);
lightAtten = ComputePixelLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightAtten = ComputeLightAttenuation(lightData, normalWS, positionWS, lightDirection);
lightColor = lightData.color * lightAtten;
diffuseColor += LightingLambert(lightColor, lightDirection, normalWS);

正在加载...
取消
保存