Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Enlighten's RGB directional lightmaps. #12

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions BakingLab/AppSettings.cpp
Expand Up @@ -161,10 +161,11 @@ static const char* SampleModesLabels[5] =
"CMJ",
};

static const char* BakeModesLabels[11] =
static const char* BakeModesLabels[12] =
{
"Diffuse",
"Directional",
"DirectionalRGB",
"Half-Life 2",
"L1 SH",
"L2 SH",
Expand Down Expand Up @@ -526,7 +527,7 @@ namespace AppSettings
BakeRussianRouletteProbability.Initialize(tweakBar, "BakeRussianRouletteProbability", "Baking", "Russian Roullette Probability", "Maximum probability for continuing when Russian roulette is used", 0.5000f, 0.0000f, 1.0000f, 0.0100f, ConversionMode::None, 1.0000f);
Settings.AddSetting(&BakeRussianRouletteProbability);

BakeMode.Initialize(tweakBar, "BakeMode", "Baking", "Bake Mode", "The current encoding/basis used for baking light map sample points", BakeModes::SG5, 11, BakeModesLabels);
BakeMode.Initialize(tweakBar, "BakeMode", "Baking", "Bake Mode", "The current encoding/basis used for baking light map sample points", BakeModes::SG5, 12, BakeModesLabels);
Settings.AddSetting(&BakeMode);

SolveMode.Initialize(tweakBar, "SolveMode", "Baking", "Solve Mode", "Controls how path tracer radiance samples are converted into a set of per-texel SG lobes", SolveModes::RunningAverageNN, 5, SolveModesLabels);
Expand Down
3 changes: 3 additions & 0 deletions BakingLab/AppSettings.cs
Expand Up @@ -261,6 +261,9 @@ enum BakeModes
[EnumLabel("Directional")]
Directional,

[EnumLabel("DirectionalRGB")]
DirectionalRGB,

[EnumLabel("Half-Life 2")]
HL2,

Expand Down
23 changes: 12 additions & 11 deletions BakingLab/AppSettings.h
Expand Up @@ -231,15 +231,16 @@ enum class BakeModes
{
Diffuse = 0,
Directional = 1,
HL2 = 2,
SH4 = 3,
SH9 = 4,
H4 = 5,
H6 = 6,
SG5 = 7,
SG6 = 8,
SG9 = 9,
SG12 = 10,
DirectionalRGB = 2,
HL2 = 3,
SH4 = 4,
SH9 = 5,
H4 = 6,
H6 = 7,
SG5 = 8,
SG6 = 9,
SG9 = 10,
SG12 = 11,

NumValues
};
Expand Down Expand Up @@ -596,7 +597,7 @@ namespace AppSettings
inline uint64 BasisCount(uint64 bakeMode)
{
Assert_(bakeMode < uint64(BakeModes::NumValues));
static const uint64 BasisCounts[] = { 1, 2, 3, 4, 9, 4, 6, 5, 6, 9, 12 };
static const uint64 BasisCounts[] = { 1, 2, 4, 3, 4, 9, 4, 6, 5, 6, 9, 12 };
StaticAssert_(ArraySize_(BasisCounts) == uint64(BakeModes::NumValues));
Assert_(BasisCounts[bakeMode] <= MaxBasisCount);
return BasisCounts[bakeMode];
Expand Down Expand Up @@ -628,7 +629,7 @@ namespace AppSettings

inline bool SupportsProgressiveIntegration(BakeModes bakeMode, SolveModes solveMode)
{
if((bakeMode == BakeModes::Directional) || (SGCount(bakeMode) > 0 && (solveMode == SolveModes::SVD || solveMode == SolveModes::NNLS)))
if((bakeMode == BakeModes::Directional) || (bakeMode == BakeModes::DirectionalRGB) || (SGCount(bakeMode) > 0 && (solveMode == SolveModes::SVD || solveMode == SolveModes::NNLS)))
return false;
else
return true;
Expand Down
19 changes: 10 additions & 9 deletions BakingLab/AppSettings.hlsl
Expand Up @@ -181,15 +181,16 @@ static const int SampleModes_CMJ = 4;

static const int BakeModes_Diffuse = 0;
static const int BakeModes_Directional = 1;
static const int BakeModes_HL2 = 2;
static const int BakeModes_SH4 = 3;
static const int BakeModes_SH9 = 4;
static const int BakeModes_H4 = 5;
static const int BakeModes_H6 = 6;
static const int BakeModes_SG5 = 7;
static const int BakeModes_SG6 = 8;
static const int BakeModes_SG9 = 9;
static const int BakeModes_SG12 = 10;
static const int BakeModes_DirectionalRGB = 2;
static const int BakeModes_HL2 = 3;
static const int BakeModes_SH4 = 4;
static const int BakeModes_SH9 = 5;
static const int BakeModes_H4 = 6;
static const int BakeModes_H6 = 7;
static const int BakeModes_SG5 = 8;
static const int BakeModes_SG6 = 9;
static const int BakeModes_SG9 = 10;
static const int BakeModes_SG12 = 11;

static const int SolveModes_Projection = 0;
static const int SolveModes_SVD = 1;
Expand Down
22 changes: 21 additions & 1 deletion BakingLab/BakeDataVisualizer.hlsl
Expand Up @@ -132,7 +132,7 @@ float4 PS(in PSInput input) : SV_Target0
}
else if (BakeMode == BakeModes_Directional)
{
float3 lightMapColor = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 0), 0.0f).xyz * Pi;
float3 lightMapColor = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 0), 0.0f).xyz;
float4 lightmapDirection = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 1), 0.0f).xyzw;

