浏览代码

Considered MainLight as always a directional light. This enables the following optimation: (and potentially more)

- no position WS interpolator
     - no distance attenuation computation
     - saved homogeneous coord division as w is always 1.0 in orthogonal projections
/main
Felipe Lira 6 年前
当前提交
a53eff3d
共有 9 个文件被更改,包括 199 次插入133 次删除
  1. 18
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  2. 3
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl
  3. 28
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl
  4. 108
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl
  5. 9
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl
  6. 3
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightScreenSpaceShadows.shader
  7. 2
      ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardSimpleLighting.shader
  8. 152
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLitSimple.hlsl
  9. 9
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLitSimple.hlsl.meta

18
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private int GetMainLight(List<VisibleLight> visibleLights)
{
int totalVisibleLights = visibleLights.Count;
bool shadowsEnabled = m_Asset.AreShadowsEnabled();
int brighestDirectionalIndex = -1;
for (int i = 0; i < totalVisibleLights; ++i)
{
VisibleLight currLight = visibleLights[i];

if (currLight.light == null)
break;
// Shadow lights are sorted by type (directional > puctual) and intensity
// The first shadow light we find in the list is the main light
if (shadowsEnabled && currLight.light.shadows != LightShadows.None && LightweightUtils.IsSupportedShadowType(currLight.lightType))
// In case no shadow light is present we will return the brightest directional light
if (currLight.lightType == LightType.Directional)
// In case no shadow light is present we will return the brightest directional light
if (currLight.lightType == LightType.Directional && brighestDirectionalIndex == -1)
brighestDirectionalIndex = i;
return brighestDirectionalIndex;
return -1;
}
private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,

}
}
cmd.SetGlobalVector(PerCameraBuffer._MainLightPosition, lightPos);
cmd.SetGlobalVector(PerCameraBuffer._MainLightPosition, new Vector4(lightPos.x, lightPos.y, lightPos.z, lightDistanceAttenuation.w));
cmd.SetGlobalVector(PerCameraBuffer._MainLightDistanceAttenuation, lightDistanceAttenuation);
cmd.SetGlobalVector(PerCameraBuffer._MainLightSpotDir, lightSpotDir);
cmd.SetGlobalVector(PerCameraBuffer._MainLightSpotAttenuation, lightSpotAttenuation);
}
private void SetupAdditionalListConstants(CommandBuffer cmd, List<VisibleLight> lights, ref LightData lightData)

3
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Input.hlsl


CBUFFER_START(_PerCamera)
float4 _MainLightPosition;
half4 _MainLightColor;
half4 _MainLightDistanceAttenuation;
half4 _MainLightSpotDir;
half4 _MainLightSpotAttenuation;
float4x4 _WorldToLight;
half4 _AdditionalLightCount;

28
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl


// Light Abstraction //
///////////////////////////////////////////////////////////////////////////////
Light GetMainLight(float3 positionWS)
Light GetMainLight()
LightInput lightInput;
lightInput.position = _MainLightPosition;
lightInput.color = _MainLightColor.rgb;
lightInput.distanceAttenuation = _MainLightDistanceAttenuation;
lightInput.spotDirection = _MainLightSpotDir;
lightInput.spotAttenuation = _MainLightSpotAttenuation;
half4 directionAndRealtimeAttenuation = GetMainLightDirectionAndAttenuation(lightInput, positionWS);
light.direction = directionAndRealtimeAttenuation.xyz;
light.attenuation = directionAndRealtimeAttenuation.w;
light.subtractiveModeAttenuation = lightInput.distanceAttenuation.w;
light.color = lightInput.color;
light.direction = _MainLightPosition.xyz;
light.attenuation = 1.0;
light.subtractiveModeAttenuation = _MainLightPosition.w;
light.color = _MainLightColor.rgb;
return light;
}

BRDFData brdfData;
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData);
Light mainLight = GetMainLight(inputData.positionWS);
mainLight.attenuation *= RealtimeShadowAttenuation(inputData.shadowCoord);
Light mainLight = GetMainLight();
mainLight.attenuation = RealtimeShadowAttenuation(inputData.shadowCoord, 0.0);
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
half3 color = GlobalIllumination(brdfData, inputData.bakedGI, occlusion, inputData.normalWS, inputData.viewDirectionWS);

