浏览代码

Enabled back support to vertex lighting

/Add-support-for-light-specular-color-tint
Felipe Lira 7 年前
当前提交
a01c178c
共有 8 个文件被更改,包括 94 次插入109 次删除
  1. 18
      ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs
  2. 72
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
  3. 4
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
  4. 6
      ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs
  5. 58
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc
  6. 39
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc
  7. 3
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader
  8. 3
      ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader

18
ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs


public static GUIContent renderScaleLabel = new GUIContent("Render Scale", "Allows game to render at a resolution different than native resolution. UI is always rendered at native resolution.");
public static GUIContent maxPixelLights = new GUIContent("Per-Object Pixel Lights",
"Max amount of pixel lights.");
public static GUIContent maxAdditionalPixelLightsLabel = new GUIContent("Max Additional Pixel Lights",
"Controls the additional per-pixel lights that run in fragment light loop.");
"Lightweight pipeline support at most 4 vertex lights.");
"If enabled, shades additional lights exceeding maxAdditionalPixelLights per-vertex up to the maximum of 8 lights.");
public static GUIContent enableSoftParticles = new GUIContent("Enable Soft Particles", "By enabled this the pipeline will generate depth texture necessary for SoftParticles");

"Material to use when creating 3D objects");
public static GUIContent defaultParticleMaterial = new GUIContent("Default Particle Material",
"Material to use when creating Paticle Systems");
"Material to use when creating Particle Systems");
public static GUIContent defaultLineMaterial = new GUIContent("Default Line Material",
"Material to use when creating Line Renderers");

public static GUIContent attenuationTextureLabel = new GUIContent("Attenuation Texture", "Light attenuation falloff texture");
}
private int kMaxSupportedPixelLights = 9;
private int kMaxSupportedAdditionalPixelLights = 8;
private SerializedProperty m_MaxPixelLights;
private SerializedProperty m_MaxAdditionalPixelLights;
private SerializedProperty m_SupportsVertexLightProp;
private SerializedProperty m_SupportSoftParticlesProp;
private SerializedProperty m_ShadowTypeProp;

{
m_LinearRenderingProperty = serializedObject.FindProperty("m_LinearRendering");
m_RenderScale = serializedObject.FindProperty("m_RenderScale");
m_MaxPixelLights = serializedObject.FindProperty("m_MaxPixelLights");
m_MaxAdditionalPixelLights = serializedObject.FindProperty("m_MaxAdditionalPixelLights");
m_SupportsVertexLightProp = serializedObject.FindProperty("m_SupportsVertexLight");
m_SupportSoftParticlesProp = serializedObject.FindProperty("m_SupportSoftParticles");
m_ShadowTypeProp = serializedObject.FindProperty("m_ShadowType");

m_RenderScale.floatValue = EditorGUILayout.Slider(m_RenderScale.floatValue, 0.1f, 1.0f);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(Styles.maxPixelLights);
m_MaxPixelLights.intValue = EditorGUILayout.IntSlider(m_MaxPixelLights.intValue, 0, kMaxSupportedPixelLights);
EditorGUILayout.LabelField(Styles.maxAdditionalPixelLightsLabel);
m_MaxAdditionalPixelLights.intValue = EditorGUILayout.IntSlider(m_MaxAdditionalPixelLights.intValue, 0, kMaxSupportedAdditionalPixelLights);
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(m_SupportsVertexLightProp, Styles.enableVertexLightLabel);
EditorGUILayout.PropertyField(m_SupportSoftParticlesProp, Styles.enableSoftParticles);

72
ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs


public struct LightData
{
public int additionalPixelLightsCount;
public int vertexLightsCount;
public int pixelAdditionalLightsCount;
public int totalAdditionalLightsCount;
public bool hasAdditionalLights;
public bool shadowsRendered;
}

// Max amount of visible lights. This controls the lights constant buffers in shader but not the max shaded lights.
// Lights are set per-object and the max shaded lights for each object are controlled by the max pixel lights in pipeline asset and kMaxVertexLights.
// Maximum amount of visible lights the shader can process. This controls the constant global light buffer size.
// It must match the MAX_VISIBLE_LIGHTS in LightweightCore.cginc
private static readonly int kMaxPerObjectLights = 8;
// Lights are culled per-object. This holds the maximum amount of additional lights that can shade each object.
// The engine fills in the lights indices per-object in unity4_LightIndices0 and unity_4LightIndices1
private static readonly int kMaxPerObjectAdditionalLights = 8;
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleAdditionalLights];
private Vector4[] m_LightColors = new Vector4[kMaxVisibleAdditionalLights];

