浏览代码

Refactor tranmission and lightEvaluation code to have more cleaner code

/main
sebastienlagarde 7 年前
当前提交
aa5363e0
共有 6 个文件被更改,包括 63 次插入69 次删除
  1. 45
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightEvaluation.hlsl
  2. 3
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.hlsl
  3. 17
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoopDef.hlsl
  4. 14
      com.unity.render-pipelines.high-definition/HDRP/Lighting/Volumetrics/VolumetricLighting.compute
  5. 46
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl
  6. 7
      com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoopDef.hlsl.orig.meta

45
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightEvaluation.hlsl


}
// None of the outputs are premultiplied.
// Note: When doing transmission we always have only one shadow sample to do: Either front or back. We use NdotL to know on which side we are
float3 N, float3 L,
out float3 color, out float attenuation, out float attenuationNoContactShadows)
float3 N, float3 L, bool isThinModeTransmission,
out float3 color, out float attenuation)
float4 shadowData = float4(1, 1, 1, 1);
float contactShadow = 1.0;
color = lightData.color;
attenuation = 1.0; // Note: no volumetric attenuation along shadow rays for directional lights

shadow = shadowMask = (lightData.shadowMaskSelector.x >= 0.0) ? dot(bakeLightingData.bakeShadowMask, lightData.shadowMaskSelector) : 1.0;
#endif
UNITY_BRANCH if (lightData.shadowIndex >= 0)
float NdotL = dot(N, L);
// We test NdotL > 0.0 to not sample the shadow map if it is not required.
// In case of thin mode we always need to perform the fetch as we reuse it for back and front lighting
UNITY_BRANCH if (lightData.shadowIndex >= 0 && (isThinModeTransmission || NdotL >= 0.0))
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, N, lightData.shadowIndex, L, posInput.positionSS);
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, NdotL > 0.0 ? N : -N, lightData.shadowIndex, L, posInput.positionSS);
#endif
#ifdef SHADOWS_SHADOWMASK

// Note: There is no shadowDimmer when there is no shadow mask
#endif
// Volumetric don't use screenspace shadow. Transparent neither (as we don't have the depth information)
contactShadow = GetContactShadow(lightLoopContext, lightData.contactShadowIndex);
// Don't apply shadow contact on transmismission
shadow = isThinModeTransmission ? shadow : min(shadow, GetContactShadow(lightLoopContext, lightData.contactShadowIndex));
attenuationNoContactShadows = shadow * attenuation;
attenuation *= min(shadow, contactShadow);
attenuation *= shadow;
}
//-----------------------------------------------------------------------------

// None of the outputs are premultiplied.
// distances = {d, d^2, 1/d, d_proj}, where d_proj = dot(lightToSample, lightData.forward).
// Note: When doing transmission we always have only one shadow sample to do: Either front or back. We use NdotL to know on which side we are
float3 N, float3 L, float3 lightToSample, float4 distances,
out float3 color, out float attenuation, out float attenuationNoContactShadows)
float3 N, float3 L, float3 lightToSample, float4 distances, bool isThinModeTransmission,
out float3 color, out float attenuation)
float contactShadow = 1.0;
color = lightData.color;
attenuation = SmoothPunctualLightAttenuation(distances, lightData.invSqrAttenuationRadius,

shadow = shadowMask = (lightData.shadowMaskSelector.x >= 0.0) ? dot(bakeLightingData.bakeShadowMask, lightData.shadowMaskSelector) : 1.0;
#endif
UNITY_BRANCH if (lightData.shadowIndex >= 0)
float NdotL = dot(N, L);
// We test NdotL > 0.0 to not sample the shadow map if it is not required.
// In case of thin mode we always need to perform the fetch as we reuse it for back and front lighting
UNITY_BRANCH if (lightData.shadowIndex >= 0 && (isThinModeTransmission || NdotL >= 0.0))
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS, N, lightData.shadowIndex, L, distances.x, posInput.positionSS);
// Note:the case of NdotL < 0 can appear with isThinModeTransmission, in this case we need to flip the shadow bias
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS, NdotL > 0.0 ? N : -N, lightData.shadowIndex, L, distances.x, posInput.positionSS);
#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)

shadow = lerp(1.0, shadow, lightData.shadowDimmer);
#endif
// Volumetric don't use screenspace shadow. Transparent neither (as we don't have the depth information)
contactShadow = GetContactShadow(lightLoopContext, lightData.contactShadowIndex);
// Don't apply shadow contact on transmismission
shadow = isThinModeTransmission ? shadow : min(shadow, GetContactShadow(lightLoopContext, lightData.contactShadowIndex));
attenuationNoContactShadows = shadow * attenuation;
attenuation *= min(shadow, contactShadow);
attenuation *= shadow;
}
// Environment map share function

3
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoop.hlsl


LightLoopContext context;
context.sampleReflection = 0;
context.shadowContext = InitShadowContext();
//We always fetch the screen space shadow texture, it is a 1x1 white texture if deferred directional shadow and/or contact shadow are disabled
context.contactShadow = LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.positionSS).y; // Contactshadow is store in Green Channel of _DeferredShadowTexture
context.contactShadow = InitContactShadow(posInput);
// This struct is define in the material. the Lightloop must not access it
// PostEvaluateBSDF call at the end will convert Lighting to diffuse and specular lighting

17
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoopDef.hlsl