float rebalancingCoefficient = max(lightmapDirection.w, 0.0001);
Expand All @@ -142,6 +142,26 @@ float4 PS(in PSInput input) : SV_Target0
float4 tau = float4(normalize(normalWS), 1.0f) * 0.5f;
float halfLambert = dot(tau, float4(lightmapDirection.xyz, 1.0f));

output = lightMapColor * halfLambert / rebalancingCoefficient;
}
else if (BakeMode == BakeModes_DirectionalRGB)
{
float3 lightMapColor = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 0), 0.0f).xyz;
float4 lightmapDirectionR = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 1), 0.0f).xyzw;
float4 lightmapDirectionG = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 2), 0.0f).xyzw;
float4 lightmapDirectionB = BakedLightingMap.SampleLevel(LinearSampler, float3(uv, 3), 0.0f).xyzw;

float3 rebalancingCoefficient = float3(max(lightmapDirectionR.w, 0.0001), max(lightmapDirectionG.w, 0.0001), max(lightmapDirectionB.w, 0.0001));

lightmapDirectionR = lightmapDirectionR * 2.0f - 1.0f;
lightmapDirectionG = lightmapDirectionG * 2.0f - 1.0f;
lightmapDirectionB = lightmapDirectionB * 2.0f - 1.0f;

float4 tau = float4(normalize(normalWS), 1.0f) * 0.5f;
float3 halfLambert = float3(dot(tau, float4(lightmapDirectionR.xyz, 1.0f)),
dot(tau, float4(lightmapDirectionG.xyz, 1.0f)),
dot(tau, float4(lightmapDirectionB.xyz, 1.0f)));

output = lightMapColor * halfLambert / rebalancingCoefficient;
}
else if(BakeMode == BakeModes_SH4)
Expand Down
20 changes: 20 additions & 0 deletions BakingLab/Mesh.hlsl
Expand Up @@ -659,6 +659,26 @@ PSOutput PS(in PSInput input)