private Camera m_CurrCamera = null;
private ComputeBuffer m_LightIndexListBuffer;
private static readonly int kMaxCascades = 4;
private int m_ShadowCasterCascadesCount = kMaxCascades;

public override void Dispose()
{
base.Dispose();
if (m_LightIndexListBuffer != null)
{
m_LightIndexListBuffer.Dispose();
m_LightIndexListBuffer = null;
}
}
CullResults m_CullResults;

// There's no way to map shadow light indices. We need to pass in the original unsorted index.
// If no additional lights then no light sorting is performed and the indices match.
int shadowOriginalIndex = (lightData.hasAdditionalLights) ? GetLightUnsortedIndex(lightData.mainLightIndex) : lightData.mainLightIndex;
int shadowOriginalIndex = (lightData.totalAdditionalLightsCount > 0) ? GetLightUnsortedIndex(lightData.mainLightIndex) : lightData.mainLightIndex;
lightData.shadowsRendered = RenderShadows(ref m_CullResults, ref mainLight,
shadowOriginalIndex, ref context);
}

int visibleLightsCount = visibleLights.Length;
m_SortedLightIndexMap.Clear();
// kMaxPerObjectLights + 1 main light
int maxSupportedPixelLights = Math.Min(m_Asset.MaxSupportedPixelLights, kMaxPerObjectLights + 1);
int maxPixelLights = Math.Min(maxSupportedPixelLights, visibleLightsCount);
if (maxPixelLights <= 1)
{
lightData.mainLightIndex = maxPixelLights - 1;
lightData.additionalPixelLightsCount = 0;
}
else
lightData.shadowsRendered = false;
if (visibleLightsCount <= 1)
lightData.mainLightIndex = SortLights(visibleLights);
lightData.additionalPixelLightsCount = maxPixelLights - 1;
// If there's exactly one visible light that will be picked as main light.
// Otherwise we disable main light by setting its index to -1.
lightData.mainLightIndex = visibleLightsCount - 1;
lightData.pixelAdditionalLightsCount = 0;
lightData.totalAdditionalLightsCount = 0;
return;
lightData.vertexLightsCount = (m_Asset.SupportsVertexLight) ? Math.Min(4, Math.Min(visibleLightsCount - maxPixelLights, kMaxPerObjectLights)) : 0;
lightData.hasAdditionalLights = (lightData.additionalPixelLightsCount + lightData.vertexLightsCount) > 0;
lightData.shadowsRendered = false;
// We always support at least one per-pixel light, which is main light. Shade objects up to a limit of per-object
// pixel lights defined in the pipeline settings.
int maxSupportedPixelLights = Math.Min(m_Asset.MaxAdditionalPixelLights, kMaxPerObjectAdditionalLights) + 1;
int maxPixelLights = Math.Min(maxSupportedPixelLights, visibleLightsCount);
// If vertex lighting is enabled in the pipeline settings, then we shade the remaining visible lights per-vertex
// up to the maximum amount of per-object lights.
int vertexLights = (m_Asset.SupportsVertexLight) ? kMaxPerObjectAdditionalLights - maxPixelLights - 1: 0;
lightData.mainLightIndex = SortLights(visibleLights);
lightData.pixelAdditionalLightsCount = maxPixelLights - 1;
lightData.totalAdditionalLightsCount = lightData.pixelAdditionalLightsCount + vertexLights;
}
private int SortLights(VisibleLight[] visibleLights)

SetupShadowShaderConstants (cmd, ref context, ref lights[lightData.mainLightIndex], m_ShadowCasterCascadesCount);
}
if (lightData.hasAdditionalLights)
if (lightData.totalAdditionalLightsCount > 0)
SetupAdditionalListConstants(cmd, lights, ref lightData, ref context);
}

}
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4 (lightData.additionalPixelLightsCount, lightData.vertexLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, new Vector4 (lightData.pixelAdditionalLightsCount,
lightData.totalAdditionalLightsCount, 0.0f, 0.0f));
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightPosition, m_LightPositions);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightColor, m_LightColors);
cmd.SetGlobalVectorArray (PerCameraBuffer._AdditionalLightAttenuationParams, m_LightAttenuations);

