浏览代码

Import various stacklit branch change

Move specular funciton in commonlighting.hlsl
Fix issue in TextureNormalVariance
Fix issue with colorPicker not working in forward
Misc format/comment/code sharing
/main
Sebastien Lagarde 6 年前
当前提交
9c4acb91
共有 8 个文件被更改,包括 92 次插入58 次删除
  1. 34
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonLighting.hlsl
  2. 10
      com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonMaterial.hlsl
  3. 6
      com.unity.render-pipelines.high-definition/HDRP/Material/LayeredLit/LayeredLitData.hlsl
  4. 8
      com.unity.render-pipelines.high-definition/HDRP/Material/Lit/Lit.hlsl
  5. 20
      com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitData.hlsl
  6. 16
      com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitDataIndividualLayer.hlsl
  7. 40
      com.unity.render-pipelines.high-definition/HDRP/Material/MaterialEvaluation.hlsl
  8. 16
      com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs

34
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonLighting.hlsl


return area;
}
// ref: Practical Realtime Strategies for Accurate Indirect Occlusion
// http://blog.selfshadow.com/publications/s2016-shading-course/#course_content
// Original Cone-Cone method with cosine weighted assumption (p129 s2016_pbs_activision_occlusion)
real GetSpecularOcclusionFromBentAO(real3 V, real3 bentNormalWS, real3 normalWS, real ambientOcclusion, real roughness)
{
// Retrieve cone angle
// Ambient occlusion is cosine weighted, thus use following equation. See slide 129
real cosAv = sqrt(1.0 - ambientOcclusion);
roughness = max(roughness, 0.01); // Clamp to 0.01 to avoid edge cases
real cosAs = exp2((-log(10.0) / log(2.0)) * Sq(roughness));
real cosB = dot(bentNormalWS, reflect(-V, normalWS));
return SphericalCapIntersectionSolidArea(cosAv, cosAs, cosB) / (TWO_PI * (1.0 - cosAs));
}
// Ref: Steve McAuley - Energy-Conserving Wrapped Diffuse
real ComputeWrappedDiffuseLighting(real NdotL, real w)
{

real3 localY = cross(localZ, localX);
return real3x3(localX, localY, localZ);
}
// Construct a right-handed view-dependent orthogonal basis around the normal:
// b0-b2 is the view-normal aka reflection plane.
real3x3 GetOrthoBasisViewNormal(real3 V, real3 N, real unclampedNdotV, bool testSingularity = false)
{
real3x3 orthoBasisViewNormal;
if (testSingularity && (abs(1.0 - unclampedNdotV) <= FLT_EPS))
{
// In this case N == V, and azimuth orientation around N shouldn't matter for the caller,
// we can use any quaternion-based method, like Frisvad or Reynold's (Pixar):
orthoBasisViewNormal = GetLocalFrame(N);
}
else
{
orthoBasisViewNormal[0] = normalize(V - N * unclampedNdotV);
orthoBasisViewNormal[2] = N;
orthoBasisViewNormal[1] = cross(orthoBasisViewNormal[2], orthoBasisViewNormal[0]);
}
return orthoBasisViewNormal;
}
#endif // UNITY_COMMON_LIGHTING_INCLUDED

10
com.unity.render-pipelines.core/CoreRP/ShaderLibrary/CommonMaterial.hlsl


void ConvertRoughnessToAnisotropy(real roughnessT, real roughnessB, out real anisotropy)
{
anisotropy = ((roughnessT - roughnessB) / (roughnessT + roughnessB + 0.0001));
anisotropy = ((roughnessT - roughnessB) / max(roughnessT + roughnessB, 0.0001));
}
// Same as ConvertAnisotropyToRoughness but

// Ref: Geometry into Shading - http://graphics.pixar.com/library/BumpRoughness/paper.pdf - equation (3)
float squaredRoughness = saturate(roughness * roughness + min(2.0 * variance, threshold * threshold)); // threshold can be really low, square the value for easier control
return 1.0 - RoughnessToPerceptualRoughness(sqrt(squaredRoughness));
return RoughnessToPerceptualSmoothness(sqrt(squaredRoughness));
}
// Reference: Error Reduction and Simplification for Shading Anti-Aliasing