indirectIrradiance = lightMapColor * halfLambert / rebalancingCoefficient;
}
else if(BakeMode == BakeModes_DirectionalRGB)
{
float3 lightMapColor = BakedLightingMap.SampleLevel(LinearSampler, float3(input.LightMapUV, 0), 0.0f).xyz * Pi;
float4 lightmapDirectionR = BakedLightingMap.SampleLevel(LinearSampler, float3(input.LightMapUV, 1), 0.0f).xyzw;
float4 lightmapDirectionG = BakedLightingMap.SampleLevel(LinearSampler, float3(input.LightMapUV, 2), 0.0f).xyzw;
float4 lightmapDirectionB = BakedLightingMap.SampleLevel(LinearSampler, float3(input.LightMapUV, 3), 0.0f).xyzw;

float3 rebalancingCoefficient = float3(max(lightmapDirectionR.w, 0.0001), max(lightmapDirectionG.w, 0.0001), max(lightmapDirectionB.w, 0.0001));

lightmapDirectionR = lightmapDirectionR * 2.0f - 1.0f;
lightmapDirectionG = lightmapDirectionG * 2.0f - 1.0f;
lightmapDirectionB = lightmapDirectionB * 2.0f - 1.0f;

float4 tau = float4(normalize(normalWS), 1.0f) * 0.5f;
float3 halfLambert = float3(dot(tau, float4(lightmapDirectionR.xyz, 1.0f)),
dot(tau, float4(lightmapDirectionG.xyz, 1.0f)),
dot(tau, float4(lightmapDirectionB.xyz, 1.0f)));

indirectIrradiance = lightMapColor * halfLambert / rebalancingCoefficient;
}
else if(BakeMode == BakeModes_SH4)
{
SH4Color shRadiance;
Expand Down
85 changes: 81 additions & 4 deletions BakingLab/MeshBaker.cpp
Expand Up @@ -122,6 +122,7 @@ struct DirectionalBaker
uint64 NumSamples = 0;
Float3 ResultSum;
Float3 DirectionSum;
float DirectionWeightSum;
Float3 NormalSum;

void Init(uint64 numSamples, Float4 prevResult[BasisCount])
Expand All @@ -130,6 +131,7 @@ struct DirectionalBaker

ResultSum = 0.0;
DirectionSum = 0.0;
DirectionWeightSum = 0.0;
NormalSum = 0.0;
}

Expand All @@ -145,18 +147,91 @@ struct DirectionalBaker
const Float3 sampleDir = Float3::Normalize(sampleDirWS);

ResultSum += sample;
DirectionSum += sampleDir;
DirectionSum += sampleDir * ComputeLuminance(sample);
DirectionWeightSum += ComputeLuminance(sample);
NormalSum += normal;
}

void FinalResult(Float4 bakeOutput[BasisCount])
{
Float3 finalColorResult = ResultSum * CosineWeightedMonteCarloFactor(NumSamples);
Float3 finalDirection = Float3::Normalize((DirectionSum * CosineWeightedMonteCarloFactor(NumSamples)) / std::max(ComputeLuminance(finalColorResult), 0.0001f));

Float3 finalDirection = Float3::Normalize(DirectionSum / std::max(DirectionWeightSum, 0.0001f));

Float3 averageNormal = Float3::Normalize(NormalSum * CosineWeightedMonteCarloFactor(NumSamples));
Float4 tau = Float4(averageNormal, 1.0f) * 0.5f;

bakeOutput[0] = Float4(Float3::Clamp(finalColorResult, 0.0f, FP16Max), 1.0f);
bakeOutput[1] = Float4(finalDirection * 0.5f + 0.5, std::max(Float4::Dot(tau, Float4(finalDirection, 1.0f)), 0.0001f));
}

void ProgressiveResult(Float4 bakeOutput[BasisCount], uint64 passIdx)
{
}
};

