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,

  • 相关阅读:
    hdu 5366 简单递推
    hdu 5365 判断正方形
    hdu 3635 并查集
    hdu 4497 数论
    hdu5419 Victor and Toys
    hdu5426 Rikka with Game
    poj2074 Line of Sight
    hdu5425 Rikka with Tree II
    hdu5424 Rikka with Graph II
    poj1009 Edge Detection
  • 原文地址:https://www.cnblogs.com/Shaojunping/p/12234720.html
Copyright © 2011-2022 走看看