UNREAL移动端LightMap自定义优化修改(六)
LightMap数据及文件自定义优化处理LightMap文件的自定义生成
这一步其实很简单,但是如果有时间做的更完善的话可以在BakeLightMap WorldSettings中增加自定义配置选项,以更加灵活的在移动端生成自己想要的数据。
首先定位到:LightMap.cpp
UnrealEngine\Engine\Source\Runtime\Engine\Private\LightMap.cpp
void FLightMapPendingTexture::CreateUObjects()
{
...
if (bIncludeNonVirtualTextures)
{...}
...
}
我们定位到此Function可以看到有VT和不带VT的两种处理方式,我们目前只看不带VT的处理方式。if(bIncludeNonVirtualTextures){...}这里主要有SkyOcclusionTexture,AOMaterialMaskTexture,ShadowMapTexture,Textures.几个部分要处理。在移动端可以根据项目需求自己去灵配置调整自己的需求,比如有的项目就把ShadowMap和LightTextures整合到一起,LightTextures上半部分是LightMapColor,下半部分是Shadow等等。
if (bIncludeNonVirtualTextures)
{
if (NeedsSkyOcclusionTexture())
{
SkyOcclusionTexture = NewObject<ULightMapTexture2D>(Outer, GetSkyOcclusionTextureName(GLightmapCounter));
}
if (NeedsAOMaterialMaskTexture())
{
AOMaterialMaskTexture = NewObject<ULightMapTexture2D>(Outer, GetAOMaterialMaskTextureName(GLightmapCounter));
}
if (NeedsStaticShadowTexture())
{
ShadowMapTexture = NewObject<UShadowMapTexture2D>(Outer, GetShadowTextureName(GLightmapCounter));
}
//以上三项,可以自己配置到WorldSettings面板里加自定义参数,或者直接在对应方法里返回T o F.
//返回F的直接就不生成了,就很简单。
// Encode and compress the coefficient textures.
for (uint32 CoefficientIndex = 0; CoefficientIndex < NUM_STORED_LIGHTMAP_COEF; CoefficientIndex += 2)
{
Textures = nullptr;
// Skip generating simple lightmaps if wanted.
static const auto CVarSupportLowQualityLightmaps = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT(&#34;r.SupportLowQualityLightmaps&#34;));
const bool bAllowLowQualityLightMaps = (!CVarSupportLowQualityLightmaps) || (CVarSupportLowQualityLightmaps->GetValueOnAnyThread() != 0);
if ((!bAllowLowQualityLightMaps) && CoefficientIndex >= LQ_LIGHTMAP_COEF_INDEX)
{
continue;
}
// Create the light-map texture for this coefficient.
if (CoefficientIndex >= NUM_HQ_LIGHTMAP_COEF) {
auto Texture = NewObject<ULightMapTexture2D>(Outer, GetLightmapName(GLightmapCounter, CoefficientIndex));
Textures = Texture;
//LQ的LightMap在此~~
}
else
{
//HQ的在此,也可以通过配置~
}
}
}
接下来定位到:EncodeCoefficientTexture()
void FLightMapPendingTexture::EncodeCoefficientTexture(int32 CoefficientIndex, UTexture* Texture, uint32 LayerIndex, const FColor& TextureColor, bool bEncodeVirtualTexture)
{
...
}
这和Function就是主要是编码LightMap的地方,UE默认的情况下会把LightMap上半部分编码为LightMapColor,下半部分编码为LightMapDirectionality。材质面板中可以配置这个材质是否使用LightMapDirectionality。如果不需要的话我们可以把这部分对应的shader一并优化一下。
接下来我们开始捋一捋EncodeCoefficientTexture()的代码。
代码段首先是定义基础文件格式,如果你不用Alpha通道,则CompressionNoAlpha =true;
我们现在是用了A通道,所以是FALSE,现在A通道写全局AO的,当然你也可以放到下半部分,都可以,增加一次采样,节省了空间。
LightMap格式以及AO等都不是SRGB的要注意一下。所以SRGB是FALSE。
这里面也有处理VT的部分,我们针对移动端的部分目前暂不考虑VT的部分。如果你需要用下半部分mipData1,MipCoverageData1就保留。
// Lock all mip levels.
FColor* MipData0 = { 0 };
//FColor* MipData1 = { 0 };
int8* MipCoverageData0 = { 0 };
//int8* MipCoverageData1 = { 0 };
{
const int32 StartBottom = GetSizeX() * GetSizeY();
for (int32 MipIndex = 0; MipIndex < NumMips; ++MipIndex)
{
const int32 MipSizeX = FMath::Max(1, TextureSizeX >> MipIndex);
const int32 MipSizeY = FMath::Max(1, TextureSizeY >> MipIndex);
MipData0 = (FColor*)Texture->Source.LockMip(0, LayerIndex, MipIndex);
MipCoverageData0 = (int8*)FMemory::Malloc(MipSizeX * MipSizeY);
/*if (bEncodeVirtualTexture)
{
// 2 coefficients are stored on adjacent VT layers
MipData1 = (FColor*)Texture->Source.LockMip(0, LayerIndex + 1, MipIndex);
MipCoverageData1 = (int8*)FMemory::Malloc(MipSizeX * MipSizeY);
}
else
{
// 2 coefficients are stored on the top/bottom halves of the same destination texture
MipData1 = MipData0 + StartBottom;
MipCoverageData1 = MipCoverageData0 + StartBottom;
}*/
}
}
接下来看RGBA通道写数据的部分,A通道写入AO,注掉了下半部分的内容。当然你也可以把下半部分写入其他内容。但是。每调整一个小地方,对应的整体很多地方都要做相应的调整,UV,Shader部分等等。。。
for (int32 Y = Allocation->MappedRect.Min.Y; Y < Allocation->MappedRect.Max.Y; ++Y)
{
for (int32 X = Allocation->MappedRect.Min.X; X < Allocation->MappedRect.Max.X; ++X)
{
const FLightMapCoefficients& SourceCoefficients = Allocation->RawData;
int32 DestY = Y - Allocation->MappedRect.Min.Y + Allocation->OffsetY;
int32 DestX = X - Allocation->MappedRect.Min.X + Allocation->OffsetX;
FColor& DestColor = MipData0;
int8& DestCoverage = MipCoverageData0;
// modify by zhoujie remove dirLightNormal;
//FColor& DestBottomColor = MipData1;
// int8& DestBottomCoverage = MipCoverageData1;
#if VISUALIZE_PACKING
if (X == Allocation->MappedRect.Min.X || Y == Allocation->MappedRect.Min.Y ||
X == Allocation->MappedRect.Max.X - 1 || Y == Allocation->MappedRect.Max.Y - 1 ||
X == Allocation->MappedRect.Min.X + 1 || Y == Allocation->MappedRect.Min.Y + 1 ||
X == Allocation->MappedRect.Max.X - 2 || Y == Allocation->MappedRect.Max.Y - 2)
{
DestColor = FColor::Red;
}
else
{
DestColor = FColor::Green;
}
#else // VISUALIZE_PACKING
//RGBA通道编码在这里,A通道写入了AOMaterialMask。
DestColor.R = SourceCoefficients.Coefficients;
DestColor.G = SourceCoefficients.Coefficients;
DestColor.B = SourceCoefficients.Coefficients;
DestColor.A = SourceCoefficients.AOMaterialMask;
//下半部分内容清理,当然你可以写入你想要的其他内容。
// DestBottomColor.R = SourceCoefficients.Coefficients;
// DestBottomColor.G = SourceCoefficients.Coefficients;
// DestBottomColor.B = SourceCoefficients.Coefficients;
// DestBottomColor.A = SourceCoefficients.Coefficients;
if (GVisualizeLightmapTextures)
{
DestColor = TextureColor;
}
// uint8 -> int8
//DestCoverage = DestBottomCoverage = SourceCoefficients.Coverage / 2;
DestCoverage = SourceCoefficients.Coverage / 2;
if (SourceCoefficients.Coverage > 0)
{
NumLightmapMappedTexels++;
}
else
{
NumLightmapUnmappedTexels++;
}
以上就是几个LightMap处理的关键的点。
最后LightMap.cpp里红框的几个Function可以多读读。
最后大家要怎么玩(′‵) 看融汇能力咯~
最后插入之前发布的视频。
后续会将怎么自定义天光的参数,通过自定义的天光参数调整全局的LightMap GI和AO以及ILC等部分。 6666沙发,很棒的分享。 [爱]大佬~双节快乐哦~[调皮] [爱心] 6666 正好也在优化Lightmap占用的问题,感谢分享
[欢呼] “可以在BakeLightMap WorldSettings中增加自定义配置选项”,因为这些配置修改后要重编材质的,所以只能放在项目设置里面吧,然后修改后强制重启引擎重编材质
页:
[1]