浏览代码

Clean up the area light code

/main
Evgenii Golubev 7 年前
当前提交
70cf921d
共有 1 个文件被更改,包括 61 次插入80 次删除
  1. 141
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

141
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


struct PreLightData
{
// General
float NdotV; // Geometric version (not clamped)
float NdotV; // Geometric version (could be negative)
// GGX iso
float ggxLambdaV;

float3 specularFGD; // Store preconvoled BRDF for both specular and diffuse
float diffuseFGD;
// area light
float3x3 orthoBasisVN; // Right-handed view-dependent orthogonal basis around the normal
float3x3 ltcXformGGX; // Sparse: should only use 4x VGPRs. Could be scalarized
float3x3 ltcXformDisneyDiffuse; // Sparse: should only use 4x VGPRs. Could be scalarized
float ltcGGXFresnelMagnitudeDiff; // The difference of magnitudes of GGX and Fresnel
float ltcGGXFresnelMagnitude;
float ltcDisneyDiffuseMagnitude;
// Area lights (17 VGPRs). Scalarize?
float3x3 orthoBasisViewNormal; // Right-handed view-dependent orthogonal basis around the normal (6x VGPRs)
float3x3 ltcTransformDiffuse; // Inverse transformation for Lambertian or Disney Diffuse (4x VGPRs)
float3x3 ltcTransformSpecular; // Inverse transformation for GGX (4x VGPRs)
float ltcMagnitudeDiffuse;
float3 ltcMagnitudeFresnel;
};
PreLightData GetPreLightData(float3 V, PositionInputs posInput, BSDFData bsdfData)

preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
// Area light
preLightData.orthoBasisVN[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);
preLightData.orthoBasisVN[1] = normalize(cross(bsdfData.normalWS, preLightData.orthoBasisVN[0]));
preLightData.orthoBasisVN[2] = bsdfData.normalWS;
// Note we load the matrix transpose (avoid to have to transpose it in shader)
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
preLightData.ltcTransformDiffuse = k_identity3x3;
#else
// Get the inverse LTC matrix for Disney Diffuse
preLightData.ltcTransformDiffuse = 0.0;
preLightData.ltcTransformDiffuse._m22 = 1.0;
preLightData.ltcTransformDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
#endif
preLightData.ltcXformGGX = 0.0;
preLightData.ltcXformGGX._m22 = 1.0;
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
preLightData.ltcTransformSpecular = 0.0;
preLightData.ltcTransformSpecular._m22 = 1.0;
preLightData.ltcTransformSpecular._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
// Get the inverse LTC matrix for Disney Diffuse
// Note we load the matrix transpose (avoid to have to transpose it in shader)
preLightData.ltcXformDisneyDiffuse = 0.0;
preLightData.ltcXformDisneyDiffuse._m22 = 1.0;
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
// Construct a right-handed view-dependent orthogonal basis around the normal
preLightData.orthoBasisViewNormal[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);
preLightData.orthoBasisViewNormal[2] = bsdfData.normalWS;
preLightData.orthoBasisViewNormal[1] = normalize(cross(preLightData.orthoBasisViewNormal[2], preLightData.orthoBasisViewNormal[0]));
preLightData.ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r;
preLightData.ltcGGXFresnelMagnitude = ltcMagnitude.g;
preLightData.ltcDisneyDiffuseMagnitude = ltcMagnitude.b;
float ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r;
float ltcGGXFresnelMagnitude = ltcMagnitude.g;
float ltcDisneyDiffuseMagnitude = ltcMagnitude.b;
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
preLightData.ltcMagnitudeDiffuse = 1;
#else
preLightData.ltcMagnitudeDiffuse = ltcDisneyDiffuseMagnitude;
#endif
// TODO: the fit seems rather poor. The scaling factor of 0.5 allows us
// to match the reference for rough metals, but further darkens dielectrics.
preLightData.ltcMagnitudeFresnel = bsdfData.fresnel0 * ltcGGXFresnelMagnitudeDiff + ltcGGXFresnelMagnitude;
return preLightData;
}

