浏览代码

Merge pull request #528 from Unity-Technologies/Refactor-LightLoop-Glue-Code

HDRenderPipeline: Refactor LightLoop glue code
/Yibing-Project-2
GitHub 7 年前
当前提交
c25c236d
共有 11 个文件被更改,包括 299 次插入256 次删除
  1. 6
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader
  2. 2
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute
  3. 20
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  4. 19
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl
  5. 18
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl
  6. 114
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  7. 323
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  8. 32
      ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl
  9. 13
      ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl
  10. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/UnlitData.hlsl
  11. 6
      ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl

6
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader


UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
uint featureFlags = 0xFFFFFFFF;
DECODE_FROM_GBUFFER(gbuffer, featureFlags, bsdfData, bakeDiffuseLighting);
DECODE_FROM_GBUFFER(gbuffer, MATERIAL_FEATURE_MASK_FLAGS, bsdfData, bakeDiffuseLighting);
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, LIGHT_FEATURE_MASK_FLAGS_OPAQUE, diffuseLighting, specularLighting);
Outputs outputs;
#ifdef OUTPUT_SPLIT_LIGHTING

2
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/Deferred.compute


{
uint2 tileCoord = (16 * groupId) / GetTileSize();
uint2 pixelCoord = dispatchThreadId;
uint featureFlags = 0xFFFFFFFF;
uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIAL_FEATURE_MASK_FLAGS;
#endif

20
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


public enum LightFeatureFlags
{
// Light bit mask must match LightDefinitions.s_LightFeatureMaskFlags value
Punctual = 1 << 8,
Area = 1 << 9,
Directional = 1 << 10,
Env = 1 << 11,
Sky = 1 << 12,
SSL = 1 << 13 // If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
Punctual = 1 << 12,
Area = 1 << 13,
Directional = 1 << 14,
Env = 1 << 15,
Sky = 1 << 16,
SSRefraction = 1 << 17,
SSReflection = 1 << 18,
// If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
}
[GenerateHLSL]

public static int s_NumFeatureVariants = 27;
// Following define the maximum number of bits use in each feature category.
public static uint s_LightFeatureMaskFlags = 0xFF00;
public static uint s_MaterialFeatureMaskFlags = 0x00FF; // don't use all bits just to be safe from signed and/or float conversions :/
public static uint s_LightFeatureMaskFlags = 0xFFF000;
public static uint s_LightFeatureMaskFlagsOpaque = 0xFFF000 & ~((uint)LightFeatureFlags.SSRefraction); // Opaque don't support screen space refraction
public static uint s_LightFeatureMaskFlagsTransparent = 0xFFF000 & ~((uint)LightFeatureFlags.SSReflection); // Transparent don't support screen space reflection
public static uint s_MaterialFeatureMaskFlags = 0x000FFF; // don't use all bits just to be safe from signed and/or float conversions :/
}
[GenerateHLSL]

19
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl


//
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightFeatureFlags: static fields
//
#define LIGHTFEATUREFLAGS_PUNCTUAL (256)
#define LIGHTFEATUREFLAGS_AREA (512)
#define LIGHTFEATUREFLAGS_DIRECTIONAL (1024)
#define LIGHTFEATUREFLAGS_ENV (2048)
#define LIGHTFEATUREFLAGS_SKY (4096)
#define LIGHTFEATUREFLAGS_SSL (8192)
#define LIGHTFEATUREFLAGS_PUNCTUAL (4096)
#define LIGHTFEATUREFLAGS_AREA (8192)
#define LIGHTFEATUREFLAGS_DIRECTIONAL (16384)
#define LIGHTFEATUREFLAGS_ENV (32768)
#define LIGHTFEATUREFLAGS_SKY (65536)
#define LIGHTFEATUREFLAGS_SSREFRACTION (131072)
#define LIGHTFEATUREFLAGS_SSREFLECTION (262144)
//
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightDefinitions: static fields

#define TILE_SIZE_FPTL (16)
#define TILE_SIZE_CLUSTERED (32)
#define NUM_FEATURE_VARIANTS (27)
#define LIGHT_FEATURE_MASK_FLAGS (65280)
#define MATERIAL_FEATURE_MASK_FLAGS (255)
#define LIGHT_FEATURE_MASK_FLAGS (16773120)
#define LIGHT_FEATURE_MASK_FLAGS_OPAQUE (16642048)
#define LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT (16510976)
#define MATERIAL_FEATURE_MASK_FLAGS (4095)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.TilePass.SFiniteLightBound
// PackingRules = Exact

