找回密码
 立即注册
查看: 657|回复: 6

UNREAL移动端LightMap自定义优化修改(六)

[复制链接]
发表于 2021-5-17 20:06 | 显示全部楼层 |阅读模式
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[CoefficientIndex] = nullptr;
                        // Skip generating simple lightmaps if wanted.
                        static const auto CVarSupportLowQualityLightmaps = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.SupportLowQualityLightmaps"));
                        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[CoefficientIndex] = 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[MAX_TEXTURE_MIP_COUNT] = { 0 };
        //FColor* MipData1[MAX_TEXTURE_MIP_COUNT] = { 0 };
        int8* MipCoverageData0[MAX_TEXTURE_MIP_COUNT] = { 0 };
        //int8* MipCoverageData1[MAX_TEXTURE_MIP_COUNT] = { 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[MipIndex] = (FColor*)Texture->Source.LockMip(0, LayerIndex, MipIndex);
                        MipCoverageData0[MipIndex] = (int8*)FMemory::Malloc(MipSizeX * MipSizeY);

                        /*if (bEncodeVirtualTexture)
                        {
                                // 2 coefficients are stored on adjacent VT layers
                                MipData1[MipIndex] = (FColor*)Texture->Source.LockMip(0, LayerIndex + 1, MipIndex);
                                MipCoverageData1[MipIndex] = (int8*)FMemory::Malloc(MipSizeX * MipSizeY);
                        }
                        else
                        {
                                // 2 coefficients are stored on the top/bottom halves of the same destination texture
                                MipData1[MipIndex] = MipData0[MipIndex] + StartBottom;
                                MipCoverageData1[MipIndex] = MipCoverageData0[MipIndex] + 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[Y * Allocation->TotalSizeX + X];

                                        int32 DestY = Y - Allocation->MappedRect.Min.Y + Allocation->OffsetY;
                                        int32 DestX = X - Allocation->MappedRect.Min.X + Allocation->OffsetX;

                                        FColor&        DestColor = MipData0[0][DestY * TextureSizeX + DestX];
                                        int8&        DestCoverage = MipCoverageData0[0][DestY * TextureSizeX + DestX];

                                        // modify by zhoujie remove dirLightNormal;
                                        //FColor&        DestBottomColor = MipData1[0][DestX + DestY * TextureSizeX];
                                //        int8&        DestBottomCoverage = MipCoverageData1[0][DestX + DestY * TextureSizeX];

#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[CoefficientIndex][0];
                                        DestColor.G = SourceCoefficients.Coefficients[CoefficientIndex][1];
                                        DestColor.B = SourceCoefficients.Coefficients[CoefficientIndex][2];
                                        DestColor.A = SourceCoefficients.AOMaterialMask;
                                       
                                        //下半部分内容清理,当然你可以写入你想要的其他内容。
                                //        DestBottomColor.R = SourceCoefficients.Coefficients[CoefficientIndex + 1][0];
                                //        DestBottomColor.G = SourceCoefficients.Coefficients[CoefficientIndex + 1][1];
                                //        DestBottomColor.B = SourceCoefficients.Coefficients[CoefficientIndex + 1][2];
                                //        DestBottomColor.A = SourceCoefficients.Coefficients[CoefficientIndex + 1][3];

                                        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等部分。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2021-5-17 20:08 | 显示全部楼层
6666沙发,很棒的分享。
发表于 2021-5-17 20:13 | 显示全部楼层
[爱]大佬~双节快乐哦~[调皮]
发表于 2021-5-17 20:19 | 显示全部楼层
[爱心]
发表于 2021-5-17 20:21 | 显示全部楼层
6666
发表于 2021-5-17 20:27 | 显示全部楼层
正好也在优化Lightmap占用的问题,感谢分享
[欢呼]
发表于 2021-5-17 20:36 | 显示全部楼层
“可以在BakeLightMap WorldSettings中增加自定义配置选项”,因为这些配置修改后要重编材质的,所以只能放在项目设置里面吧,然后修改后强制重启引擎重编材质
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-26 00:41 , Processed in 0.095091 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表