return _EnvLightDatas[j];
}
// We always fetch the screen space shadow texture to reduce the number of shader variant, overhead is negligible,
// it is a 1x1 white texture if deferred directional shadow and/or contact shadow are disabled
// We perform a single featch a the beginning of the lightloop
float InitContactShadow(PositionInputs posInput)
{
// For now we only support one contact shadow
// Contactshadow is store in Green Channel of _DeferredShadowTexture
return LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.positionSS).y;
}
// Here we take the contact shadow value using the contactShadowIndex of the light
// If the contact shadows are diasbled, it's value is -1 so this function will only
// return 1
// On the other hand, if the feature is active it's value is 0 so we can return
// the value fetched at the begining of LightLoop()
return max(lightLoopContext.contactShadow, abs(contactShadowIndex));
return contactShadowIndex >= 0 ? lightLoopContext.contactShadow : 1.0;
}

14
com.unity.render-pipelines.high-definition/HDRP/Lighting/Volumetrics/VolumetricLighting.compute


float3 L = -light.forward; // Lights point backwards in Unity
float3 color; float attenuation; float attenuationNoContactShadows;
EvaluateLight_Directional(context, posInput, light, unused, 0, L,
color, attenuation, attenuationNoContactShadows);
EvaluateLight_Directional(context, posInput, light, unused, 0, L, false,
color, attenuation);
// Important:
// Ideally, all scattering calculations should use the jittered versions

float3 color; float attenuation; float attenuationNoContactShadows;
EvaluateLight_Punctual(context, posInput, light, unused,
0, L, lightToSample, distances, color,
attenuation, attenuationNoContactShadows);
0, L, lightToSample, distances, false,
color, attenuation);
// Important:
// Ideally, all scattering calculations should use the jittered versions

float4 distances = float4(1, 1, 1, distProj);
float3 color; float attenuation; float attenuationNoContactShadows;
EvaluateLight_Punctual(context, posInput, light, unused,
0, L, lightToSample, distances, color,
attenuation, attenuationNoContactShadows);
EvaluateLight_Punctual( context, posInput, light, unused,
0, L, lightToSample, distances, false,
color, attenuation);
// Important:
// Ideally, all scattering calculations should use the jittered versions

46
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl


#define MATERIAL_FEATURE_FLAGS_SSS_OUTPUT_SPLIT_LIGHTING ((MATERIAL_FEATURE_MASK_FLAGS + 1) << 0)
#define MATERIAL_FEATURE_FLAGS_SSS_TEXTURING_MODE_OFFSET FastLog2((MATERIAL_FEATURE_MASK_FLAGS + 1) << 1) // 2 bits
#define MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS ((MATERIAL_FEATURE_MASK_FLAGS + 1) << 3)
// Flags used as a shortcut to know if we have thin mode transmission
#define MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS ((MATERIAL_FEATURE_MASK_FLAGS + 1) << 4)
//
// Vertically Layered BSDF : "vlayering"

// the current object. That's not a problem, since large thickness will result in low intensity.
bool useThinObjectMode = IsBitSet(asuint(_TransmissionFlags), diffusionProfile);
bsdfData.materialFeatures |= useThinObjectMode ? 0 : MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS;
bsdfData.materialFeatures |= useThinObjectMode ? MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS : MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS;
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
_HalfRcpVariancesAndWeights[diffusionProfile][0].a,
_HalfRcpVariancesAndWeights[diffusionProfile][1].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][1].a,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
_HalfRcpVariancesAndWeights[diffusionProfile][0].a,
_HalfRcpVariancesAndWeights[diffusionProfile][1].rgb,
_HalfRcpVariancesAndWeights[diffusionProfile][1].a,
_TransmissionTintsAndFresnel0[diffusionProfile].rgb,
bsdfData.thickness);
#endif
}

float attenuationNoContactShadows;
// For shadow attenuation (ie receiver bias), always use the geometric normal:
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L, color, attenuation, attenuationNoContactShadows);
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L, HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS), color, attenuation);
float intensity = max(0, attenuation); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)

}
// The mixed thickness mode is not supported by directional lights due to poor quality and high performance impact.
bool mixedThicknessMode = HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS);
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_TRANSMISSION) && !mixedThicknessMode)
if (HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS))
{
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
lighting.diffuse += EvaluateTransmission(bsdfData, bsdfData.transmittance, NdotL, NdotV, LdotV, attenuationNoContactShadows * lightData.diffuseScale);

float NdotL = dot(N, L);
float LdotV = dot(L, V);
bool mixedThicknessMode = HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS)
&& NdotL < 0 && lightData.shadowIndex >= 0;
// Save the original version for the transmission code below.
int originalShadowIndex = lightData.shadowIndex;
if (mixedThicknessMode)
{
// Make sure we do not sample the shadow map twice.
lightData.shadowIndex = -1;
//No need to restore as we dont use it later
lightData.contactShadowIndex = -1;
}
float3 color;
float attenuation;
float attenuationNoContactShadows;

lightToSample, distances, color, attenuation, attenuationNoContactShadows);
lightToSample, distances, HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_THIN_THICKNESS),
color, attenuation);
// Restore the original shadow index.
lightData.shadowIndex = originalShadowIndex;
float intensity = max(0, attenuation); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)

if (HasFeatureFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_TRANSMISSION))
{
float3 transmittance = bsdfData.transmittance;
bool mixedThicknessMode = HasFeatureFlag(bsdfData.materialFeatures, MATERIAL_FEATURE_FLAGS_TRANSMISSION_MODE_MIXED_THICKNESS)
&& NdotL < 0 && lightData.shadowIndex >= 0;
if (mixedThicknessMode)
{

7
com.unity.render-pipelines.high-definition/HDRP/Lighting/LightLoop/LightLoopDef.hlsl.orig.meta


fileFormatVersion: 2
guid: 6e203653f9366b8498c42efe2e53ccbd
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存