half4 LightweightFragmentBlinnPhong(InputData inputData, half3 diffuse, half4 specularGloss, half shininess, half3 emission, half alpha)
{
Light mainLight = GetMainLight(inputData.positionWS);
mainLight.attenuation *= RealtimeShadowAttenuation(inputData.shadowCoord);
Light mainLight = GetMainLight();
mainLight.attenuation = RealtimeShadowAttenuation(inputData.shadowCoord, 0.0);
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));
half3 attenuatedLightColor = mainLight.color * mainLight.attenuation;

108
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLit.hlsl


{
float2 uv : TEXCOORD0;
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
float4 posWSShininess : TEXCOORD2; // xyz: posWS, w: Shininess * 128
#ifdef _ADDITIONAL_LIGHTS
float3 posWS : TEXCOORD2;
#endif
#ifdef _NORMALMAP
half4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x

void InitializeInputData(LightweightVertexOutput IN, half3 normalTS, out InputData inputData)
{
inputData.positionWS = IN.posWSShininess.xyz;
inputData = (InputData)0;
#ifdef _ADDITIONAL_LIGHTS
inputData.positionWS = IN.posWS;
#endif
#ifdef _NORMALMAP
half3 viewDir = half3(IN.normal.w, IN.tangent.w, IN.binormal.w);

o.uv = TransformMainTextureCoord(v.texcoord);
o.posWSShininess.xyz = TransformObjectToWorld(v.vertex.xyz);
o.clipPos = TransformWorldToHClip(o.posWSShininess.xyz);
float3 posWS = TransformObjectToWorld(v.vertex.xyz);
o.clipPos = TransformWorldToHClip(posWS);
half3 viewDir = VertexViewDirWS(GetCameraPositionWS() - o.posWSShininess.xyz);
half3 viewDir = VertexViewDirWS(GetCameraPositionWS() - posWS);
#ifdef _NORMALMAP
o.normal.w = viewDir.x;

OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUV);
OUTPUT_SH(o.normal.xyz, o.vertexSH);
half3 vertexLight = VertexLighting(o.posWSShininess.xyz, o.normal.xyz);
half3 vertexLight = VertexLighting(posWS, o.normal.xyz);
half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);

#else
o.shadowCoord = TransformWorldToShadowCoord(o.posWSShininess.xyz);
o.shadowCoord = TransformWorldToShadowCoord(posWS);
#if _ADDITIONAL_LIGHTS
o.posWS = posWS;
#endif
return o;
}