private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, VisibleLight[] visibleLights)
{
int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;
LightweightUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", lightData.vertexLightsCount > 0);
LightweightUtils.SetKeyword(cmd, "_ATTENUATION_TEXTURE", m_Asset.AttenuationTexture != null);
LightweightUtils.SetKeyword(cmd, "_VERTEX_LIGHTS", vertexLightsCount > 0);
LightweightUtils.SetKeyword(cmd, "_ADDITIONAL_PIXEL_LIGHTS", lightData.additionalPixelLightsCount > 0);
LightweightUtils.SetKeyword(cmd, "_ADDITIONAL_LIGHTS", lightData.totalAdditionalLightsCount > 0);
string[] shadowKeywords = new string[] { "_HARD_SHADOWS", "_SOFT_SHADOWS", "_HARD_SHADOWS_CASCADES", "_SOFT_SHADOWS_CASCADES" };
for (int i = 0; i < shadowKeywords.Length; ++i)

RendererConfiguration GetRendererSettings(ref LightData lightData)
{
RendererConfiguration settings = RendererConfiguration.PerObjectReflectionProbes | RendererConfiguration.PerObjectLightmaps | RendererConfiguration.PerObjectLightProbe;
if (lightData.hasAdditionalLights)
if (lightData.totalAdditionalLightsCount > 0)
settings |= RendererConfiguration.PerObjectLightIndices8;
return settings;
}

4
ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset


m_Script: {fileID: 11500000, guid: bf2edee5c58d82540a51f03df9d42094, type: 3}
m_Name: LightweightPipelineAsset
m_EditorClassIdentifier:
m_MaxPixelLights: 5
m_SupportsVertexLight: 1
m_MaxAdditionalPixelLights: 4
m_SupportsVertexLight: 0
m_SupportSoftParticles: 1
m_MSAA: 4
m_RenderScale: 1

6
ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs


private static readonly string m_PipelineFolder = "Assets/ScriptableRenderPipeline/LightweightPipeline";
private static readonly string m_AssetName = "LightweightPipelineAsset.asset";
[SerializeField] private int m_MaxPixelLights = 1;
[SerializeField] private int m_MaxAdditionalPixelLights = 1;
[SerializeField] private bool m_SupportsVertexLight = true;
[SerializeField] private bool m_SupportSoftParticles = false;
[SerializeField] private MSAAQuality m_MSAA = MSAAQuality.Disabled;

return ShadowSetting != ShadowType.NO_SHADOW;
}
public int MaxSupportedPixelLights
public int MaxAdditionalPixelLights
get { return m_MaxPixelLights; }
get { return m_MaxAdditionalPixelLights; }
}
public bool SupportsVertexLight

58
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc


return o;
}
inline half ComputeLightAttenuationVertex(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
half SpotAttenuation(half3 spotDirection, half3 lightDirection, float4 attenuationParams)
{
// attenuationParams.x = cos(spotAngle * 0.5)
// attenuationParams.y = cos(innerSpotAngle * 0.5)
half SdotL = saturate(dot(spotDirection, lightDirection));
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)
float3 posToLightVec = lightInput.pos - worldPos;
float3 posToLightVec = lightInput.pos - worldPos * lightInput.pos.w;
//// attenuationParams.z = kQuadFallOff = (25.0) / (lightRange * lightRange)
//// attenuationParams.w = lightRange * lightRange
//// TODO: we can precompute 1.0 / (attenuationParams.w * 0.64 - attenuationParams.w)
//// falloff is computed from 80% light range squared
float lightAtten = half(1.0 / (1.0 + distanceSqr * attenuationParams.z));
half SdotL = saturate(dot(lightInput.spotDir.xyz, lightDirection));
lightAtten *= saturate((SdotL - attenuationParams.x) / attenuationParams.y);
return half(lightAtten);
// 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;
inline half ComputeLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
// In per-pixel falloff attenuation smoothly decreases to light range.
inline half ComputePixelLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)
#ifdef _ATTENUATION_TEXTURE
float u = (distanceSqr * attenuationParams.z) / attenuationParams.w;
float lightAtten = tex2D(_AttenuationTexture, float2(u, 0.0)).a;
#else
//// attenuationParams.z = kQuadFallOff = (25.0) / (lightRange * lightRange)
//// attenuationParams.w = lightRange * lightRange
//// TODO: we can precompute 1.0 / (attenuationParams.w * 0.64 - attenuationParams.w)
//// falloff is computed from 80% light range squared
float lightAtten = half(1.0 / (1.0 + distanceSqr * attenuationParams.z));
float falloff = saturate((distanceSqr - attenuationParams.w) / (attenuationParams.w * 0.64 - attenuationParams.w));
lightAtten *= half(falloff);
#endif
half SdotL = saturate(dot(lightInput.spotDir.xyz, lightDirection));
lightAtten *= saturate((SdotL - attenuationParams.x) / attenuationParams.y);
return half(lightAtten);
float u = (distanceSqr * attenuationParams.z) / attenuationParams.w;
half lightAtten = tex2D(_AttenuationTexture, float2(u, 0.0)).a;
lightAtten *= SpotAttenuation(lightInput.spotDir.xyz, lightDirection, attenuationParams);
return lightAtten;
}
inline half ComputeMainLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection)

