浏览代码

Improve and enable GetShiftedNdotV()

/main
Evgenii Golubev 8 年前
当前提交
a1d11347
共有 3 个文件被更改,包括 22 次插入28 次删除
  1. 12
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  2. 36
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  3. 2
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl

12
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl


PreLightData preLightData;
// TODO: check Eric idea about doing that when writting into the GBuffer (with our forward decal)
#if 0
preLightData.NdotV = GetShiftedNdotV(bsdfData.normalWS, V); // Note: May not work with speedtree...
#else
preLightData.NdotV = GetNdotV(bsdfData.normalWS, V);
#endif
preLightData.NdotV = GetShiftedNdotV(bsdfData.normalWS, V, false);
preLightData.ggxLambdaV = GetSmithJointGGXLambdaV(preLightData.NdotV, bsdfData.roughness);

// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NDotV) and use iblNormalWS
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
// With this in mind and for performance reasons we chose to only use modified normal to calculate R.
// iblNdotV = GetNdotV(iblNormalWS, V);
// iblNdotV = GetShiftedNdotV(iblNormalWS, V), false);
}
GetPreIntegratedFGD(iblNdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD);

float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float NdotV = saturate(dot(N, V));
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d

float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float NdotV = saturate(dot(N, V));
float NdotV = GetShiftedNdotV(N, V, false);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d

36
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


}
#ifndef INTRINSIC_CUBEMAP_FACE_ID
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
/*
float CubemapFaceID(float3 dir)
{

// 4 VGPR, 16 FR (12 FR, 1 QR), 2 scalar
// input [-infinity, infinity] and output [-PI/2, PI/2]
float FastATan(float x)
float FastATan(float x)
{
float t0 = FastATanPos(abs(x));
return (x < 0.0) ? -t0 : t0;

// various helper
//-----------------------------------------------------------------------------
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping + decal
// In this case this may cause weird artifact.
// GetNdotV return a 'valid' data
float GetNdotV(float3 N, float3 V)
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal
// should be modified to become valid (i.e facing the camera) to avoid weird artifacts.
// Note: certain applications (e.g. SpeedTree) make use of two-sided lighting.
float GetShiftedNdotV(inout float3 N, float3 V, bool twoSided)
return abs(dot(N, V)); // This abs allow to limit artifact
}
float NdotV = dot(N, V);
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping + decal
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Note: This code is not compatible with two sided lighting used in SpeedTree (TODO: investigate).
float GetShiftedNdotV(float3 N, float3 V)
{
// The amount we shift the normal toward the view vector is defined by the dot product.
float shiftAmount = dot(N, V);
N = shiftAmount < 0.0 ? N + V * (-shiftAmount + 1e-5f) : N;
N = normalize(N);
if (!twoSided && NdotV < 0.0)
{
const float magic = 1e-5f;
// We do not renormalize the normal because { abs(length(N) - 1.0) < magic }.
N += (-NdotV + magic) * V;
NdotV = magic;
}
return saturate(dot(N, V)); // TODO: this saturate should not be necessary here
return NdotV;
#endif // UNITY_COMMON_INCLUDED

2
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// Ref: Listing 18 in "Moving Frostbite to PBR" + https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/
float4 IntegrateGGXAndDisneyFGD(float3 V, float3 N, float roughness, uint sampleCount)
{
float NdotV = saturate(dot(N, V));
float NdotV = GetShiftedNdotV(N, V, false);
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);

正在加载...
取消
保存