浏览代码

Refactor directional and punctual light code

/main
Evgenii Golubev 7 年前
当前提交
8ed2bde7
共有 6 个文件被更改,包括 127 次插入109 次删除
  1. 2
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  2. 2
      ScriptableRenderPipeline/Core/Shadow/Shadow.cs
  3. 15
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs
  4. 20
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl
  5. 4
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  6. 193
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

2
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


// Z buffer to linear depth.
// Correctly handles oblique view frustums.
// Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
float LinearEyeDepth(float3 positionWS, float3x3 viewProjMatrix)
float LinearEyeDepth(float3 positionWS, float4x4 viewProjMatrix)
{
return mul(viewProjMatrix, float4(positionWS, 1.0)).w;
}

2
ScriptableRenderPipeline/Core/Shadow/Shadow.cs


}
m_TmpSortKeys.Sort( new SortReverter() );
m_TmpSortKeys.ExtractTo( shadowRequests, 0, out shadowRequestsCount, delegate(long key) { return (int) (key & UINT_MAX); } );
m_TmpSortKeys.ExtractTo( shadowRequests, 0, out shadowRequestsCount, delegate(long key) { return (int) (key & 0xffffffff); } );
}
protected override void PruneShadowCasters( Camera camera, List<VisibleLight> lights, ref VectorArray<int> shadowRequests, ref ShadowRequestVector requestsGranted, out uint totalRequestCount )

15
ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs


public Vector3 forward;
public int cookieIndex; // -1 if unused
public Vector3 right; // Rescaled by (2 / shapeLenght)
public Vector3 right; // Rescaled by (2 / shapeLength)
public bool dynamicShadowCasterOnly; // Use with ShadowMask feature
public bool dynamicShadowCasterOnly; // Use with ShadowMask feature
public Vector4 shadowMaskSelector; // Use with ShadowMask feature
};

public Vector3 forward;
public int cookieIndex; // -1 if unused
public Vector3 right; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by (2 / shapeLenght)
public Vector3 right; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by (2 / shapeLength)
public Vector3 up; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by * (2 / shapeWidth)
public Vector3 up; // If spot: rescaled by cot(outerHalfAngle); if projector: rescaled by (2 / shapeWidth)
public float diffuseScale;
public float angleScale; // Spot light

public Vector2 size; // Used by area, frustum projector and spot lights (x = cot(outerHalfAngle))
public Vector4 shadowMaskSelector; // Use with ShadowMask feature
public Vector2 size; // Used by area and pyramid projector lights
public Vector4 shadowMaskSelector; // Use with ShadowMask feature
[GenerateHLSL]

20
ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl


float specularScale;
float3 up;
float diffuseScale;
bool dynamicShadowCasterOnly;
bool dynamicShadowCasterOnly;
float4 shadowMaskSelector;
};

float angleOffset;
float shadowDimmer;
bool dynamicShadowCasterOnly;
float4 shadowMaskSelector;
float4 shadowMaskSelector;
};
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.EnvLightData

{
return value.diffuseScale;
}
bool GetDynamicShadowCasterOnly(DirectionalLightData value)
{
return value.dynamicShadowCasterOnly;
}
float2 GetFadeDistanceScaleAndBias(DirectionalLightData value)
{
return value.fadeDistanceScaleAndBias;

return value.unused0;
}
bool GetDynamicShadowCasterOnly(DirectionalLightData value)
{
return value.dynamicShadowCasterOnly;
}
float4 GetShadowMaskSelector(DirectionalLightData value)
{
return value.shadowMaskSelector;

{
return value.dynamicShadowCasterOnly;
}
float4 GetShadowMaskSelector(LightData value)
{
return value.shadowMaskSelector;
}
float2 GetSize(LightData value)
{
return value.size;

float GetMinRoughness(LightData value)
{
return value.minRoughness;
}
float4 GetShadowMaskSelector(LightData value)
{
return value.shadowMaskSelector;
}
//

4
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


for (i = 0; i < punctualLightCount; ++i)
{
int punctualIndex = FetchIndex(punctualLightStart, i);
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[punctualIndex], bsdfData, bakeLightingData, _LightDatas[punctualIndex].lightType);
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[punctualIndex], bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
}

{
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[i], bsdfData, bakeLightingData, _LightDatas[i].lightType);
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[i], bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
}