18
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl


ShadowContext shadowContext;
};
// Store all the accumulated lighting produce by the light loop
struct LightLoopAccumulatedLighting
{
float3 dirDiffuseLighting;
float3 dirSpecularLighting;
float3 punctualDiffuseLighting;
float3 punctualSpecularLighting;
float3 areaDiffuseLighting;
float3 areaSpecularLighting;
float3 envDiffuseLighting;
float3 envSpecularLighting;
float envDiffuseLightingWeight;
};
//-----------------------------------------------------------------------------
// Cookie sampling functions
// ----------------------------------------------------------------------------

114
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


#endif // LIGHTLOOP_TILE_PASS
void applyWeigthedIblLighting(float3 localDiffuseLighting, float3 localSpecularLighting, float2 weight, inout float3 iblDiffuseLighting, inout float3 iblSpecularLighting, inout float totalIblWeight)
{
// IBL weights should not exceed 1.
float accumulatedWeight = totalIblWeight + weight.y;
totalIblWeight = saturate(accumulatedWeight);
weight.y -= saturate(accumulatedWeight - totalIblWeight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x);
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, PositionInputs posInput, PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, uint featureFlags,
out float3 diffuseLighting,

context.sampleReflection = 0;
context.shadowContext = InitShadowContext();
// This struct is use to store accumulated lighting, summation is done in PostEvaluateBSDF
LightLoopAccumulatedLighting accLighting;
ZERO_INITIALIZE(LightLoopAccumulatedLighting, accLighting);
// This struct is define in the material. the Lightloop must not access it
// PostEvaluateBSDF call at the end will convert Lighting to diffuse and specular lighting
AggregateLighting aggregateLighting;
ZERO_INITIALIZE(AggregateLighting, aggregateLighting); // LightLoop is in charge of initializing the struct
uint i = 0; // Declare once to avoid the D3D11 compiler warning.

{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional(context, V, posInput, preLightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
accLighting.dirDiffuseLighting += localDiffuseLighting;
accLighting.dirSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Directional(context, V, posInput, preLightData, _DirectionalLightDatas[i], bsdfData);
AccumulateDirectLighting(lighting, aggregateLighting);
}
}

for (i = 0; i < punctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, posInput, preLightData, _LightDatas[punctualIndex], bsdfData, _LightDatas[punctualIndex].lightType,
localDiffuseLighting, localSpecularLighting);
accLighting.punctualDiffuseLighting += localDiffuseLighting;
accLighting.punctualSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[punctualIndex], bsdfData, _LightDatas[punctualIndex].lightType);
AccumulateDirectLighting(lighting, aggregateLighting);
}
#else

float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, posInput, preLightData, _LightDatas[i], bsdfData, _LightDatas[i].lightType,
localDiffuseLighting, localSpecularLighting);
accLighting.punctualDiffuseLighting += localDiffuseLighting;
accLighting.punctualSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[i], bsdfData, _LightDatas[i].lightType);
AccumulateDirectLighting(lighting, aggregateLighting);
}
#endif

while (i < areaLightCount && lightType == GPULIGHTTYPE_LINE)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Area( context, V, posInput, preLightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_LINE,
localDiffuseLighting, localSpecularLighting);
accLighting.areaDiffuseLighting += localDiffuseLighting;
accLighting.areaSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Area(context, V, posInput, preLightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_LINE);
AccumulateDirectLighting(lighting, aggregateLighting);
i++;
areaIndex = i < areaLightCount ? FetchIndex(areaLightStart, i) : 0;
lightType = i < areaLightCount ? _LightDatas[areaIndex].lightType : 0xFF;

