浏览代码

Finish testing dual normals: push N dependent geometric term inside BSDF( ) evaluation, use geometric normals for receiver bias and base normal (for now) for diffuse, SSS and transmission.

/stacklit
Stephane Laroche 6 年前
当前提交
43efd730
共有 1 个文件被更改,包括 39 次插入32 次删除
  1. 71
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.hlsl

71
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.hlsl


struct PreLightData
{
float NdotV[NB_NORMALS]; // Could be negative due to normal mapping, use ClampNdotV()
//float NdotV;
float geomNdotV;
float bottomAngleFGD;
float TdotV; // Stored only when VLAYERED_RECOMPUTE_PERLIGHT
float BdotV;

// slnote dual map
float PreLightData_GetBaseNdotVForFGD(BSDFData bsdfData, PreLightData preLightData, float NdotV[NB_NORMALS])
{
float baseLayerNdotV;

return baseLayerNdotV;
}
// slnote dual map
void PreLightData_SetupNormals(BSDFData bsdfData, inout PreLightData preLightData, float3 V, out float3 N[NB_NORMALS], out float NdotV[NB_NORMALS])
{
N[BASE_NORMAL_IDX] = bsdfData.normalWS;

N[COAT_NORMAL_IDX] = bsdfData.coatNormalWS;
preLightData.NdotV[COAT_NORMAL_IDX] = dot(N[COAT_NORMAL_IDX], V);
NdotV[COAT_NORMAL_IDX] = ClampNdotV(preLightData.NdotV[COAT_NORMAL_IDX]);
preLightData.geomNdotV = dot(bsdfData.geomNormalWS, V);
}
#endif
}

IF_DEBUG( if(_DebugLobeMask.y == 0.0) DV[BASE_LOBEA_IDX] = (float3)0; )
IF_DEBUG( if(_DebugLobeMask.z == 0.0) DV[BASE_LOBEB_IDX] = (float3)0; )
specularLighting = preLightData.vLayerEnergyCoeff[BOTTOM_VLAYER_IDX]
specularLighting = max(0, NdotL[DNLV_BASE_IDX]) * preLightData.vLayerEnergyCoeff[BOTTOM_VLAYER_IDX]
specularLighting += preLightData.vLayerEnergyCoeff[TOP_VLAYER_IDX]
specularLighting += max(0, NdotL[DNLV_COAT_IDX]) * preLightData.vLayerEnergyCoeff[TOP_VLAYER_IDX]
* preLightData.energyCompensationFactor[COAT_LOBE_IDX]
* DV[COAT_LOBE_IDX];

IF_DEBUG( if(_DebugLobeMask.y == 0.0) DV[BASE_LOBEA_IDX] = (float3)0; )
IF_DEBUG( if(_DebugLobeMask.z == 0.0) DV[BASE_LOBEB_IDX] = (float3)0; )
specularLighting = F * lerp(DV[0]*preLightData.energyCompensationFactor[BASE_LOBEA_IDX],
DV[1]*preLightData.energyCompensationFactor[BASE_LOBEB_IDX],
bsdfData.lobeMix);
specularLighting = max(0, NdotL[0]) * F * lerp(DV[0]*preLightData.energyCompensationFactor[BASE_LOBEA_IDX],
DV[1]*preLightData.energyCompensationFactor[BASE_LOBEB_IDX],
bsdfData.lobeMix);
float3 diffuseTerm = Lambert();
float3 diffuseTerm = Lambert() * max(0, NdotL[DNLV_BASE_IDX]);
#ifdef VLAYERED_DIFFUSE_ENERGY_HACKED_TERM
// TODOTODO: Energy when vlayered.