193
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData)
{
PreLightData preLightData;
ZERO_INITIALIZE(PreLightData, preLightData);
float3 N;
float NdotV;

float3 EvaluateTransmission(BSDFData bsdfData, float intensity, float shadow)
{
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;
shadow = bsdfData.useThinObjectMode ? shadow : 1.0;
float backLight = intensity * shadow;

//-----------------------------------------------------------------------------
// EvaluateBSDF_Directional (supports directional and box projector lights)
// EvaluateBSDF_Directional
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane.
// Compute the CS position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane.
float2 positionNDC = positionLS.xy;
float2 positionCS = positionLS.xy;
float2 coord = positionNDC * 0.5 + 0.5;
float2 positionNDC = positionCS * 0.5 + 0.5;
coord = frac(coord);
isInBounds = true;
positionNDC = frac(positionNDC);
isInBounds = true;
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1.0 - positionLS.z) <= 1.0;
isInBounds = Max3(abs(positionCS.x), abs(positionCS.y), 1.0 - positionLS.z) <= 1.0;
float4 cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
float4 cookie = SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex);
cookie.a = isInBounds ? cookie.a : 0.0;
cookie.a = isInBounds ? cookie.a : 0;
DirectLighting EvaluateBSDF_Directional( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData, BakeLightingData bakeLightingData)
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything.
void EvaluateLight_Directional(LightLoopContext lightLoopContext,
float3 N, float3 L, float NdotL, PositionInputs posInput,
DirectionalLightData lightData, BakeLightingData bakeLightingData,
out float3 color, out float intensity, out float shadow)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float shadowMask = 1.0;
float3 L = -lightData.forward; // Lights are pointing backward in Unity
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL);
color = lightData.color;
intensity = saturate(NdotL);
shadow = 1.0;
float shadow = 1.0;
float shadowMask = 1.0;
#ifdef SHADOWS_SHADOWMASK
// shadowMaskSelector.x is -1 if there is no shadow mask
// Note that we override shadow value (in case we don't have any dynamic shadow)

[branch] if (lightData.shadowIndex >= 0)
{
#ifdef _SURFACE_TYPE_TRANSPARENT
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, N, lightData.shadowIndex, L, posInput.unPositionSS);
#else
shadow = LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.unPositionSS).x;
#endif

#endif
}
illuminance *= shadow;
intensity *= shadow;
float3 lightToSurface = positionWS - lightData.positionWS;
float4 cookie = EvaluateCookie_Directional(lightLoopContext, lightData, lightToSurface);
float3 lightToSample = positionWS - lightData.positionWS;
float4 cookie = EvaluateCookie_Directional(lightLoopContext, lightData, lightToSample);
// Premultiply.
lightData.color *= cookie.rgb;
lightData.diffuseScale *= cookie.a;
lightData.specularScale *= cookie.a;
color *= cookie.rgb;
intensity *= cookie.a;
}
[branch] if (illuminance > 0.0)
DirectLighting EvaluateBSDF_Directional(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData,
BakeLightingData bakeLightingData)
{
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 positionWS = posInput.positionWS;
float3 N = bsdfData.normalWS;
float3 L = -lightData.forward; // Lights point backward in Unity
float NdotL = dot(bsdfData.normalWS, L);
float3 color; float intensity, shadow;
EvaluateLight_Directional(lightLoopContext, N, L, NdotL, posInput, lightData, bakeLightingData,
color, intensity, shadow);
[branch] if (intensity > 0.0)
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
lighting.diffuse *= intensity * lightData.diffuseScale;
lighting.specular *= intensity * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)

#ifdef LIT_DIFFUSE_LAMBERT_BRDF
illuminance = Lambert() * wrappedNdotL;
intensity = Lambert() * wrappedNdotL;
illuminance = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
lighting.diffuse += EvaluateTransmission(bsdfData, intensity * lightData.diffuseScale, shadow);
// Save ALU by applying 'lightData.color' only once.
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
// Save ALU by applying light and cookie colors only once.
lighting.diffuse *= color;
lighting.specular *= color;
return lighting;
}

{
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the plane at 1m distance.
// Box projector lights require no perspective division.
float perspectiveZ = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? positionLS.z : 1;
float2 positionNDC = positionLS.xy / perspectiveZ;
bool isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1;
float perspectiveZ = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? positionLS.z : 1.0;
float2 positionCS = positionLS.xy / perspectiveZ;
bool isInBounds = Max3(abs(positionCS.x), abs(positionCS.y), 1.0 - positionLS.z) <= 1.0;
float2 coord = positionNDC * 0.5 + 0.5;
float2 positionNDC = positionCS * 0.5 + 0.5;
cookie = SampleCookie2D(lightLoopContext, coord, lightData.cookieIndex);
cookie = SampleCookie2D(lightLoopContext, positionNDC, lightData.cookieIndex);
cookie.a = isInBounds ? cookie.a : 0;
}