{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Area( context, V, posInput, preLightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_RECTANGLE,
localDiffuseLighting, localSpecularLighting);
accLighting.areaDiffuseLighting += localDiffuseLighting;
accLighting.areaSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Area(context, V, posInput, preLightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_RECTANGLE);
AccumulateDirectLighting(lighting, aggregateLighting);
i++;
areaIndex = i < areaLightCount ? FetchIndex(areaLightStart, i) : 0;

#else
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Area( context, V, posInput, preLightData, _LightDatas[i], bsdfData, _LightDatas[i].lightType,
localDiffuseLighting, localSpecularLighting);
accLighting.areaDiffuseLighting += localDiffuseLighting;
accLighting.areaSpecularLighting += localSpecularLighting;
DirectLighting lighting = EvaluateBSDF_Area(context, V, posInput, preLightData, _LightDatas[i], bsdfData, _LightDatas[i].lightType);
AccumulateDirectLighting(lighting, aggregateLighting);
float totalIblWeight = 0.0; // Max: 1
float reflectionHierarchyWeight = 0.0; // Max: 1.0
float refractionHierarchyWeight = 0.0; // Max: 1.0
if (featureFlags & LIGHTFEATUREFLAGS_SSL)
if (featureFlags & LIGHTFEATUREFLAGS_SSREFRACTION)
{
IndirectLighting lighting = EvaluateBSDF_SSRefraction(context, V, posInput, preLightData, bsdfData, refractionHierarchyWeight);
AccumulateIndirectLighting(lighting, aggregateLighting);
}
if (featureFlags & LIGHTFEATUREFLAGS_SSREFLECTION)
// SSR and rough refraction
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
EvaluateBSDF_SSL(V, posInput, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
applyWeigthedIblLighting(localDiffuseLighting, localSpecularLighting, weight, accLighting.envDiffuseLighting, accLighting.envSpecularLighting, totalIblWeight);
accLighting.envDiffuseLightingWeight = weight.x;
IndirectLighting lighting = EvaluateBSDF_SSReflection(context, V, posInput, preLightData, bsdfData, reflectionHierarchyWeight);
AccumulateIndirectLighting(lighting, aggregateLighting);
}
if (featureFlags & LIGHTFEATUREFLAGS_ENV || featureFlags & LIGHTFEATUREFLAGS_SKY)

{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
#ifdef LIGHTLOOP_TILE_PASS

#endif
// Note: In case of IBL we are sorted from smaller to bigger projected solid angle bounds. We are not sorted by type so we can't do a 'while' approach like for area light.
for (i = 0; i < envLightCount && totalIblWeight < 1.0; ++i)
for (i = 0; i < envLightCount && reflectionHierarchyWeight < 1.0; ++i)
{
#ifdef LIGHTLOOP_TILE_PASS
uint envLightIndex = FetchIndex(envLightStart, i);

EvaluateBSDF_Env(context, V, posInput, preLightData, _EnvLightDatas[envLightIndex], bsdfData, _EnvLightDatas[envLightIndex].envShapeType, localDiffuseLighting, localSpecularLighting, weight);
applyWeigthedIblLighting(localDiffuseLighting, localSpecularLighting, weight, accLighting.envDiffuseLighting, accLighting.envSpecularLighting, totalIblWeight);
IndirectLighting lighting = EvaluateBSDF_Env(context, V, posInput, preLightData, _EnvLightDatas[envLightIndex], bsdfData, _EnvLightDatas[envLightIndex].envShapeType,
reflectionHierarchyWeight);
AccumulateIndirectLighting(lighting, aggregateLighting);
}
}

if (_EnvLightSkyEnabled && totalIblWeight < 1.0)
if (_EnvLightSkyEnabled && reflectionHierarchyWeight < 1.0)
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
EvaluateBSDF_Env(context, V, posInput, preLightData, envLightSky, bsdfData, ENVSHAPETYPE_SKY, localDiffuseLighting, localSpecularLighting, weight);
applyWeigthedIblLighting(localDiffuseLighting, localSpecularLighting, weight, accLighting.envDiffuseLighting, accLighting.envSpecularLighting, totalIblWeight);
IndirectLighting lighting = EvaluateBSDF_Env(context, V, posInput, preLightData, envLightSky, bsdfData, ENVSHAPETYPE_SKY, reflectionHierarchyWeight);
AccumulateIndirectLighting(lighting, aggregateLighting);
}
}
}