void EvaluateBSDF_GetNormalUnclampedNdotV(BSDFData bsdfData, PreLightData preLightData, float3 V, out float3 N, out float unclampedNdotV)
{
//TODO: This affects transmission and SSS, choose the normal the use when we have
// both. For now, just use the base:
N = bsdfData.normalWS;
unclampedNdotV = preLightData.NdotV[BASE_NORMAL_IDX];
//TODOWIP for now just return geometric normal:
N = bsdfData.geomNormalWS;
unclampedNdotV = dot(N, V);
}
else
#ifdef _STACKLIT_DEBUG
if(_DebugLobeMask.w == 2.0)
{
N = bsdfData.coatNormalWS;
unclampedNdotV = preLightData.NdotV[COAT_NORMAL_IDX];
}
else if(_DebugLobeMask.w == 3.0)
{
N = bsdfData.geomNormalWS;
unclampedNdotV = preLightData.geomNdotV;
}
{
// TODOWIP, for now, preserve previous behavior
N = bsdfData.normalWS;
unclampedNdotV = preLightData.NdotV[BASE_NORMAL_IDX];
#endif // _MATERIAL_FEATURE_COAT_NORMALMAP
}
//-----------------------------------------------------------------------------

DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
//slnote dual map
//float3 N = bsdfData.normalWS;
//float NdotV = ClampNdotV(preLightData.NdotV);
float NdotV = ClampNdotV(unclampedNdotV);
float NdotL = dot(N, L);
float LdotV = dot(L, V);

float attenuation;
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, N, L, color, attenuation);
float intensity = max(0, attenuation * NdotL); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
// For shadow attenuation (ie receiver bias), always use the geometric normal:
EvaluateLight_Directional(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L, 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)
// Note: We use NdotL here to early out, but in case of coat this is not correct. But we are ok with this
// Note: the NdotL term is now applied in the BSDF() eval itself to account for different normals.
UNITY_BRANCH if (intensity > 0.0)
{
BSDF(V, L, NdotL, posInput.positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);

if (_DebugLightingMode == DEBUGLIGHTINGMODE_LUX_METER)
{
// Only lighting, not BSDF
intensity = max(0, attenuation * NdotL);
lighting.diffuse = color * intensity * lightData.diffuseScale;
}
#endif

distances.xyz = float3(dist, distSq, distRcp);
}
//slnote dual map
//float3 N = bsdfData.normalWS;
//float NdotV = ClampNdotV(preLightData.NdotV);
float NdotV = ClampNdotV(unclampedNdotV);
float NdotL = dot(N, L);
float LdotV = dot(L, V);

float3 color;
float attenuation;
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L,
// For shadow attenuation (ie receiver bias), always use the geometric normal:
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, bsdfData.geomNormalWS, L,
float intensity = max(0, attenuation * NdotL); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
float intensity = max(0, attenuation); // Warning: attenuation can be greater than 1 due to the inverse square attenuation (when position is close to light)
// Note: We use NdotL here to early out, but in case of coat this is not correct. But we are ok with this
// Note: the NdotL term is now applied in the BSDF() eval itself to account for different normals.
UNITY_BRANCH if (intensity > 0.0)
{
// Simulate a sphere light with this hack

if (_DebugLightingMode == DEBUGLIGHTINGMODE_LUX_METER)
{
// Only lighting, not BSDF
intensity = max(0, attenuation * NdotL);
lighting.diffuse = color * intensity * lightData.diffuseScale;
}
#endif

if( (i == (0 IF_FEATURE_COAT(+1))) && _DebugEnvLobeMask.y == 0.0) continue;
if( (i == (1 IF_FEATURE_COAT(+1))) && _DebugEnvLobeMask.z == 0.0) continue;
#endif
//slnote dual map
//EvaluateLight_EnvIntersection(positionWS, bsdfData.normalWS, lightData, influenceShapeType, R[i], tempWeight[i]);
EvaluateLight_EnvIntersection(positionWS, influenceNormal, lightData, influenceShapeType, R[i], tempWeight[i]);
// When we are rough, we tend to see outward shifting of the reflection when at the boundary of the projection volume

正在加载...
取消
保存