ApplyFog(color.rgb, inputData.fogCoord);
return color;
}
// Used in Standard (Simple Lighting) shader
// TODO: we only need to specialise this because of _Shininess prop
// Once we refactor SimpleLighting shader we will be able to share vertex
// between PBS and Simple
LightweightVertexOutput LitPassVertexSimple(LightweightVertexInput v)
{
LightweightVertexOutput o = (LightweightVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.uv = TransformMainTextureCoord(v.texcoord);
o.posWSShininess.xyz = TransformObjectToWorld(v.vertex.xyz);
o.posWSShininess.w = _Shininess * 128.0;
o.clipPos = TransformWorldToHClip(o.posWSShininess.xyz);
half3 viewDir = VertexViewDirWS(GetCameraPositionWS() - o.posWSShininess.xyz);
#ifdef _NORMALMAP
o.normal.w = viewDir.x;
o.tangent.w = viewDir.y;
o.binormal.w = viewDir.z;
#else
o.viewDir = viewDir;
#endif
// initializes o.normal and if _NORMALMAP also o.tangent and o.binormal
OUTPUT_NORMAL(v, o);
// We either sample GI from lightmap or SH.
// Lightmap UV and vertex SH coefficients use the same interpolator ("float2 lightmapUV" for lightmap or "half3 vertexSH" for SH)
// see DECLARE_LIGHTMAP_OR_SH macro.
// The following funcions initialize the correct variable with correct data
OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUV);
OUTPUT_SH(o.normal.xyz, o.vertexSH);
half3 vertexLight = VertexLighting(o.posWSShininess.xyz, o.normal.xyz);
half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(o.clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(o.posWSShininess.xyz);
#endif
#endif
return o;
}
// Used for StandardSimpleLighting shader
half4 LitPassFragmentSimple(LightweightVertexOutput IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
float2 uv = IN.uv;
half4 diffuseAlpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
half3 diffuse = diffuseAlpha.rgb * _Color.rgb;
half alpha = diffuseAlpha.a * _Color.a;
AlphaDiscard(alpha, _Cutoff);
#ifdef _ALPHAPREMULTIPLY_ON
diffuse *= alpha;
#endif
#ifdef _NORMALMAP
half3 normalTS = Normal(uv);
#else
half3 normalTS = half3(0, 0, 1);
#endif
half3 emission = Emission(uv);
half4 specularGloss = SpecularGloss(uv, diffuseAlpha.a);
half shininess = IN.posWSShininess.w;
InputData inputData;
InitializeInputData(IN, normalTS, inputData);
return LightweightFragmentBlinnPhong(inputData, diffuse, specularGloss, shininess, emission, alpha);
};
#endif

9
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl


return attenuation;
}
inline real SampleShadowmap(float4 shadowCoord)
inline real SampleShadowmap(float4 shadowCoord, float isPerspectiveProjection = 1.0)
shadowCoord.xyz /= shadowCoord.w;
if (isPerspectiveProjection == 0.0)
shadowCoord.xyz /= shadowCoord.w;
real attenuation;

return ComputeScreenPos(clipPos);
}
half RealtimeShadowAttenuation(float4 shadowCoord)
half RealtimeShadowAttenuation(float4 shadowCoord, float isPerspectiveProjection = 1.0)
{
#ifndef _SHADOWS_ENABLED
return 1.0h;

return SampleScreenSpaceShadowMap(shadowCoord);
#else
return SampleShadowmap(shadowCoord);
return SampleShadowmap(shadowCoord, isPerspectiveProjection);
#endif
}

3
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightScreenSpaceShadows.shader


//Fetch shadow coordinates for cascade.
float4 coords = TransformWorldToShadowCoord(wpos);
return SampleShadowmap(coords);
// Screenspace shadowmap is only used for directional lights which use orthogonal projection.
return SampleShadowmap(coords, 0.0);
}
ENDHLSL

2
ScriptableRenderPipeline/LightweightPipeline/LWRP/Shaders/LightweightStandardSimpleLighting.shader


#pragma vertex LitPassVertexSimple
#pragma fragment LitPassFragmentSimple
#define BUMP_SCALE_NOT_SUPPORTED 1
#include "LWRP/ShaderLibrary/LightweightPassLit.hlsl"
#include "LWRP/ShaderLibrary/LightweightPassLitSimple.hlsl"
ENDHLSL
}

152
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLitSimple.hlsl