PostEvaluateBSDF( context, V, posInput, preLightData, accLighting, bsdfData, bakeDiffuseLighting,
PostEvaluateBSDF( context, V, posInput, preLightData, bsdfData, bakeDiffuseLighting, aggregateLighting,
diffuseLighting, specularLighting);
ApplyDebug(context, posInput.positionWS, diffuseLighting, specularLighting);

323
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


/* 2 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 4 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 5 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 5 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_STANDARD,
// SSS
/* 6 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SSS,

/* 10 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_SSS,
/* 10 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_SSS,
// Aniso
/* 11 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_ANISO,

/* 15 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 15 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_ANISO,
// With foliage or crowd with SSS and standard can overlap a lot, better to have a dedicated combination
/* 16 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,

/* 20 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 20 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
// ClearCoat
/* 21 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,

/* 25 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 25 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIALFEATUREFLAGS_LIT_CLEAR_COAT,
/* 26 */ LIGHT_FEATURE_MASK_FLAGS | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
/* 26 */ LIGHT_FEATURE_MASK_FLAGS_OPAQUE | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
};
uint FeatureFlagsToTileVariant(uint featureFlags)

// We deem the intensity difference of a couple of percent for high values of roughness
// to not be worth the cost of another precomputed table.
// Note: this formulation bakes the BSDF non-symmetric!
preLightData.energyCompensation = 1 / reflectivity - 1;
preLightData.energyCompensation = 1.0 / reflectivity - 1.0;
preLightData.energyCompensation = 0;
preLightData.energyCompensation = 0.0;
#endif // LIT_USE_GGX_ENERGY_COMPENSATION
// Area light

#ifdef HAS_LIGHTLOOP
//-----------------------------------------------------------------------------
// Lighting structure for light accumulation
//-----------------------------------------------------------------------------
// These structure allow to accumulate lighting accross the Lit material
// AggregateLighting is init to zero and transfer to EvaluateBSDF, but the LightLoop can't access its content.
struct DirectLighting
{
float3 diffuse;
float3 specular;
};
struct IndirectLighting
{
float3 specularReflected;
float3 specularTransmitted;
};
struct AggregateLighting
{
DirectLighting direct;
IndirectLighting indirect;
};
void AccumulateDirectLighting(DirectLighting src, inout AggregateLighting dst)
{
dst.direct.diffuse += src.diffuse;
dst.direct.specular += src.specular;
}
void AccumulateIndirectLighting(IndirectLighting src, inout AggregateLighting dst)
{
dst.indirect.specularReflected += src.specularReflected;
dst.indirect.specularTransmitted += src.specularTransmitted;
}
//-----------------------------------------------------------------------------
// BSDF share between directional light, punctual light and area light (reference)
//-----------------------------------------------------------------------------

}
else
{
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1;
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1.0 - positionLS.z) <= 1.0;
}
// We let the sampler handle tiling or clamping to border.

cookie.a = isInBounds ? cookie.a : 0;
cookie.a = isInBounds ? cookie.a : 0.0;
void EvaluateBSDF_Directional(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
DirectLighting EvaluateBSDF_Directional( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 positionWS = posInput.positionWS;
float3 L = -lightData.forward; // Lights are pointing backward in Unity

diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float shadow = 1;
float shadow = 1.0;
[branch] if (lightData.shadowIndex >= 0)
{

[branch] if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);
diffuseLighting *= illuminance * lightData.diffuseScale;
specularLighting *= illuminance * lightData.specularScale;
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)

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);
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
}
//-----------------------------------------------------------------------------

return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
}
void EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType,
out float3 diffuseLighting,
out float3 specularLighting)
DirectLighting EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 positionWS = posInput.positionWS;
int lightType = GPULightType;

lightData.diffuseScale *= attenuation;
lightData.specularScale *= attenuation;
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float shadow = 1;
float shadow = 1.0;
[branch] if (lightData.shadowIndex >= 0)
{

[branch] if (illuminance > 0.0)
{
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual ligth have a radius with this hack
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual light have a radius with this hack
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);
diffuseLighting *= illuminance * lightData.diffuseScale;
specularLighting *= illuminance * lightData.specularScale;
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
}
[branch] if (bsdfData.enableTransmission)

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);
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
}
#include "LitReference.hlsl"

//-----------------------------------------------------------------------------
void EvaluateBSDF_Line(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Line( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
diffuseLighting, specularLighting);
lighting.diffuse, lighting.specular);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float len = lightData.size.x;
float3 T = lightData.right;

axis, invAspectRatio);
// Terminate if the shaded point is too far away.
if (intensity == 0.0) return;
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;
lightData.specularScale *= intensity;