return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
}
DirectLighting EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, BakeLightingData bakeLightingData, int GPULightType)
// 'intensity' is already premultiplied with 'shadow', 'color' is NOT premultiplied with anything.
void EvaluateLight_Punctual(LightLoopContext lightLoopContext,
float3 N, float3 L, float NdotL, float distSq, PositionInputs posInput,
LightData lightData, BakeLightingData bakeLightingData,
out float3 color, out float intensity, out float shadow)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
int lightType = GPULightType;
// All punctual light type in the same formula, attenuation is neutral depends on light type.
// light.positionWS is the normalize light direction in case of directional light and invSqrAttenuationRadius is 0
// mean dot(unL, unL) = 1 and mean GetDistanceAttenuation() will return 1
// For point light and directional GetAngleAttenuation() return 1
float3 lightToSurface = positionWS - lightData.positionWS;
float3 unL = -lightToSurface;
float distSq = dot(unL, unL);
float dist = sqrt(distSq);
float3 L = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? unL * rsqrt(distSq) : -lightData.forward;
float NdotL = dot(bsdfData.normalWS, L);
float illuminance = saturate(NdotL);
float attenuation = GetPunctualShapeAttenuation(lightData, L, distSq);
float shadowMask = 1.0;
// Premultiply.
lightData.diffuseScale *= attenuation;
lightData.specularScale *= attenuation;
color = lightData.color;
intensity = GetPunctualShapeAttenuation(lightData, L, distSq) * saturate(NdotL);
shadow = 1.0;
float shadow = 1.0;
float shadowMask = 1.0;
#ifdef SHADOWS_SHADOWMASK
// shadowMaskSelector.x is -1 if there is no shadow mask
// Note that we override shadow value (in case we don't have any dynamic shadow)

{
// TODO: make projector lights cast shadows.
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
float4 L_dist = { L, dist };
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L_dist, posInput.unPositionSS);
float4 L_dist = float4(L, sqrt(distSq));
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, N, lightData.shadowIndex, L_dist, posInput.unPositionSS);
#ifdef SHADOWS_SHADOWMASK
// Note: Legacy Unity have two shadow mask mode. ShadowMask (ShadowMask contain static objects shadow and ShadowMap contain only dynamic objects shadow, final result is the minimun of both value)
// and ShadowMask_Distance (ShadowMask contain static objects shadow and ShadowMap contain everything and is blend with ShadowMask based on distance (Global distance setup in QualitySettigns)).

#endif
}
illuminance *= shadow;
intensity *= shadow;
float4 cookie = EvaluateCookie_Punctual(lightLoopContext, lightData, lightToSurface);
float3 lightToSample = positionWS - lightData.positionWS;
float4 cookie = EvaluateCookie_Punctual(lightLoopContext, lightData, lightToSample);
// Premultiply.
lightData.color *= cookie.rgb;
lightData.diffuseScale *= cookie.a;
lightData.specularScale *= cookie.a;
color *= cookie.rgb;
intensity *= cookie.a;
}
[branch] if (illuminance > 0.0)
DirectLighting EvaluateBSDF_Punctual(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, BakeLightingData bakeLightingData)
{
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 positionWS = posInput.positionWS;
float3 lightToSample = positionWS - lightData.positionWS;
int lightType = lightData.lightType;
float3 unL = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? -lightToSample : -lightData.forward;
float distSq = dot(unL, unL);
float3 N = bsdfData.normalWS;
float3 L = unL * rsqrt(distSq);
float NdotL = dot(bsdfData.normalWS, L);
float3 color; float intensity, shadow;
EvaluateLight_Punctual(lightLoopContext, N, L, NdotL, distSq, posInput, lightData, bakeLightingData,
color, intensity, shadow);
[branch] if (intensity > 0.0)
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
lighting.diffuse *= intensity * lightData.diffuseScale;
lighting.specular *= intensity * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)

#ifdef LIT_DIFFUSE_LAMBERT_BRDF
illuminance = Lambert() * wrappedNdotL;
intensity = Lambert() * wrappedNdotL;
illuminance = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
intensity = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
lighting.diffuse += EvaluateTransmission(bsdfData, intensity * lightData.diffuseScale, shadow);
// Save ALU by applying 'lightData.color' only once.
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
// Save ALU by applying light and cookie colors only once.
lighting.diffuse *= color;
lighting.specular *= color;
return lighting;
}

正在加载...
取消
保存