#ifndef LIGHTWEIGHT_PASS_LIT_INCLUDED
#define LIGHTWEIGHT_PASS_LIT_INCLUDED
#include "LWRP/ShaderLibrary/InputSurface.hlsl"
#include "LWRP/ShaderLibrary/Lighting.hlsl"
struct LightweightVertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float2 texcoord : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct LightweightVertexOutput
{
float2 uv : TEXCOORD0;
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
float4 posWSShininess : TEXCOORD2; // xyz: posWS, w: Shininess * 128
#ifdef _NORMALMAP
half4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x
half4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y
half4 binormal : TEXCOORD5; // xyz: binormal, w: viewDir.z
#else
half3 normal : TEXCOORD3;
half3 viewDir : TEXCOORD4;
#endif
half4 fogFactorAndVertexLight : TEXCOORD6; // x: fogFactor, yzw: vertex light
#ifdef _SHADOWS_ENABLED
float4 shadowCoord : TEXCOORD7;
#endif
float4 clipPos : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
void InitializeInputData(LightweightVertexOutput IN, half3 normalTS, out InputData inputData)
{
inputData.positionWS = IN.posWSShininess.xyz;
#ifdef _NORMALMAP
half3 viewDir = half3(IN.normal.w, IN.tangent.w, IN.binormal.w);
inputData.normalWS = TangentToWorldNormal(normalTS, IN.tangent.xyz, IN.binormal.xyz, IN.normal.xyz);
#else
half3 viewDir = IN.viewDir;
inputData.normalWS = FragmentNormalWS(IN.normal);
#endif
inputData.viewDirectionWS = FragmentViewDirWS(viewDir);
#ifdef _SHADOWS_ENABLED
inputData.shadowCoord = IN.shadowCoord;
#else
inputData.shadowCoord = float4(0, 0, 0, 0);
#endif
inputData.fogCoord = IN.fogFactorAndVertexLight.x;
inputData.vertexLighting = IN.fogFactorAndVertexLight.yzw;
inputData.bakedGI = SAMPLE_GI(IN.lightmapUV, IN.vertexSH, inputData.normalWS);
}
///////////////////////////////////////////////////////////////////////////////
// Vertex and Fragment functions //
///////////////////////////////////////////////////////////////////////////////
// Used in Standard (Simple Lighting) shader
LightweightVertexOutput LitPassVertexSimple(LightweightVertexInput v)
{
LightweightVertexOutput o = (LightweightVertexOutput)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_TRANSFER_INSTANCE_ID(v, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.uv = TransformMainTextureCoord(v.texcoord);
o.posWSShininess.xyz = TransformObjectToWorld(v.vertex.xyz);
o.posWSShininess.w = _Shininess * 128.0;
o.clipPos = TransformWorldToHClip(o.posWSShininess.xyz);
half3 viewDir = VertexViewDirWS(GetCameraPositionWS() - o.posWSShininess.xyz);
#ifdef _NORMALMAP
o.normal.w = viewDir.x;
o.tangent.w = viewDir.y;
o.binormal.w = viewDir.z;
#else
o.viewDir = viewDir;
#endif
// initializes o.normal and if _NORMALMAP also o.tangent and o.binormal
OUTPUT_NORMAL(v, o);
// We either sample GI from lightmap or SH.
// Lightmap UV and vertex SH coefficients use the same interpolator ("float2 lightmapUV" for lightmap or "half3 vertexSH" for SH)
// see DECLARE_LIGHTMAP_OR_SH macro.
// The following funcions initialize the correct variable with correct data
OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUV);
OUTPUT_SH(o.normal.xyz, o.vertexSH);
half3 vertexLight = VertexLighting(o.posWSShininess.xyz, o.normal.xyz);
half fogFactor = ComputeFogFactor(o.clipPos.z);
o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
#ifdef _SHADOWS_ENABLED
#if SHADOWS_SCREEN
o.shadowCoord = ComputeShadowCoord(o.clipPos);
#else
o.shadowCoord = TransformWorldToShadowCoord(o.posWSShininess.xyz);
#endif
#endif
return o;
}
// Used for StandardSimpleLighting shader
half4 LitPassFragmentSimple(LightweightVertexOutput IN) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(IN);
float2 uv = IN.uv;
half4 diffuseAlpha = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv);
half3 diffuse = diffuseAlpha.rgb * _Color.rgb;
half alpha = diffuseAlpha.a * _Color.a;
AlphaDiscard(alpha, _Cutoff);
#ifdef _ALPHAPREMULTIPLY_ON
diffuse *= alpha;
#endif
#ifdef _NORMALMAP
half3 normalTS = Normal(uv);
#else
half3 normalTS = half3(0, 0, 1);
#endif
half3 emission = Emission(uv);
half4 specularGloss = SpecularGloss(uv, diffuseAlpha.a);
half shininess = IN.posWSShininess.w;
InputData inputData;
InitializeInputData(IN, normalTS, inputData);
return LightweightFragmentBlinnPhong(inputData, diffuse, specularGloss, shininess, emission, alpha);
};
#endif

9
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/LightweightPassLitSimple.hlsl.meta


fileFormatVersion: 2
guid: ee447e65526c7db45a978c16b28827a9
timeCreated: 1488965025
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存