{
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse);
ltcValue *= lightData.diffuseScale;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
[branch] if (bsdfData.enableTransmission)

ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1);
}
// Evaluate the coat part

{
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformSpecular);
ltcValue *= lightData.specularScale;
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue;
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue;
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
}
//-----------------------------------------------------------------------------

// #define ELLIPSOIDAL_ATTENUATION
void EvaluateBSDF_Rect( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Rect( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
diffuseLighting, specularLighting);
lighting.diffuse, lighting.specular);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float3 unL = lightData.positionWS - positionWS;
[branch]

return;
return lighting;
}
// Rotate the light direction into the light space.

#endif
// Terminate if the shaded point is too far away.
if (intensity == 0.0) return;
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;
lightData.specularScale *= intensity;

// Polygon irradiance in the transformed configuration.
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse));
ltcValue *= lightData.diffuseScale;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
[branch] if (bsdfData.enableTransmission)

ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1);
}
// Evaluate the coat part

// ltcValue = LTCEvaluate(lightVerts, V, bsdfData.coatNormalWS, preLightData.coatNdotV, preLightData.ltcXformClearCoat);
// specularLighting = preLightData.ltcClearCoatFresnelTerm * (ltcValue * bsdfData.coatCoverage);
// lighting.specular = preLightData.ltcClearCoatFresnelTerm * (ltcValue * bsdfData.coatCoverage);
// modify matL value based on Fresnel transmission
// matL = mul(matL, preLightData.ltcCoatT);

// Polygon irradiance in the transformed configuration.
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular));
ltcValue *= lightData.specularScale;
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue;
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue;
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
void EvaluateBSDF_Area( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Area( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType)
EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData);
EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData);
// EvaluateBSDF_SSL
// EvaluateBSDF_SSLighting for screen space lighting
void EvaluateBSDF_SSL(float3 V, PositionInputs posInput, BSDFData bsdfData, out float3 diffuseLighting, out float3 specularLighting, out float2 weight)
IndirectLighting EvaluateBSDF_SSReflection(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, BSDFData bsdfData,
inout float hierarchyWeight)
{
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
// TODO
return lighting;
}
IndirectLighting EvaluateBSDF_SSRefraction(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, BSDFData bsdfData,
inout float hierarchyWeight)
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
weight = float2(0.0, 0.0);
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
// 3. If this point is available (ie: in color GBuffer and point is not in front of the object)
// 3. If this point is available (ie: in color buffer and point is not in front of the object)
weight.x = bsdfData.transmittanceMask;
float3 refractedBackPointWS = float3(0.0, 0.0, 0.0);
float opticalDepth = 0.0;

// we approximate the scene as a plane (back plane) with normal -V at the depth hit point.
// (We avoid to raymarch the depth texture to get the refracted point.)
#if defined(_REFRACTION_PLANE)
// Plane shape model:
// We approximate locally the shape of the object as a plane with normal {bsdfData.normalWS} at {bsdfData.positionWS}
// with a thickness {bsdfData.thickness}
// Plane shape model:
// We approximate locally the shape of the object as a plane with normal {bsdfData.normalWS} at {bsdfData.positionWS}
// with a thickness {bsdfData.thickness}
// Refracted ray
// Refracted ray
// Get the depth of the approximated back plane
// Get the depth of the approximated back plane
// Distance from point to the back plane
// Distance from point to the back plane
// Optical depth within the thin plane
// Optical depth within the thin plane
// The refracted ray exiting the thin plane is the same as the incident ray (parallel interfaces and same ior)
// The refracted ray exiting the thin plane is the same as the incident ray (parallel interfaces and same ior)
float VoR = dot(-V, R);
float VoN = dot(V, bsdfData.normalWS);
refractedBackPointWS = posInput.positionWS + R * opticalDepth - V * (distFromP - VoR * opticalDepth);

|| any(refractedBackPointSS < 0.0)
|| any(refractedBackPointSS > 1.0))
{
diffuseLighting = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, posInput.positionSS, 0.0).rgb;
return;
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, posInput.positionSS, 0.0).rgb;
// TODO: check with fred. If a pixel is in front of the object we should not sample at all and put hierarchyWeight to 1.0 so we discard the effect as it is occlusion
// Otherwise fallback on cubemap
return lighting;
diffuseLighting = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb;
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb;
diffuseLighting *= transmittance;
#endif // HAS_REFRACTION
lighting.specularTransmitted *= transmittance;
float weight = 1.0;
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hiearchy priority
lighting.specularTransmitted *= weight;
#else
// No refraction, no need to go further
hierarchyWeight = 1.0;
#endif
return lighting;
}
//-----------------------------------------------------------------------------

