zoukankan      html  css  js  c++  java
  • ue4 lightmass研究

    Exporter.cpp文件中:导出shadowDepthMap:

    void FLightmassSolverExporter::ExportStaticShadowDepthMap(const FGuid& LightGuid, const FStaticShadowDepthMap& StaticShadowDepthMap) const
    	{
    		const FString ChannelName = CreateChannelName(LightGuid, LM_DOMINANTSHADOW_VERSION, LM_DOMINANTSHADOW_EXTENSION);
    		const int32 ErrorCode = Swarm->OpenChannel(*ChannelName, LM_DOMINANTSHADOW_CHANNEL_FLAGS, true);
    		if( ErrorCode >= 0 )
    		{
    			Swarm->Write(&StaticShadowDepthMap, sizeof(FStaticShadowDepthMapData));
    			static_assert(sizeof(FStaticShadowDepthMapSample) == sizeof(FStaticShadowDepthMapSampleData), "ShadowDerivedSizeMustMatch");
    			WriteArray(StaticShadowDepthMap.ShadowMap);
    			Swarm->CloseCurrentChannel();
    		}
    		else
    		{
    			UE_LOG(LogLightmass, Log, TEXT("Failed to open static shadow depth map channel!"));
    		}
    	}
    

      WriteArray函数是将TArray中的数据写道swarm栈的顶:

    /** Writes a TArray to the channel on the top of the Swarm stack. */
    	template<class T>
    	void FLightmassSolverExporter::WriteArray(const TArray<T>& Array) const
    	{
    		const int32 ArrayNum = Array.Num();
    		Swarm->Write((void*)&ArrayNum, sizeof(ArrayNum));
    		if (ArrayNum > 0)
    		{
    			Swarm->Write(Array.GetData(), Array.GetTypeSize() * ArrayNum);
    		}
    	}
    

      输出staticLightData:

    int32 FLightmassSolverExporter::BeginExportResults(struct FTextureMappingStaticLightingData& LightingData, uint32 NumMappings) const
    	{
    		const FString ChannelName = CreateChannelName(LightingData.Mapping->Guid, LM_TEXTUREMAPPING_VERSION, LM_TEXTUREMAPPING_EXTENSION);
    		const int32 ErrorCode = Swarm->OpenChannel(*ChannelName, LM_TEXTUREMAPPING_CHANNEL_FLAGS, true);
    		if( ErrorCode < 0 )
    		{
    			UE_LOG(LogLightmass, Log, TEXT("Failed to open texture mapping channel %s!"), *ChannelName);
    		}
    		else
    		{
    			// Write out the number of mappings this channel will contain
    			Swarm->Write(&NumMappings, sizeof(NumMappings));
    		}
    		return ErrorCode;
    	}
    

      这个函数被ExportResults函数调用:

    void FLightmassSolverExporter::ExportResults( FTextureMappingStaticLightingData& LightingData, bool bUseUniqueChannel ) const
    	{
    		UE_LOG(LogLightmass, Verbose, TEXT("Exporting texture lighting %s [%.3fs]"), *(LightingData.Mapping->Guid.ToString()), LightingData.ExecutionTime);
    
    		// If requested, use a unique channel for this mapping, otherwise, just use the one that is already open
    		if (bUseUniqueChannel)
    		{
    			if (BeginExportResults(LightingData, 1) < 0)
    			{
    				return;
    			}
    		}
    
    		const int32 PaddedOffset = LightingData.Mapping->bPadded ? 1 : 0;
    		const int32 DebugSampleIndex = LightingData.Mapping == Scene.DebugMapping
    			? (Scene.DebugInput.LocalY + PaddedOffset) * LightingData.Mapping->SizeX + Scene.DebugInput.LocalX + PaddedOffset
    			: INDEX_NONE;
    
    		if (bDumpTextures)
    		{
    			WriteBitmap<4>(*(LightingData.Mapping->Guid.ToString() + TEXT("_LM")), LightingData.LightMapData->GetData(), LightingData.LightMapData->GetSizeX(), LightingData.LightMapData->GetSizeY());
    		}
    
    		// If we need to compress the data before writing out, do it now
    		LightingData.LightMapData->Compress(DebugSampleIndex);
    //		UE_LOG(LogLightmass, Log, TEXT("LM data went from %d to %d bytes"), LightingData.LightMapData->UncompressedDataSize, LightingData.LightMapData->CompressedDataSize);
    
    		const int32 ShadowMapCount = LightingData.ShadowMaps.Num();
    		const int32 SignedDistanceFieldShadowMapCount = LightingData.SignedDistanceFieldShadowMaps.Num();
    		const int32 NumLights = LightingData.LightMapData->Lights.Num();
    	
    #pragma pack (push,1)
    		struct FTextureHeader
    		{
    			FTextureHeader(FGuid& InGuid, double InExecutionTime, FLightMapData2DData& InData, int32 InShadowMapCount, int32 InSignedDistanceFieldShadowMapCount, int32 InLightCount)
    				: Guid(InGuid), ExecutionTime(InExecutionTime), Data(InData), ShadowMapCount(InShadowMapCount), SignedDistanceFieldShadowMapCount(InSignedDistanceFieldShadowMapCount), LightCount(InLightCount)
    			{}
    			FGuid Guid;
    			double ExecutionTime;
    			FLightMapData2DData Data;
    			int32 ShadowMapCount;
    			int32 SignedDistanceFieldShadowMapCount;
    			int32 LightCount;
    		};
    #pragma pack (pop)
    		FTextureHeader Header(LightingData.Mapping->Guid, LightingData.ExecutionTime, *(FLightMapData2DData*)LightingData.LightMapData, LightingData.ShadowMaps.Num(), LightingData.SignedDistanceFieldShadowMaps.Num(), NumLights);
    		Swarm->Write(&Header, sizeof(Header));
    
    		for (int32 LightIndex = 0; LightIndex < NumLights; LightIndex++)
    		{
    			FGuid CurrentGuid = LightingData.LightMapData->Lights[LightIndex]->Guid;
    			Swarm->Write(&CurrentGuid, sizeof(CurrentGuid));
    		}
    
    		// Write out compressed data if supported
    		Swarm->Write(LightingData.LightMapData->GetCompressedData(), LightingData.LightMapData->CompressedDataSize ? LightingData.LightMapData->CompressedDataSize : LightingData.LightMapData->UncompressedDataSize);
    
    		// The resulting light GUID --> shadow map data
    		int32 ShadowIndex = 0;
    
    		for (TMap<const FLight*,FSignedDistanceFieldShadowMapData2D*>::TIterator It(LightingData.SignedDistanceFieldShadowMaps); It; ++It, ++ShadowIndex)
    		{
    			FGuid OutGuid = It.Key()->Guid;
    			FSignedDistanceFieldShadowMapData2D* OutData = It.Value();
    
    			// If we need to compress the data before writing out, do it now
    			OutData->Compress(INDEX_NONE);
    
    			Swarm->Write(&OutGuid, sizeof(FGuid));
    			Swarm->Write((FSignedDistanceFieldShadowMapData2DData*)OutData, sizeof(FSignedDistanceFieldShadowMapData2DData));
    
    			// Write out compressed data if supported
    			Swarm->Write(OutData->GetCompressedData(), OutData->CompressedDataSize ? OutData->CompressedDataSize : OutData->UncompressedDataSize);
    		}
    
    		WriteDebugLightingOutput(LightingData.DebugOutput);
    
    		// free up the calculated data
    		delete LightingData.LightMapData;
    		LightingData.ShadowMaps.Empty();
    		LightingData.SignedDistanceFieldShadowMaps.Empty();
    
    		// Only close the channel if we opened it
    		if (bUseUniqueChannel)
    		{
    			EndExportResults();
    		}
    	}
    

      一个贴图映射的静态光照数据:

    /** The static lighting data for a texture mapping. */
    struct FTextureMappingStaticLightingData
    {
    	FStaticLightingTextureMapping* Mapping;
    	FLightMapData2D* LightMapData;
    	TMap<const FLight*,FShadowMapData2D*> ShadowMaps;
    	TMap<const FLight*,FSignedDistanceFieldShadowMapData2D*> SignedDistanceFieldShadowMaps;
    	FDebugLightingOutput DebugOutput;
    
    	/** Stores the time this mapping took to process */
    	double ExecutionTime;
    };  

    裏面shadowmapData2D类:

    class FShadowMapData2D : public FShadowMapData2DData
    	{
    	public:
    		FShadowMapData2D(uint32 InSizeX,uint32 InSizeY)
    			: FShadowMapData2DData(InSizeX, InSizeY)
    			, CompressedData(NULL)
    		{
    			Data.Empty(InSizeX * InSizeY);
    			Data.AddZeroed(InSizeX * InSizeY);
    		}
    
    		virtual ~FShadowMapData2D(){ }
    
    		// Accessors.
    		const FShadowSample& operator()(uint32 X,uint32 Y) const { return Data[SizeX * Y + X]; }
    		FShadowSample& operator()(uint32 X,uint32 Y) { return Data[SizeX * Y + X]; }
    		uint32 GetSizeX() const { return SizeX; }
    		uint32 GetSizeY() const { return SizeY; }
    
    		// USurface interface
    		virtual float GetSurfaceWidth() const { return SizeX; }
    		virtual float GetSurfaceHeight() const { return SizeY; }
    
    		void Quantize(int32 DebugSampleIndex);
    
    		const FShadowSample* GetData() { return Data.GetData(); }
    		const FQuantizedShadowSampleData* GetQuantizedData() { return QuantizedData.GetData(); }
    
    		void Compress(int32 DebugSampleIndex);
    		uint8* GetCompressedData()
    		{
    			return CompressedData;
    		}
    
    	private:
    		TArray<FShadowSample>				Data;
    		TArray<FQuantizedShadowSampleData>	QuantizedData;
    		uint8*								CompressedData;
    	};
    

      FSHadowSample类:

    /**
    	 * A sample of the visibility factor between a light and a single point.
    	 */
    	class FShadowSample : public FShadowSampleData
    	{
    	public:
    		FShadowSample operator-(const FShadowSample& SampleB) const
    		{
    			FShadowSample Result;
    			Result.bIsMapped = bIsMapped;
    			Result.Visibility = Visibility - SampleB.Visibility;
    			return Result;
    		}
    		FShadowSample operator*(const float& Scalar) const
    		{
    			FShadowSample Result;
    			Result.bIsMapped = bIsMapped;
    			Result.Visibility = Visibility * Scalar;
    			return Result;
    		}
    	};
    

      

    lightmass的Export

    StaticLightingTextureMapping继承了StaticLightingMapping、StaticLightingMappingData:

    {

    FStaticLightingMesh* Mesh; //和映射关联的mesh,用来计算静态光的mesh。

    }

    FStaticLightingMesh

    {

      TArray<FLight*> RelevantLights;

    TArray<int32> VisibilityIds;

    TArray<FMaterialElement, TInlineAllocator<5>> MaterialElements;

    bool IsTranslucent(int32 ElementIndex)

    bool IsMasked(int32 ElementIndex)

     bool UsesTwoSidedLighting(int32 ElementIndex)

    IsTwoSided(int32 ElementIndex)

    bool UseVertexNormalForHemisphereGather(int32 ElementIndex)

    virtual void GetTriangle(int32 TriangleIndex,FStaticLightingVertex& OutV0,FStaticLightingVertex& OutV1,FStaticLightingVertex& OutV2,int32& ElementIndex) const = 0;

    virtual void GetShadingTriangle(int32 TriangleIndex,FStaticLightingVertex& OutV0,FStaticLightingVertex& OutV1,FStaticLightingVertex& OutV2,int32& ElementIndex) const

    void GetTriangleIndices(int32 TriangleIndex,int32& OutI0,int32& OutI1,int32& OutI2)

    FLinearColor EvaluateBRDF(
    const FStaticLightingVertex& Vertex,
    int32 ElementIndex,
    const FVector4& IncomingDirection,
    const FVector4& OutgoingDirection) const;

    FLinearColor SampleBRDF(
    const FStaticLightingVertex& Vertex,
    int32 ElementIndex,
    const FVector4& IncomingDirection,
    FVector4& OutgoingDirection,
    float& DirectionPDF,
    FLMRandomStream& RandomStream
    ) const;

    inline FLinearColor EvaluateEmissive(const FVector2D& UVs, int32 ElementIndex) const;

    inline FLinearColor EvaluateDiffuse(const FVector2D& UVs, int32 ElementIndex) const;

    }

    用一个空level, 添加一个点光源和一个cube,进行测试,build lightt后生成一张256*256的HQ_Lightmap_1_1和LQ_Lightmap_1_1。前者包含A通道,后者不包含。一张256*128的ShadowMapTexture2D_2,包含R和G通道。一张64*64

    的HQ_Lightmap_1_2和LQ_Lightmap_1_2。一张32*32的shadowmapTexture2D_3,4个通道都有东西,东西差不多一样。

    空level什么都不添加,build lightt后生成一张256*256的HQ_Lightmap_1_1和LQ_Lightmap_1_1。前者包含A通道,后者不包含。一张128*128的ShadowMapTexture2D_2,包含4个通道,东西一样。一张64*64的HQ_Lightmap_1_2和LQ_Lightmap_1_2。一张32*32的shadowmapTexture2D_3,4个通道都有东西,东西差不多一样。

    综合,不同的地方:1. ShadowMapTexture2D_2的大小;2.ShadowMapTexture2D_2的通道数。

    void UEditorEngine::BuildLighting(const FLightingBuildOptions& Options)函数是编辑器按build lighting only触发的,里面调用了OnLightingBUildStarted.Broadcast()和FStaticLightingManager::Get()->createStaticLightingSystem(Options);

          createStaticLIghtingSystem函数里StaticLightingSystems数组放置光照系统(如果level是光照场景,则每个level场景一个)。然后第一个静态光照系统作为激活的系统,这个系统开启lightmass程序,下面的函数:

                FStaticLightingSystem::BeginLightmassProcess()里面包含 Gather 创建lightmass进程(CreateLIghtmassProcessor函数,启动swarm,新建lightmass、关联到swarm),GatherScene函数(lightmassExporter的levelSetting、没用的局部核心、品质等级、level名称、重要度体积、角色间接细节体积、立体lightmap密度体积、lightmassPortal、mesh、mapping、light、 staticMeshLightingMesheslight、material、staticMeshTextureMapping、volumetricLightmapTaskGuids),初始化lightmass进程(InitiateLightmassProcessor函数,InitiateExport()(Exporter->writeChannel))。

    FStaticLightingSystem::UpdateLightingBuild()

    void FStaticLightingManager::UpdateBuildLighting()

    void UEditorEngine::UpdateBuildLighting()
    {
    FStaticLightingManager::Get()->UpdateBuildLighting();
    }

    void FLightmassProcessor::ImportMapping( const FGuid& MappingGuid, bool bProcessImmediately )、void FLightmassProcessor::ImportVolumetricLightmap()、


    void FLightmassProcessor::ImportStaticShadowDepthMap(ULightComponent* Light)、void FLightmassProcessor::ImportMappings(bool bProcessImmediately)

     CompleteRun函数里会importVolumeSamples、importVolumetricLightmap、importPrecomputedVisibility、importMappings、ProcessAvailableMappings()这些函数。

    ImportMappings函数调用ImportMapping函数,后者又会调用ImportStaticLightingTextureMapping、ImportStaticShadowDepthMap。

           ImportStaticLightingTextureMapping函数又调用了ImportTextureMapping,后者又调用了ImportLightmapData2DData。

    ProcessAvailableMappings()这个函数会又会ProcessMappings,后者又会调用ApplyMapping,

  • 相关阅读:
    docker实例之mysql的使用
    使用Dockerfile创建ssh服务的镜像02
    添加ssh服务构建新镜像-docker commit 方式01
    Keepalived
    ubuntu网卡配置
    升级openssl
    源码安装nginx env
    dockerfile
    shell字符截取
    MYSQL导入/迁移后事件不执行
  • 原文地址:https://www.cnblogs.com/Shaojunping/p/12234720.html
Copyright © 2011-2022 走看看