// like Toksvig.
float TextureNormalVariance(float avgNormalLength)
{
float variance = 0.0;
if (avgNormalLength < 1.0)
{
float avgNormLen2 = avgNormalLength * avgNormalLength;

// Relationship between gaussian lobe and vMF lobe is 2 * variance = 1 / (2 * kappa) = roughness^2
// (Equation 36 of Normal map filtering based on The Order : 1886 SIGGRAPH course notes implementation).
// So to get variance we must use variance = 1 / (4 * kappa)
return 0.25 * kappa;
variance = 0.25 / kappa;
return 0.0;
return variance;
}
float TextureNormalFiltering(float perceptualSmoothness, float avgNormalLength, float threshold)

6
com.unity.render-pipelines.high-definition/HDRP/Material/LayeredLit/LayeredLitData.hlsl


// If user provide bent normal then we process a better term
#if (defined(_BENTNORMALMAP0) || defined(_BENTNORMALMAP1) || defined(_BENTNORMALMAP2) || defined(_BENTNORMALMAP3)) && defined(_ENABLESPECULAROCCLUSION)
// If we have bent normal and ambient occlusion, process a specular occlusion
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData);
#ifdef SPECULAR_OCCLUSION_USE_SPTD
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAOPivot(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness));
#else
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
#endif
#elif defined(_MASKMAP0) || defined(_MASKMAP1) || defined(_MASKMAP2) || defined(_MASKMAP3)
surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(dot(surfaceData.normalWS, V), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
#else

8
com.unity.render-pipelines.high-definition/HDRP/Material/Lit/Lit.hlsl


preLightData.ltcTransformSpecular._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
// Construct a right-handed view-dependent orthogonal basis around the normal
preLightData.orthoBasisViewNormal[0] = normalize(V - N * preLightData.NdotV); // Do not clamp NdotV here
preLightData.orthoBasisViewNormal[2] = N;
preLightData.orthoBasisViewNormal[1] = cross(preLightData.orthoBasisViewNormal[2], preLightData.orthoBasisViewNormal[0]);
preLightData.orthoBasisViewNormal = GetOrthoBasisViewNormal(V, N, preLightData.NdotV);
preLightData.ltcTransformCoat = 0.0;
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))

// If refraction is enable we use the transmittanceMask to lerp between current diffuse lighting and refraction value
// Physically speaking, transmittanceMask should be 1, but for artistic reasons, we let the value vary
//
// Note we also transfer the refracted light (lighting.indirect.specularTransmitted) into diffuseLighting
// since we know it won't be further processed: it is called at the end of the LightLoop(), but doing this
// enables opacity to affect it (in ApplyBlendMode()) while the rest of specularLighting escapes it.
#if HAS_REFRACTION
diffuseLighting = lerp(diffuseLighting, lighting.indirect.specularTransmitted, bsdfData.transmittanceMask);
#endif

20
com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitData.hlsl


#include "HDRP/Material/MaterialUtilities.hlsl"
#include "HDRP/Material/Decal/DecalUtilities.hlsl"
// TODO: move this function to commonLighting.hlsl once validated it work correctly
float GetSpecularOcclusionFromBentAO(float3 V, float3 bentNormalWS, SurfaceData surfaceData)
{
// Retrieve cone angle
// Ambient occlusion is cosine weighted, thus use following equation. See slide 129
float cosAv = sqrt(1.0 - surfaceData.ambientOcclusion);
float roughness = max(PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness), 0.01); // Clamp to 0.01 to avoid edge cases
float cosAs = exp2((-log(10.0)/log(2.0)) * Sq(roughness));
float cosB = dot(bentNormalWS, reflect(-V, surfaceData.normalWS));
return SphericalCapIntersectionSolidArea(cosAv, cosAs, cosB) / (TWO_PI * (1.0 - cosAs));
}
//#include "HDRP/Material/SphericalCapPivot/SPTDistribution.hlsl"
//#define SPECULAR_OCCLUSION_USE_SPTD
// Struct that gather UVMapping info of all layers + common calculation
// This is use to abstract the mapping that can differ on layers

// If user provide bent normal then we process a better term
#if defined(_BENTNORMALMAP) && defined(_ENABLESPECULAROCCLUSION)
// If we have bent normal and ambient occlusion, process a specular occlusion
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData);
#ifdef SPECULAR_OCCLUSION_USE_SPTD
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAOPivot(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToPerceptualRoughness(surfaceData.perceptualSmoothness));
#else
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData.normalWS, surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
#endif
#elif defined(_MASKMAP)
surfaceData.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(dot(surfaceData.normalWS, V)), surfaceData.ambientOcclusion, PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness));
#else