// _preIntegratedFGD and _CubemapLD are unique for each BRDF
void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType,
out float3 diffuseLighting, out float3 specularLighting, out float2 weight)
IndirectLighting EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType,
inout float hierarchyWeight)
weight = float2(0.0, 1.0);
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
float weight = 1.0;
specularLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
lighting.specularReflected = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
diffuseLighting = IntegrateLambertIBLRef(lightData, V, bsdfData);
lighting.directDiffuse += IntegrateLambertIBLRef(lightData, V, bsdfData);
diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
lighting.directDiffuse += IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
diffuseLighting = float3(0.0, 0.0, 0.0);
hierarchyWeight = 0.0;
#else

// 2. Process the influence
float distFade = max(length(positionLS) - lightData.innerDistance.x, 0.0);
weight.y = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
}
else if (envShapeType == ENVSHAPETYPE_BOX)
{

// Influence volume
// 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.y = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
weight.y = Smoothstep01(weight.y);
weight = Smoothstep01(weight);
specularLighting = float3(0.0, 0.0, 0.0);
// Evaluate the Clear Coat component if needed and change the BSDF roughness to match Fresnel transmission
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))

// Evaluate the Clear Coat color
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, coatR, 0.0);
specularLighting += F * preLD.rgb * bsdfData.coatCoverage;
lighting.specularReflected += F * preLD.rgb * bsdfData.coatCoverage;
// Change the Fresnel term to account for transmission through Clear Coat and reflection on the base layer.
F = Sqr(-F * bsdfData.coatCoverage + 1.0);

specularLighting += F * preLD.rgb * preLightData.specularFGD;
lighting.specularReflected += F * preLD.rgb * preLightData.specularFGD;
diffuseLighting = float3(0.0, 0.0, 0.0);
#endif
#endif
UpdateLightingHierarchyWeights(hierarchyWeight, weight);
lighting.specularReflected *= weight;
return lighting;
}
//-----------------------------------------------------------------------------

void PostEvaluateBSDF( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightLoopAccumulatedLighting accLighting, BSDFData bsdfData, float3 bakeDiffuseLighting,
PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, AggregateLighting lighting,
out float3 diffuseLighting, out float3 specularLighting)
{
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the baseColor)

// Try to mimic multibounce with specular color. Not the point of the original formula but ok result.
// Take the min of screenspace specular occlusion and visibility cone specular occlusion
#if GTAO_MULTIBOUNCE_APPROX
accLighting.envSpecularLighting *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0);
lighting.indirect.specularReflected *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0);
accLighting.envSpecularLighting *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion));
lighting.indirect.specularReflected *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion));
float3 directDiffuseLighting = (accLighting.dirDiffuseLighting + accLighting.punctualDiffuseLighting + accLighting.areaDiffuseLighting)
lighting.direct.diffuse *=
* GTAOMultiBounce(directAmbientOcclusion, bsdfData.diffuseColor);
GTAOMultiBounce(directAmbientOcclusion, bsdfData.diffuseColor);
* lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), directAmbientOcclusion);
lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), directAmbientOcclusion);
#endif
diffuseLighting = lighting.direct.diffuse + bakeDiffuseLighting;
// If refraction is enable we use the transmittanceMask to lerp between current diffuse lighting and refraction value
// Physically speaking, it should be transmittanceMask should be 1, but for artistic reasons, we let the value vary
#if HAS_REFRACTION
diffuseLighting = lerp(diffuseLighting, lighting.indirect.specularTransmitted, bsdfData.transmittanceMask);
// envDiffuseLighting is used for refraction in this Lit material. Use the weight to balance between transmission and reflection
diffuseLighting = lerp(directDiffuseLighting + bakeDiffuseLighting, accLighting.envDiffuseLighting, accLighting.envDiffuseLightingWeight);
specularLighting = accLighting.dirSpecularLighting + accLighting.punctualSpecularLighting + accLighting.areaSpecularLighting + accLighting.envSpecularLighting;
specularLighting = lighting.direct.specular + lighting.indirect.specularReflected;
specularLighting *= 1 + bsdfData.fresnel0 * preLightData.energyCompensation;
specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation;
#ifdef DEBUG_DISPLAY
if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO)