// Bakes irradiance based on Enlighten's RGB directional approach, with 3 floats for
// color, and 4 floats per RGB channel were 3 of the floats are the direction for the
// specific channel and the 4th float ensures that the directional term evaluates to 1
// when the surface normal aligns with normal used when baking.
//
// Reference: https://static.docs.arm.com/100837/0308/enlighten_3-08_sdk_documentation__100837_0308_00_en.pdf
struct DirectionalRGBBaker
{
static const uint64 BasisCount = 4;

uint64 NumSamples = 0;
Float3 ResultSum;
Float3 DirectionSum[3];
Float3 DirectionWeightSum;
Float3 NormalSum;

void Init(uint64 numSamples, Float4 prevResult[BasisCount])
{
NumSamples = numSamples;

ResultSum = 0.0;
DirectionSum[0] = 0.0;
DirectionSum[1] = 0.0;
DirectionSum[2] = 0.0;
DirectionWeightSum = 0.0;
NormalSum = 0.0;
}

Float3 SampleDirection(Float2 samplePoint)
{
return SampleDirectionHemisphere(samplePoint.x, samplePoint.y);
}

void AddSample(Float3 sampleDirTS, uint64 sampleIdx, Float3 sample, Float3 sampleDirWS, Float3 normal)
{
normal = Float3::Normalize(normal);

const Float3 sampleDir = Float3::Normalize(sampleDirWS);

ResultSum += sample;
DirectionSum[0] += sampleDir * sample.x;
DirectionSum[1] += sampleDir * sample.y;
DirectionSum[2] += sampleDir * sample.z;
DirectionWeightSum += sample;
NormalSum += normal;
}

void FinalResult(Float4 bakeOutput[BasisCount])
{
Float3 finalColorResult = ResultSum * CosineWeightedMonteCarloFactor(NumSamples);

Float3 finalDirectionR = Float3::Normalize(DirectionSum[0] / std::max(DirectionWeightSum.x, 0.0001f));
Float3 finalDirectionG = Float3::Normalize(DirectionSum[1] / std::max(DirectionWeightSum.y, 0.0001f));
Float3 finalDirectionB = Float3::Normalize(DirectionSum[2] / std::max(DirectionWeightSum.z, 0.0001f));

Float3 averageNormal = Float3::Normalize(NormalSum * CosineWeightedMonteCarloFactor(NumSamples));
Float4 tau = Float4(averageNormal, 1.0f) * 0.5f;

bakeOutput[0] = Float4(Float3::Clamp(finalColorResult, 0.0f, FP16Max), 1.0f);
bakeOutput[1] = Float4(finalDirection * 0.5f + 0.5, std::max(Float4::Dot(Float4(averageNormal, 1.0f) * 0.5f, Float4(finalDirection, 1.0f)), 0.0001f));
bakeOutput[1] = Float4(finalDirectionR * 0.5f + 0.5, std::max(Float4::Dot(tau, Float4(finalDirectionR, 1.0f)), 0.0001f));
bakeOutput[2] = Float4(finalDirectionG * 0.5f + 0.5, std::max(Float4::Dot(tau, Float4(finalDirectionG, 1.0f)), 0.0001f));
bakeOutput[3] = Float4(finalDirectionB * 0.5f + 0.5, std::max(Float4::Dot(tau, Float4(finalDirectionB, 1.0f)), 0.0001f));
}

void ProgressiveResult(Float4 bakeOutput[BasisCount], uint64 passIdx)
Expand Down Expand Up @@ -1833,8 +1908,10 @@ void MeshBaker::StartBakeThreads()
uint32 (__stdcall* threadFunction)(void*) = BakeThread<DiffuseBaker>;
if(currBakeMode == BakeModes::HL2)
threadFunction = BakeThread<HL2Baker>;
if (currBakeMode == BakeModes::Directional)
else if (currBakeMode == BakeModes::Directional)
threadFunction = BakeThread<DirectionalBaker>;
else if(currBakeMode == BakeModes::DirectionalRGB)
threadFunction = BakeThread<DirectionalRGBBaker>;
else if(currBakeMode == BakeModes::SH4)
threadFunction = BakeThread<SH4Baker>;
else if(currBakeMode == BakeModes::SH9)
Expand Down