16
com.unity.render-pipelines.high-definition/HDRP/Material/Lit/LitDataIndividualLayer.hlsl


#ifdef SURFACE_GRADIENT
normalTS += detailNormalTS * detailMask;
#else
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask); // todo: detailMask should lerp the angle of the quaternion rotation, not the normals
#endif
#endif
#else

surfaceData.baseColor = SAMPLE_UVMAPPING_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).rgb * ADD_IDX(_BaseColor).rgb;
#ifdef _DETAIL_MAP_IDX
// Goal: we want the detail albedo map to be able to darken down to black and brighten up to white the surface albedo.
// The scale control the speed of the gradient. We simply remap detailAlbedo from [0..1] to [-1..1] then perform a lerp to black or white
// with a factor based on speed.
// Goal: we want the detail albedo map to be able to darken down to black and brighten up to white the surface albedo.
// The scale control the speed of the gradient. We simply remap detailAlbedo from [0..1] to [-1..1] then perform a lerp to black or white
// with a factor based on speed.
float albedoDetailSpeed = saturate(abs(detailAlbedo) * ADD_IDX(_DetailAlbedoScale));
float3 baseColorOverlay = lerp(sqrt(surfaceData.baseColor), (detailAlbedo < 0.0) ? float3(0.0, 0.0, 0.0) : float3(1.0, 1.0, 1.0), albedoDetailSpeed * albedoDetailSpeed);
baseColorOverlay *= baseColorOverlay;
float albedoDetailSpeed = saturate(abs(detailAlbedo) * ADD_IDX(_DetailAlbedoScale));
float3 baseColorOverlay = lerp(sqrt(surfaceData.baseColor), (detailAlbedo < 0.0) ? float3(0.0, 0.0, 0.0) : float3(1.0, 1.0, 1.0), albedoDetailSpeed * albedoDetailSpeed);
baseColorOverlay *= baseColorOverlay;
// Lerp with details mask
surfaceData.baseColor = lerp(surfaceData.baseColor, saturate(baseColorOverlay), detailMask);
#endif

#ifdef _DETAIL_MAP_IDX
// See comment for baseColorOverlay
float smoothnessDetailSpeed = saturate(abs(detailSmoothness) * ADD_IDX(_DetailSmoothnessScale));
float smoothnessOverlay = lerp(surfaceData.perceptualSmoothness, (detailSmoothness < 0.0) ? 0.0 : 1.0, smoothnessDetailSpeed);
float smoothnessOverlay = lerp(surfaceData.perceptualSmoothness, (detailSmoothness < 0.0) ? 0.0 : 1.0, smoothnessDetailSpeed);
// Lerp with details mask
surfaceData.perceptualSmoothness = lerp(surfaceData.perceptualSmoothness, saturate(smoothnessOverlay), detailMask);
#endif

40
com.unity.render-pipelines.high-definition/HDRP/Material/MaterialEvaluation.hlsl


float3 indirectSpecularOcclusion;
};
void GetScreenSpaceAmbientOcclusion(float2 positionSS, float NdotV, float perceptualRoughness, float ambientOcclusionFromData, float specularOcclusionFromData, out AmbientOcclusionFactor aoFactor)
// Get screen space ambient occlusion only:
float GetScreenSpaceDiffuseOcclusion(float2 positionSS)
// Ambient occlusion use for indirect lighting (reflection probe, baked diffuse lighting)
// Ambient occlusion use for indirect lighting (reflection probe, baked diffuse lighting)
// Ambient occlusion use for direct lighting (directional, punctual, area)
float directAmbientOcclusion = lerp(1.0, indirectAmbientOcclusion, _AmbientOcclusionParam.w);
float directAmbientOcclusion = 1.0;
return indirectAmbientOcclusion;
}
void GetScreenSpaceAmbientOcclusion(float2 positionSS, float NdotV, float perceptualRoughness, float ambientOcclusionFromData, float specularOcclusionFromData, out AmbientOcclusionFactor aoFactor)
{
float indirectAmbientOcclusion = GetScreenSpaceDiffuseOcclusion(positionSS);
float directAmbientOcclusion = lerp(1.0, indirectAmbientOcclusion, _AmbientOcclusionParam.w);
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(NdotV), indirectAmbientOcclusion, roughness);