#endif
#endif
}
#endif // #ifdef HAS_LIGHTLOOP

32
ScriptableRenderPipeline/HDRenderPipeline/Material/Material.hlsl


return result;
}
//-----------------------------------------------------------------------------
// Alpha test replacement
//-----------------------------------------------------------------------------
// This function must be use instead of clip instruction. It allow to manage in which case the clip is perform
void DoAlphaTest(float alpha, float alphaCutoff)
{
// For Deferred:
// If we have a prepass, we need to remove the clip from the GBuffer pass (otherwise HiZ does not work on PS4) - SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
// For Forward (Lit or Unlit)
// Opaque geometry always has a depth pre-pass so we never want to do the clip here. For transparent we perform the clip as usual.
// Also no alpha test for light transport
#if !(SHADERPASS == SHADERPASS_FORWARD && !defined(_SURFACE_TYPE_TRANSPARENT)) && !(SHADERPASS == SHADERPASS_FORWARD_UNLIT && !defined(_SURFACE_TYPE_TRANSPARENT)) && !defined(SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST) && !(SHADERPASS == SHADERPASS_LIGHT_TRANSPORT)
clip(alpha - alphaCutoff);
#endif
}
//-----------------------------------------------------------------------------
// Reflection / Refraction hierarchy handling
//-----------------------------------------------------------------------------
// This function is use with reflection and refraction hierarchy of LightLoop
// It will add weight to hierarchyWeight but ensure that hierarchyWeight is not more than one
// by updating the weight value. Returned weight value must be apply on current lighting
// Example: Total hierarchyWeight is 0.8 and weight is 0.4. Function return hierarchyWeight of 1.0 and weight of 0.2
// hierarchyWeight and weight must be positive and between 0 and 1
void UpdateLightingHierarchyWeights(inout float hierarchyWeight, inout float weight)
{
float accumulatedWeight = hierarchyWeight + weight;
hierarchyWeight = saturate(accumulatedWeight);
weight -= saturate(accumulatedWeight - hierarchyWeight);
}
//-----------------------------------------------------------------------------
// BuiltinData

13
ScriptableRenderPipeline/HDRenderPipeline/Material/MaterialUtilities.hlsl


#endif
}
// This function must be use instead of clip instruction. It allow to manage in which case the clip is perform
void DoAlphaTest(float alpha, float alphaCutoff)
{
// For Deferred:
// If we have a prepass, we need to remove the clip from the GBuffer pass (otherwise HiZ does not work on PS4) - SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST
// For Forward (Lit or Unlit)
// Opaque geometry always has a depth pre-pass so we never want to do the clip here. For transparent we perform the clip as usual.
// Also no alpha test for light transport
#if !(SHADERPASS == SHADERPASS_FORWARD && !defined(_SURFACE_TYPE_TRANSPARENT)) && !(SHADERPASS == SHADERPASS_FORWARD_UNLIT && !defined(_SURFACE_TYPE_TRANSPARENT)) && !defined(SHADERPASS_GBUFFER_BYPASS_ALPHA_TEST) && !(SHADERPASS == SHADERPASS_LIGHT_TRANSPORT)
clip(alpha - alphaCutoff);
#endif
}
float2 CalculateVelocity(float4 positionCS, float4 previousPositionCS)
{
// This test on define is required to remove warning of divide by 0 when initializing empty struct

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Unlit/UnlitData.hlsl


#include "../MaterialUtilities.hlsl"
//-------------------------------------------------------------------------------------
// Fill SurfaceData/Builtin data function
//-------------------------------------------------------------------------------------

6
ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


if (_DebugLightingMode != DEBUGLIGHTINGMODE_NONE)
#endif
{
uint featureFlags = 0xFFFFFFFF;
#ifdef _SURFACE_TYPE_TRANSPARENT
uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_TRANSPARENT;
#else
uint featureFlags = LIGHT_FEATURE_MASK_FLAGS_OPAQUE;
#endif
float3 diffuseLighting;
float3 specularLighting;
float3 bakeDiffuseLighting = GetBakedDiffuseLigthing(surfaceData, builtinData, bsdfData, preLightData);

正在加载...
取消
保存