lightDirection = lightInput.pos;
return 1.0;
#else
return ComputeLightAttenuation(lightInput, normal, worldPos, lightDirection);
return ComputePixelLightAttenuation(lightInput, normal, worldPos, lightDirection);
#endif
}

color += LightweightBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance;
#endif
#ifdef _ADDITIONAL_PIXEL_LIGHTS
#ifdef _ADDITIONAL_LIGHTS
half lightAtten = ComputeLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half lightAtten = ComputePixelLightAttenuation(light, normalWS, positionWS, lightDirectionWS);
half NdotL = saturate(dot(normalWS, lightDirectionWS));
half3 radiance = light.color * (lightAtten * NdotL);

39
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc


#endif
o.fogFactorAndVertexLight.yzw = half3(0.0h, 0.0h, 0.0h);
// TODO: change to only support point lights per vertex. This will greatly simplify shader ALU
//#if defined(_VERTEX_LIGHTS) && defined(_MULTIPLE_LIGHTS)
// half3 diffuse = half3(1.0, 1.0, 1.0);
// // pixel lights shaded = min(pixelLights, perObjectLights)
// // vertex lights shaded = min(vertexLights, perObjectLights) - pixel lights shaded
// // Therefore vertexStartIndex = pixelLightCount; vertexEndIndex = min(vertexLights, perObjectLights)
// int vertexLightStart = min(globalLightCount.x, unity_LightIndicesOffsetAndCount.y);
// int vertexLightEnd = min(globalLightCount.y, unity_LightIndicesOffsetAndCount.y);
// for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter)
// {
// int lightIndex = unity_4LightIndices0[lightIter];
// LightInput lightInput;
// INITIALIZE_LIGHT(lightInput, lightIndex);
//
// half3 lightDirection;
// half atten = ComputeLightAttenuationVertex(lightInput, normal, worldPos, lightDirection);
// o.ambient.yzw += LightingLambert(diffuse, lightDirection, normal, atten);
// }
//#endif
#if defined(_VERTEX_LIGHTS)
half3 diffuse = half3(1.0, 1.0, 1.0);
int vertexLightStart = _AdditionalLightCount.x;
int vertexLightEnd = min(_AdditionalLightCount.y, unity_LightIndicesOffsetAndCount.y);
for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter)
{
LightInput lightData;
INITIALIZE_LIGHT(lightData, lightIter);
half3 lightDirection;
half atten = ComputeVertexLightAttenuation(lightData, normal, worldPos, lightDirection);
o.fogFactorAndVertexLight.yzw += LightingLambert(diffuse, lightDirection, normal, atten) * lightData.color;
}
#endif
float4 clipPos = UnityObjectToClipPos(v.vertex);
o.fogFactorAndVertexLight.x = ComputeFogFactor(clipPos.z);

#endif
#ifdef _ADDITIONAL_PIXEL_LIGHTS
#ifdef _ADDITIONAL_LIGHTS
half lightAtten = ComputeLightAttenuation(lightData, normalWorld, worldPos, lightDirection);
half lightAtten = ComputePixelLightAttenuation(lightData, normalWorld, worldPos, lightDirection);
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
color += LightingBlinnPhong(diffuse, specularGloss, lightDirection, normalWorld, viewDir, lightAtten) * lightData.color;

}
#endif // _ADDITIONAL_PIXEL_LIGHTS
#endif // _ADDITIONAL_LIGHTS
color += EmissionLW(uv);
color += IN.fogFactorAndVertexLight.yzw;

3
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader


#pragma shader_feature _OCCLUSIONMAP
#pragma multi_compile _ _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT
#pragma multi_compile _ _ADDITIONAL_PIXEL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ATTENUATION_TEXTURE
#pragma multi_compile_fog
#pragma multi_compile_instancing

3
ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader


#pragma shader_feature _EMISSION
#pragma multi_compile _ _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT
#pragma multi_compile _ _ADDITIONAL_PIXEL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ATTENUATION_TEXTURE
#pragma multi_compile_fog
#pragma multi_compile_instancing

正在加载...
取消
保存