// Currently, we only model diffuse transmission. Specular transmission is not yet supported.
// We assume that the back side of the object is a uniformly illuminated infinite plane
// with the reversed normal (and the view vector) of the current sample.
float3 EvaluateTransmission(BSDFData bsdfData, float intensity, float diffuseScale, float shadow)
float3 EvaluateTransmission(BSDFData bsdfData, float intensity, float shadow)
float backLight = intensity * shadow * diffuseScale;
float backLight = intensity * shadow;
return backLight * bsdfData.transmittance; // Premultiplied with the diffuse color
}

float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, illuminance, lightData.diffuseScale, shadow);
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
}
// Save ALU by applying 'lightData.color' only once.

float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, illuminance, lightData.diffuseScale, shadow);
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
}
// Save ALU by applying 'lightData.color' only once.

float3 P2 = lightData.positionWS + T * (0.5 * len);
// Rotate the endpoints into the local coordinate system.
P1 = mul(P1, transpose(preLightData.orthoBasisVN));
P2 = mul(P2, transpose(preLightData.orthoBasisVN));
P1 = mul(P1, transpose(preLightData.orthoBasisViewNormal));
P2 = mul(P2, transpose(preLightData.orthoBasisViewNormal));
// Compute the binormal.
// Compute the binormal in the local coordinate system.
float3 B = normalize(cross(P1, P2));
float ltcValue;

#ifdef LIT_DIFFUSE_LAMBERT_BRDF
ltcValue = LTCEvaluate(P1, P2, B, k_identity3x3);
#else
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcXformDisneyDiffuse);
#endif
#ifndef LIT_DIFFUSE_LAMBERT_BRDF
ltcValue *= preLightData.ltcDisneyDiffuseMagnitude;
#endif
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse);
diffuseLighting = bsdfData.diffuseColor * ltcValue;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
[branch] if (bsdfData.enableTransmission)

// Use the Lambertian approximation for performance reasons.
// The matrix multiplication should not generate any extra ALU on GCN.
ltcValue = LTCEvaluate(P1, P2, B, mul(flipMatrix, k_identity3x3));
ltcValue = LTCEvaluate(P1, P2, B, mul(flipMatrix, k_identity3x3));
ltcValue *= lightData.diffuseScale;
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, lightData.diffuseScale, 1);
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
// TODO: the fit seems rather poor. The scaling factor of 0.5 allows us
// to match the reference for rough metals, but further darkens dielectrics.
float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcXformGGX);
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformSpecular);
specularLighting = fresnelTerm * ltcValue;
specularLighting = preLightData.ltcMagnitudeFresnel * ltcValue;
}
// Save ALU by applying 'lightData.color' only once.

lightVerts[3] = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
// Rotate the endpoints into the local coordinate system.
lightVerts = mul(lightVerts, transpose(preLightData.orthoBasisVN));
lightVerts = mul(lightVerts, transpose(preLightData.orthoBasisViewNormal));
float3x3 ltcMatrix;
float ltcValue;
float ltcValue;
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
ltcMatrix = k_identity3x3;
#else
ltcMatrix = preLightData.ltcXformDisneyDiffuse;
#endif
ltcValue = PolygonIrradiance(mul(lightVerts, ltcMatrix));
#ifndef LIT_DIFFUSE_LAMBERT_BRDF
ltcValue *= preLightData.ltcDisneyDiffuseMagnitude;
#endif
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse));
diffuseLighting = bsdfData.diffuseColor * ltcValue;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
[branch] if (bsdfData.enableTransmission)

// Use the Lambertian approximation for performance reasons.
// The matrix multiplication should not generate any extra ALU on GCN.
ltcMatrix = mul(flipMatrix, k_identity3x3);
float3x3 ltcTransform = mul(flipMatrix, k_identity3x3);
ltcValue = PolygonIrradiance(mul(lightVerts, ltcMatrix));
ltcValue = PolygonIrradiance(mul(lightVerts, ltcTransform));
ltcValue *= lightData.diffuseScale;
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, lightData.diffuseScale, 1);
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
ltcMatrix = preLightData.ltcXformGGX;
ltcValue = PolygonIrradiance(mul(lightVerts, ltcMatrix));
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular));
// TODO: the fit seems rather poor. The scaling factor of 0.5 allows us
// to match the reference for rough metals, but further darkens dielectrics.
float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
specularLighting = fresnelTerm * ltcValue;
specularLighting = preLightData.ltcMagnitudeFresnel * ltcValue;
}
// Save ALU by applying 'lightData.color' only once.

正在加载...
取消
保存