Sebastien Lagarde
8 年前
当前提交
2ffcb7f1
共有 11 个文件被更改,包括 267 次插入 和 280 次删除
-
2Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
-
1Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Deferred.shader
-
8Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs
-
24Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/LightDefinition.cs.hlsl
-
2Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/Lighting.hlsl
-
9Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/SinglePass/SinglePass.hlsl
-
5Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Lighting/SinglePass/SinglePassLoop.hlsl
-
241Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl
-
10Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Material.hlsl
-
9Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/LitEnvTemplate.hlsl.meta
-
236Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/LitEnvTemplate.hlsl
|
|||
fileFormatVersion: 2 |
|||
guid: 22c20a34a48ade04daa95ffdc51ac052 |
|||
timeCreated: 1476997917 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Env - Reference |
|||
// ---------------------------------------------------------------------------- |
|||
|
|||
// Ref: Moving Frostbite to PBR (Appendix A) |
|||
float3 IntegrateLambertIBLRef( EnvLightData lightData, BSDFData bsdfData, |
|||
UNITY_ARGS_ENV(_EnvTextures), |
|||
uint sampleCount = 2048) |
|||
{ |
|||
float3 N = bsdfData.normalWS; |
|||
float3 acc = float3(0.0, 0.0, 0.0); |
|||
// Add some jittering on Hammersley2d |
|||
float2 randNum = InitRandom(N.xy * 0.5 + 0.5); |
|||
|
|||
float3 tangentX, tangentY; |
|||
GetLocalFrame(N, tangentX, tangentY); |
|||
|
|||
for (uint i = 0; i < sampleCount; ++i) |
|||
{ |
|||
float2 u = Hammersley2d(i, sampleCount); |
|||
u = frac(u + randNum + 0.5); |
|||
|
|||
float3 L; |
|||
float NdotL; |
|||
float weightOverPdf; |
|||
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf); |
|||
|
|||
if (NdotL > 0.0) |
|||
{ |
|||
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0); |
|||
|
|||
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function |
|||
acc += bsdfData.diffuseColor * Lambert() * weightOverPdf * val.rgb; |
|||
} |
|||
} |
|||
|
|||
return acc / sampleCount; |
|||
} |
|||
|
|||
float3 IntegrateDisneyDiffuseIBLRef(float3 V, EnvLightData lightData, BSDFData bsdfData, |
|||
UNITY_ARGS_ENV(_EnvTextures), |
|||
uint sampleCount = 2048) |
|||
{ |
|||
float3 N = bsdfData.normalWS; |
|||
float NdotV = dot(N, V); |
|||
float3 acc = float3(0.0, 0.0, 0.0); |
|||
// Add some jittering on Hammersley2d |
|||
float2 randNum = InitRandom(N.xy * 0.5 + 0.5); |
|||
|
|||
float3 tangentX, tangentY; |
|||
GetLocalFrame(N, tangentX, tangentY); |
|||
|
|||
for (uint i = 0; i < sampleCount; ++i) |
|||
{ |
|||
float2 u = Hammersley2d(i, sampleCount); |
|||
u = frac(u + randNum + 0.5); |
|||
|
|||
float3 L; |
|||
float NdotL; |
|||
float weightOverPdf; |
|||
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table |
|||
ImportanceSampleLambert(u, N, tangentX, tangentY, L, NdotL, weightOverPdf); |
|||
|
|||
if (NdotL > 0.0) |
|||
{ |
|||
float3 H = normalize(L + V); |
|||
float LdotH = dot(L, H); |
|||
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account |
|||
// in weightOverPdf of ImportanceSampleLambert call. |
|||
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness); |
|||
|
|||
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function |
|||
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0); |
|||
acc += bsdfData.diffuseColor * disneyDiffuse * weightOverPdf * val.rgb; |
|||
} |
|||
} |
|||
|
|||
return acc / sampleCount; |
|||
} |
|||
|
|||
// Ref: Moving Frostbite to PBR (Appendix A) |
|||
float3 IntegrateSpecularGGXIBLRef( float3 V, EnvLightData lightData, BSDFData bsdfData, |
|||
UNITY_ARGS_ENV(_EnvTextures), |
|||
uint sampleCount = 2048) |
|||
{ |
|||
float3 N = bsdfData.normalWS; |
|||
float NdotV = saturate(dot(N, V)); |
|||
float3 acc = float3(0.0, 0.0, 0.0); |
|||
|
|||
// Add some jittering on Hammersley2d |
|||
float2 randNum = InitRandom(V.xy * 0.5 + 0.5); |
|||
|
|||
float3 tangentX, tangentY; |
|||
GetLocalFrame(N, tangentX, tangentY); |
|||
|
|||
for (uint i = 0; i < sampleCount; ++i) |
|||
{ |
|||
float2 u = Hammersley2d(i, sampleCount); |
|||
u = frac(u + randNum + 0.5); |
|||
|
|||
float VdotH; |
|||
float NdotL; |
|||
float3 L; |
|||
float weightOverPdf; |
|||
|
|||
// GGX BRDF |
|||
ImportanceSampleGGX(u, V, N, tangentX, tangentY, bsdfData.roughness, NdotV, |
|||
L, VdotH, NdotL, weightOverPdf); |
|||
|
|||
if (NdotL > 0.0) |
|||
{ |
|||
// Fresnel component is apply here as describe in ImportanceSampleGGX function |
|||
float3 FweightOverPdf = F_Schlick(bsdfData.fresnel0, VdotH) * weightOverPdf; |
|||
|
|||
float4 val = UNITY_SAMPLE_ENV_LOD(_EnvTextures, L, lightData, 0); |
|||
|
|||
acc += FweightOverPdf * val.rgb; |
|||
} |
|||
} |
|||
|
|||
return acc / sampleCount; |
|||
} |
|||
|
|||
//----------------------------------------------------------------------------- |
|||
// EvaluateBSDF_Env |
|||
// ---------------------------------------------------------------------------- |
|||
|
|||
// _preIntegratedFGD and _CubemapLD are unique for each BRDF |
|||
void EvaluateBSDF_Env( float3 V, float3 positionWS, PreLightData prelightData, EnvLightData lightData, BSDFData bsdfData, |
|||
UNITY_ARGS_ENV(_EnvTextures), |
|||
out float4 diffuseLighting, |
|||
out float4 specularLighting) |
|||
{ |
|||
#ifdef LIT_DISPLAY_REFERENCE |
|||
|
|||
specularLighting.rgb = IntegrateSpecularGGXIBLRef(V, lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures)); |
|||
specularLighting.a = 1.0; |
|||
|
|||
/* |
|||
#ifdef DIFFUSE_LAMBERT_BRDF |
|||
diffuseLighting.rgb = IntegrateLambertIBLRef(lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures)); |
|||
#else |
|||
diffuseLighting.rgb = IntegrateDisneyDiffuseIBLRef(V, lightData, bsdfData, UNITY_PASS_ENV(_EnvTextures)); |
|||
#endif |
|||
diffuseLighting.a = 1.0; |
|||
*/ |
|||
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0); |
|||
|
|||
#else |
|||
// TODO: factor this code in common, so other material authoring don't require to rewrite everything, |
|||
// also think about how such a loop can handle 2 cubemap at the same time as old unity. Macro can allow to do that |
|||
// but we need to have UNITY_SAMPLE_ENV_LOD replace by a true function instead that is define by the lighting arcitecture. |
|||
// Also not sure how to deal with 2 intersection.... |
|||
// Box and sphere are related to light property (but we have also distance based roughness etc...) |
|||
|
|||
// TODO: test the strech from Tomasz |
|||
// float shrinkedRoughness = AnisotropicStrechAtGrazingAngle(bsdfData.roughness, bsdfData.perceptualRoughness, NdotV); |
|||
|
|||
// Note: As explain in GetPreLightData we use normalWS and not iblNormalWS here (in case of anisotropy) |
|||
float3 rayWS = GetSpecularDominantDir(bsdfData.normalWS, prelightData.iblR, bsdfData.roughness); |
|||
|
|||
float3 R = rayWS; |
|||
float weight = 1.0; |
|||
|
|||
// In this code we redefine a bit the behavior of the reflcetion proble. We separate the projection volume (the proxy of the scene) form the influence volume (what pixel on the screen is affected) |
|||
|
|||
// 1. First determine the projection volume |
|||
|
|||
// In Unity the cubemaps are capture with the localToWorld transform of the component. |
|||
// This mean that location and oritention matter. So after intersection of proxy volume we need to convert back to world. |
|||
|
|||
// CAUTION: localToWorld is the transform use to convert the cubemap capture point to world space (mean it include the offset) |
|||
// the center of the bounding box is thus in locals space: positionLS - offsetLS |
|||
// We use this formulation as it is the one of legacy unity that was using only AABB box. |
|||
|
|||
float3x3 worldToLocal = transpose(float3x3(lightData.right, lightData.up, lightData.forward)); // worldToLocal assume no scaling |
|||
float3 positionLS = positionWS - lightData.positionWS; |
|||
positionLS = mul(positionLS, worldToLocal).xyz - lightData.offsetLS; // We want to calculate the intersection from the center of the bounding box. |
|||
|
|||
if (lightData.envShapeType == ENVSHAPETYPE_BOX) |
|||
{ |
|||
float3 rayLS = mul(rayWS, worldToLocal); |
|||
float3 boxOuterDistance = lightData.innerDistance + float3(lightData.blendDistance, lightData.blendDistance, lightData.blendDistance); |
|||
float dist = BoxRayIntersectSimple(positionLS, rayLS, -boxOuterDistance, boxOuterDistance); |
|||
|
|||
// No need to normalize for fetching cubemap |
|||
// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS |
|||
R = (positionWS + dist * rayWS) - lightData.positionWS; |
|||
|
|||
// TODO: add distance based roughness |
|||
} |
|||
else if (lightData.envShapeType == ENVSHAPETYPE_SPHERE) |
|||
{ |
|||
float3 rayLS = mul(rayWS, worldToLocal); |
|||
float sphereOuterDistance = lightData.innerDistance.x + lightData.blendDistance; |
|||
float dist = SphereRayIntersectSimple(positionLS, rayLS, sphereOuterDistance); |
|||
|
|||
R = (positionWS + dist * rayWS) - lightData.positionWS; |
|||
} |
|||
|
|||
// 2. Apply the influence volume (Box volume is used for culling whatever the influence shape) |
|||
// TODO: In the future we could have an influence volume inside the projection volume (so with a different transform, in this case we will need another transform) |
|||
if (lightData.envShapeType == ENVSHAPETYPE_SPHERE) |
|||
{ |
|||
float distFade = max(length(positionLS) - lightData.innerDistance.x, 0.0); |
|||
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero |
|||
} |
|||
else // ENVSHAPETYPE_BOX or ENVSHAPETYPE_NONE |
|||
{ |
|||
// Calculate falloff value, so reflections on the edges of the volume would gradually blend to previous reflection. |
|||
float distFade = DistancePointBox(positionLS, -lightData.innerDistance, lightData.innerDistance); |
|||
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero |
|||
} |
|||
|
|||
// Smooth weighting |
|||
weight = smoothstep01(weight); |
|||
|
|||
// TODO: we must always perform a weight calculation as due to tiled rendering we need to smooth out cubemap at boundaries. |
|||
// So goal is to split into two category and have an option to say if we parallax correct or not. |
|||
|
|||
// TODO: compare current Morten version: offline cubemap with a particular remap + the bias in perceptualRoughnessToMipmapLevel |
|||
// to classic remap like unreal/Frobiste. The function GetSpecularDominantDir can result in a better matching in this case |
|||
// We let GetSpecularDominantDir currently as it still an improvement but not as good as it could be |
|||
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness); |
|||
float4 preLD = UNITY_SAMPLE_ENV_LOD(_EnvTextures, R, lightData, mip); |
|||
specularLighting.rgb = preLD.rgb * prelightData.specularFGD; |
|||
|
|||
// Apply specular occlusion on it |
|||
specularLighting.rgb *= bsdfData.specularOcclusion; |
|||
specularLighting.a = weight; |
|||
|
|||
diffuseLighting = float4(0.0, 0.0, 0.0, 0.0); |
|||
|
|||
#endif |
|||
} |
|||
|
撰写
预览
正在加载...
取消
保存
Reference in new issue