aoFactor.directAmbientOcclusion = lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), directAmbientOcclusion);
}
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the diffuseColor)
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the diffuseColor)
// Note: When we ImageLoad outside of texture size, the value returned by Load is 0 (Note: On Metal maybe it clamp to value of texture which is also fine)
// We use this property to have a neutral value for AO that doesn't consume a sampler and work also with compute shader (i.e use ImageLoad)
// We store inverse AO so neutral is black. So either we sample inside or outside the texture it return 0 in case of neutral
// Ambient occlusion use for indirect lighting (reflection probe, baked diffuse lighting)
#ifndef _SURFACE_TYPE_TRANSPARENT
float indirectAmbientOcclusion = 1.0 - LOAD_TEXTURE2D(_AmbientOcclusionTexture, positionSS).x;
// Ambient occlusion use for direct lighting (directional, punctual, area)
float indirectAmbientOcclusion = GetScreenSpaceDiffuseOcclusion(positionSS);
#else
float indirectAmbientOcclusion = 1.0;
float directAmbientOcclusion = 1.0;
#endif
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(ClampNdotV(NdotV), indirectAmbientOcclusion, roughness);

void ApplyAmbientOcclusionFactor(AmbientOcclusionFactor aoFactor, inout BuiltinData builtinData, inout AggregateLighting lighting)
{
// Note: in case of deferred Lit, builtinData.bakeDiffuseLighting contain indirect diffuse * surfaceData.ambientOcclusion + emissive,
// so emissive is affected by SSAO and we get a double darkening from SSAO and from AO which is incorrect but we accept the tradeoff
// Note: In case of deferred Lit, builtinData.bakeDiffuseLighting contains indirect diffuse * surfaceData.ambientOcclusion + emissive,
// so SSAO is multiplied by emissive which is wrong.
// Also, we have double occlusion for diffuse lighting since it already had precomputed AO (aka "FromData") applied
// (the * surfaceData.ambientOcclusion above)
// This is a tradeoff to avoid storing the precomputed (from data) AO in the GBuffer.
// (This is also why GetScreenSpaceAmbientOcclusion*() is effectively called with AOFromData = 1.0 in Lit:PostEvaluateBSDF() in the
// deferred case since DecodeFromGBuffer will init bsdfData.ambientOcclusion to 1.0 and we will only have SSAO in the aoFactor here)
builtinData.bakeDiffuseLighting *= aoFactor.indirectAmbientOcclusion;
lighting.indirect.specularReflected *= aoFactor.indirectSpecularOcclusion;
lighting.direct.diffuse *= aoFactor.directAmbientOcclusion;

16
com.unity.render-pipelines.high-definition/HDRP/RenderPipeline/HDRenderPipeline.cs


public void ApplyDebugDisplaySettings(HDCamera hdCamera, CommandBuffer cmd)
{
// See ShaderPassForward.hlsl: for forward shaders, if DEBUG_DISPLAY is enabled and no DebugLightingMode or DebugMipMapMod
// modes have been set, lighting is automatically skipped (To avoid some crashed due to lighting RT not set on console).
// However debug mode like colorPickerModes and false color don't need DEBUG_DISPLAY and must work with the lighting.
// So we will enabled DEBUG_DISPLAY independently
// Enable globally the keyword DEBUG_DISPLAY on shader that support it with multicompile
CoreUtils.SetKeyword(cmd, "DEBUG_DISPLAY", m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled());
// enable globally the keyword DEBUG_DISPLAY on shader that support it with multicompile
cmd.EnableShaderKeyword("DEBUG_DISPLAY");
// This is for texture streaming
m_CurrentDebugDisplaySettings.UpdateMaterials();

// The DebugNeedsExposure test allows us to set a neutral value if exposure is not needed. This way we don't need to make various tests inside shaders but only in this function.
cmd.SetGlobalFloat(HDShaderIDs._DebugExposure, m_CurrentDebugDisplaySettings.DebugNeedsExposure() ? lightingDebugSettings.debugExposure : 0.0f);
}
else
{
// TODO: Be sure that if there is no change in the state of this keyword, it doesn't imply any work on CPU side! else we will need to save the sate somewher
cmd.DisableShaderKeyword("DEBUG_DISPLAY");
}
}

正在加载...
取消
保存