首页 > 其他分享 >lumen光照

lumen光照

时间:2024-08-13 18:16:20浏览次数:11  
标签:CardPageIndex CardUpdateContext CardPage uint 光照 lumen const Card

 1.创建cardUpdateContext

2,。直接光照

3. 间接光照

context

 1. 清除数据:ClearCardUpdateContextCS

/**
 * Batch clear all resources required for the subsequent card context update pass
 */
[numthreads(THREADGROUP_SIZE, 1, 1)]
void ClearCardUpdateContextCS(
    uint3 DispatchThreadId : SV_DispatchThreadID)
{
    uint ElementIndex = DispatchThreadId.x;

    if (ElementIndex < 1)
    {
        RWDirectLightingCardPageIndexAllocator[ElementIndex] = 0;
        RWIndirectLightingCardPageIndexAllocator[ElementIndex] = 0;
    }

    if (ElementIndex < CARD_UPDATE_CONTEXT_MAX * MAX_UPDATE_BUCKET_STRIDE)
    {
        RWMaxUpdateBucket[ElementIndex] = 0;
    }

    if (ElementIndex < CARD_UPDATE_CONTEXT_MAX * CARD_PAGE_TILE_ALLOCATOR_STRIDE)
    {
        RWCardPageTileAllocator[ElementIndex] = 0;
    }

    if (ElementIndex < CARD_UPDATE_CONTEXT_MAX * PRIORITY_HISTOGRAM_SIZE)
    {
        RWPriorityHistogram[ElementIndex] = 0;
    }
}

 

2. page更新直方图  

BuildPageUpdatePriorityHistogram

[numthreads(THREADGROUP_SIZE, 1, 1)]
void BuildPageUpdatePriorityHistogramCS(
    uint3 DispatchThreadId : SV_DispatchThreadID)
{
    uint IndexInIndexBuffer = DispatchThreadId.x;

    if (IndexInIndexBuffer < CardPageNum)
    {
        uint CardPageIndex = IndexInIndexBuffer;
        FLumenCardPageData CardPage = GetLumenCardPageData(CardPageIndex);
        FLumenCardData Card = GetLumenCardData(CardPage.CardIndex);
        const uint NumCardPageTiles = GetNumCardPageTiles(CardPage);

        if (NumCardPageTiles > 0)
        {
            BuildUpdatePriorityHistogram(Card, CardPage, CardPageIndex, NumCardPageTiles, CARD_UPDATE_CONTEXT_DIRECT_LIGHTING);
            BuildUpdatePriorityHistogram(Card, CardPage, CardPageIndex, NumCardPageTiles, CARD_UPDATE_CONTEXT_INDIRECT_LIGHTING);
        }
    }
}

优先级的计算

uint GetPriorityBucketIndex(FLumenCardData Card, FLumenCardPageData CardPage, uint CardPageIndex, uint CardUpdateContext)
{
    const float MaxUpdateFrequency = 7.0f;

    uint LastLightingUpdateFrameIndex = GetLastLightingUpdateFrameIndex(CardPage, CardUpdateContext);
    const float UpdateFactor = GetUpdateFactor(CardUpdateContext);

    // [1;N]
    uint FramesSinceLastUpdated = SurfaceCacheUpdateFrameIndex - LastLightingUpdateFrameIndex;

    // [0;MaxUpdateFrequency]
    float Frequency = 0.0f;
    {
        float DistanceFromViewer = 100000000.0f;

        for (uint ViewIndex = 0; ViewIndex < NumCameraOrigins; ViewIndex++)
        {
            float3 CardSpaceViewPosition = mul(WorldCameraOrigins[ViewIndex].xyz - Card.Origin, Card.WorldToLocalRotation);
            float3 CardPageLocalCenter;
            float3 CardPageLocalExtent;
            GetCardPageLocalBBox(CardPage, Card, CardPageLocalCenter, CardPageLocalExtent);
            DistanceFromViewer = min(DistanceFromViewer, sqrt(ComputeSquaredDistanceFromBoxToPoint(CardPageLocalCenter, CardPageLocalExtent, CardSpaceViewPosition)));
        }
        Frequency = MaxUpdateFrequency - clamp(DistanceFromViewer * FirstClipmapWorldExtentRcp, 0.0f, MaxUpdateFrequency);
    }

    // Drive frequency based on the feedback
    #if SURFACE_CACHE_FEEDBACK
    {
        const uint LastUsedFrameIndex = CardPageLastUsedBuffer[CardPageIndex];
        const uint LastUsedHighResFrameIndex = CardPageHighResLastUsedBuffer[CardPageIndex];
        const uint LastUsedCombinedFrameIndex = max(LastUsedFrameIndex, LastUsedHighResFrameIndex);

        FramesSinceLastUpdated = LastUsedCombinedFrameIndex > LastLightingUpdateFrameIndex ? LastUsedCombinedFrameIndex - LastLightingUpdateFrameIndex : 1;

        Frequency *= 0.5f;
        if (SurfaceCacheUpdateFrameIndex >= LastUsedHighResFrameIndex + 1)
        {
            Frequency += 0.5f * MaxUpdateFrequency * saturate((SurfaceCacheUpdateFrameIndex - (LastUsedHighResFrameIndex + 1)) / 2.0f);
        }
    }
    #endif

    uint BucketIndex = 0;
    if (LastLightingUpdateFrameIndex == 0)
    {
        // Special case where page wasn't ever updated, just place into first 8 most important buckets based on the frequency
        BucketIndex = clamp(MaxUpdateFrequency - Frequency, 0.0f, MaxUpdateFrequency);
    }
    else
    {
        // [0;N]
        float UpdateImportance = FramesSinceLastUpdated * (Frequency + 1.0f);

        // Offset from [1;N] and invert in order to place most important pages in bucket 0
        BucketIndex = PRIORITY_HISTOGRAM_SIZE - 1 - clamp(log2(UpdateImportance / (MaxUpdateFrequency + 1.0f)), 0, PRIORITY_HISTOGRAM_SIZE - 1);
    }

    return BucketIndex;
}

void BuildUpdatePriorityHistogram(FLumenCardData Card, FLumenCardPageData CardPage, uint CardPageIndex, uint NumCardPageTiles, uint CardUpdateContext)
{
    uint PriorityBucketIndex = GetPriorityBucketIndex(Card, CardPage, CardPageIndex, CardUpdateContext);
    InterlockedAdd(RWPriorityHistogram[CardUpdateContext * PRIORITY_HISTOGRAM_SIZE + PriorityBucketIndex], NumCardPageTiles);
}

 

3.最大优先级的找到 

SelectMaxUpdateBucketCS

void SelectMaxUpdateBucket(uint CardUpdateContext)
{
    const uint MaxTilesToUpdate = GetMaxTilesToUpdate(CardUpdateContext);

    uint UpdateTileSum = 0;
    uint PriorityBucketIndex = 0;
    uint PriorityBucketMaxTiles = MaxTilesToUpdate;

    for (; PriorityBucketIndex < PRIORITY_HISTOGRAM_SIZE; ++PriorityBucketIndex)
    {
        uint TilesPerBucket = PriorityHistogram[CardUpdateContext * PRIORITY_HISTOGRAM_SIZE + PriorityBucketIndex];

        if (UpdateTileSum + TilesPerBucket >= MaxTilesToUpdate)
        {
            PriorityBucketMaxTiles = MaxTilesToUpdate - UpdateTileSum;
            break;
        }

        UpdateTileSum += TilesPerBucket;
    }

    RWMaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 0] = PriorityBucketIndex;
    RWMaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 1] = PriorityBucketMaxTiles;
}

/** 
 * Compute max bucket histogram to update and how many tiles should be updated in that last bucket 
 */
[numthreads(THREADGROUP_SIZE, 1, 1)]
void SelectMaxUpdateBucketCS(
    uint3 GroupId : SV_GroupID,
    uint3 GroupThreadId : SV_GroupThreadID,
    uint3 DispatchThreadId : SV_DispatchThreadID)
{
    if (GroupId.x == 0 && GroupThreadId.x == 0)
    {
        SelectMaxUpdateBucket(CARD_UPDATE_CONTEXT_DIRECT_LIGHTING);
    }
    else if (GroupId.x == 1 && GroupThreadId.x == 0)
    {
        SelectMaxUpdateBucket(CARD_UPDATE_CONTEXT_INDIRECT_LIGHTING);
    }
}

 

4.创建更新列表

BuildCardsUpdateListCS:

card更新列表得到,设置更新数据:再次遍历每个 Card Page,根据最大可更新的 Bucket 将当前 Card Page Index 加入到更新列表中,对应 RDG 资源名为 Lumen.DirectLightingCardPageIndexDataLumen.IndirectLightingCardPageIndexData。同时每个加入到更新列表中的 Card Page 记录当前帧索引,用于下次构建直方图,Pass:Build cards update list。

/**
 * Iterate over all cards and pick first N for update based on the histogram max update bucket
 */
[numthreads(THREADGROUP_SIZE, 1, 1)]
void BuildCardsUpdateListCS(
    uint3 DispatchThreadId : SV_DispatchThreadID)
{
    uint IndexInIndexBuffer = DispatchThreadId.x;

    if (IndexInIndexBuffer < CardPageNum)
    {
        const uint CardPageIndex = IndexInIndexBuffer;
        FLumenCardPageData CardPage = GetLumenCardPageData(CardPageIndex);
        FLumenCardData Card = GetLumenCardData(CardPage.CardIndex);
        const uint NumCardPageTiles = GetNumCardPageTiles(CardPage);

        if (NumCardPageTiles > 0)
        {
            bool bUpdatedCardPage = false;

            // On radiosity atlas reset invalidate all history data
            if (IndirectLightingHistoryValid == 0)
            {
                CardPage.LastIndirectLightingUpdateFrameIndex = 0;
                bUpdatedCardPage = true;
            }

            if (BuildCardsUpdateList(
                Card,
                CardPage,
                CardPageIndex,
                NumCardPageTiles,
                CARD_UPDATE_CONTEXT_DIRECT_LIGHTING,
                RWDirectLightingCardPageIndexAllocator,
                RWDirectLightingCardPageIndexData))
            {
                CardPage.LastDirectLightingUpdateFrameIndex = SurfaceCacheUpdateFrameIndex;
                bUpdatedCardPage = true;
            }

            if (BuildCardsUpdateList(
                Card,
                CardPage,
                CardPageIndex,
                NumCardPageTiles,
                CARD_UPDATE_CONTEXT_INDIRECT_LIGHTING,
                RWIndirectLightingCardPageIndexAllocator,
                RWIndirectLightingCardPageIndexData))
            {
                CardPage.LastIndirectLightingUpdateFrameIndex = SurfaceCacheUpdateFrameIndex;
                CardPage.IndirectLightingTemporalIndex = CardPage.IndirectLightingTemporalIndex + 1;
                bUpdatedCardPage = true;
            }

            if (bUpdatedCardPage && FreezeUpdateFrame == 0)
            {
                SetCardPageUpdateData(CardPageIndex, CardPage);
            }
        }
    }
}
BuildCardsUpdateList

bool BuildCardsUpdateList(
    FLumenCardData Card,
    FLumenCardPageData CardPage,
    uint CardPageIndex,
    uint NumCardPageTiles,
    uint CardUpdateContext,
    RWStructuredBuffer<uint> RWCardPageIndexAllocator,
    RWStructuredBuffer<uint> RWCardPageIndexData)
{
    const uint MaxTilesToUpdate = GetMaxTilesToUpdate(CardUpdateContext);
    const uint MaxUpdateBucketIndex = MaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 0];
    const uint MaxUpdateBucketMaxTiles = MaxUpdateBucket[MAX_UPDATE_BUCKET_STRIDE * CardUpdateContext + 1];

    // Update everything up to the max selected priority bucket
    uint PriorityBucketIndex = GetPriorityBucketIndex(Card, CardPage, CardPageIndex, CardUpdateContext);
    bool bUpdateThisPage = PriorityBucketIndex <= MaxUpdateBucketIndex;

    if (bUpdateThisPage && PriorityBucketIndex == MaxUpdateBucketIndex)
    {
        // Can't update more than MaxUpdateBucketMaxTiles in the max bucket to preserve the general order
        uint NumAllocatedTilesInMaxUpdateBucket = 0;
        InterlockedAdd(RWCardPageTileAllocator[CARD_PAGE_TILE_ALLOCATOR_STRIDE * CardUpdateContext + 1], NumCardPageTiles, NumAllocatedTilesInMaxUpdateBucket);

        if (!(NumAllocatedTilesInMaxUpdateBucket + NumCardPageTiles <= MaxUpdateBucketMaxTiles))
        {
            bUpdateThisPage = false;
        }
    }

    if (bUpdateThisPage)
    {
        bUpdateThisPage = false;
        uint NumAllocatedTiles = 0;
        InterlockedAdd(RWCardPageTileAllocator[CARD_PAGE_TILE_ALLOCATOR_STRIDE * CardUpdateContext + 0], NumCardPageTiles, NumAllocatedTiles);

        if (NumAllocatedTiles + NumCardPageTiles <= MaxTilesToUpdate)
        {
            uint NextIndex = 0;
            InterlockedAdd(RWCardPageIndexAllocator[0], 1, NextIndex);

            if (NextIndex < CardPageNum)
            {
                RWCardPageIndexData[NextIndex] = CardPageIndex;
                bUpdateThisPage = true;
            }
        }
    }

    return bUpdateThisPage;
}

设置数据:

// Store only card page update data
void SetCardPageUpdateData(uint CardPageId, FLumenCardPageData CardPageData)
{
    // Note: layout must match FLumenCardPageData in C++

    uint4 Vector4;
    Vector4.x = CardPageData.LastDirectLightingUpdateFrameIndex;
    Vector4.y = CardPageData.LastIndirectLightingUpdateFrameIndex;
    Vector4.z = CardPageData.IndirectLightingTemporalIndex;
    Vector4.w = 0;

    uint BaseOffset = CardPageId * LUMEN_CARD_PAGE_DATA_STRIDE;
    RWLumenCardPageDataBuffer[BaseOffset + 4] = asfloat(Vector4);
}

 

5.设置命令参数

设置间接参数FSetCardPageIndexIndirectArgsCS:根据上面的数据生成后续步骤的 Indirect Draw 和 Indirect Dispatch 参数

 

 
{
        FSetCardPageIndexIndirectArgsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FSetCardPageIndexIndirectArgsCS::FParameters>();
        PassParameters->RWDirectLightingDrawCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs);
        PassParameters->RWDirectLightingDispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(DirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs);
        PassParameters->RWIndirectLightingDrawCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.DrawCardPageIndicesIndirectArgs);
        PassParameters->RWIndirectLightingDispatchCardPageIndicesIndirectArgs = GraphBuilder.CreateUAV(IndirectLightingCardUpdateContext.DispatchCardPageIndicesIndirectArgs);
        PassParameters->DirectLightingCardPageIndexAllocator = DirectCardPageIndexAllocatorSRV;
        PassParameters->IndirectLightingCardPageIndexAllocator = IndirectCardPageIndexAllocatorSRV;
        PassParameters->VertexCountPerInstanceIndirect = GRHISupportsRectTopology ? 3 : 6;

        auto ComputeShader = Views[0].ShaderMap->GetShader<FSetCardPageIndexIndirectArgsCS>();

        FComputeShaderUtils::AddPass(
            GraphBuilder,
            RDG_EVENT_NAME("SetCardPageIndexIndirectArgs"),
            ComputePassFlags,
            ComputeShader,
            PassParameters,
            FIntVector(1, 1, 1));
    }

FSetCardPageIndexIndirectArgsCS

RWBuffer<uint> RWDirectLightingDrawCardPageIndicesIndirectArgs;
RWBuffer<uint> RWDirectLightingDispatchCardPageIndicesIndirectArgs;
RWBuffer<uint> RWIndirectLightingDrawCardPageIndicesIndirectArgs;
RWBuffer<uint> RWIndirectLightingDispatchCardPageIndicesIndirectArgs;

StructuredBuffer<uint> DirectLightingCardPageIndexAllocator;
StructuredBuffer<uint> IndirectLightingCardPageIndexAllocator;
uint VertexCountPerInstanceIndirect;

[numthreads(THREADGROUP_SIZE, 1, 1)]
void SetCardPageIndexIndirectArgsCS(uint3 DispatchThreadId : SV_DispatchThreadID)
{
    if (DispatchThreadId.x == 0)
    {
        {
            uint NumPageIndices = DirectLightingCardPageIndexAllocator[0];

            // FRHIDrawIndirectParameters
            RWDirectLightingDrawCardPageIndicesIndirectArgs[0] = VertexCountPerInstanceIndirect;
            RWDirectLightingDrawCardPageIndicesIndirectArgs[1] = NumPageIndices;
            RWDirectLightingDrawCardPageIndicesIndirectArgs[2] = 0;
            RWDirectLightingDrawCardPageIndicesIndirectArgs[3] = 0;

            // Thread per page
            WriteDispatchIndirectArgs(RWDirectLightingDispatchCardPageIndicesIndirectArgs, 0, (NumPageIndices + 63) / 64, 1, 1);

            // Thread per tile
            WriteDispatchIndirectArgs(RWDirectLightingDispatchCardPageIndicesIndirectArgs, 1, 4 * NumPageIndices, 1, 1);
        }

        {
            uint NumPageIndices = IndirectLightingCardPageIndexAllocator[0];

            // FRHIDrawIndirectParameters
            RWIndirectLightingDrawCardPageIndicesIndirectArgs[0] = VertexCountPerInstanceIndirect;
            RWIndirectLightingDrawCardPageIndicesIndirectArgs[1] = NumPageIndices;
            RWIndirectLightingDrawCardPageIndicesIndirectArgs[2] = 0;
            RWIndirectLightingDrawCardPageIndicesIndirectArgs[3] = 0;

            // Thread per page
            WriteDispatchIndirectArgs(RWIndirectLightingDispatchCardPageIndicesIndirectArgs, 0, (NumPageIndices + 63) / 64, 1, 1);

            // Thread per tile
            WriteDispatchIndirectArgs(RWIndirectLightingDispatchCardPageIndicesIndirectArgs, 1, 4 * NumPageIndices, 1, 1);
        }
    }
}

RenderDirectLightingForLumenScene

void FDeferredShadingSceneRenderer::RenderDirectLightingForLumenScene(
FRDGBuilder& GraphBuilder,
const FLumenSceneFrameTemporaries& FrameTemporaries,
const FLumenDirectLightingTaskData* LightingTaskData,
const FLumenCardUpdateContext& CardUpdateContext,
ERDGPassFlags ComputePassFlags)

 

CullDirectLightingTiles:将cardPage分为tile,以tile为单位对光源进行Culling;每个光源一个light列表

SpliceCardPagesIntoTiles

FBuildLightTilesCS:创建light tile列表

FComputeLightTileOffsetsPerLightCS:计算每个tile的偏移

FInitializeLightTileIndirectArgsCS:为剔除tile初始化间接参数

FCompactLightTilesCS:压缩card tile

ComputeShadowMaskFromLightAttenuation:

FLumenDirectLightingShadowMaskFromLightAttenuationCS 光照函数或普通的

FInitShadowTraceIndirectArgsCS

TraceDistanceFieldShadows

CullMeshObjectsForLightCards

CullDistanceFieldObjectsForLight

ScatterObjectsToShadowTiles

RenderDirectLightIntoLumenCardsBatched:应用光照

CombineLumenSceneLighting:更新最终light

 

标签:CardPageIndex,CardUpdateContext,CardPage,uint,光照,lumen,const,Card
From: https://www.cnblogs.com/Shaojunping/p/18357502

相关文章

  • 1328、基于51单片机光照人体检测手自动语音控制蓝牙远程控制智能台灯(程序+原理图+PCB
    毕设帮助、开题指导、技术解答(有偿)见文未  目录方案选择单片机的选择一、设计功能二、实物图单片机模块设计三、原理图四、程序源码五、PCB图六、proteus仿真资料包括:需要完整的资料可以点击下面的名片加下我,找我要资源压缩包的百度网盘下载地址及提取码。方......
  • 算法介绍(一):LLCNN低光照
    对于一张灰度图片,像素值越大则亮度越高,像素值越小则亮度越低在数字图像处理领域有一种很简单的图像亮度调整算法——伽马变换伽马变换是一种用于调整图像亮度和对比度的非线性操作,其基本公式为(I'=I^\gamma),其中(I')是输出图像的灰度值,(I)是输入图像的灰度值,而(\g......
  • STM32:ADC采集光照(含完整源码)
    需求通过ADC转换实现光照亮度的数字化测量,最后将实时测量的结果打印在串口上。一、ADC概要  ADC全称是Analog-to-DigitalConverter模数转换器,一般我们把模拟信号(Analogsignal)用A来进行简写,数字信号(digitalsignal)用D来表示。  自然界中绝大部分都是模拟信......
  • 基于51单片机的光照强度检测系统设计与实现
    基于51单片机的光照强度检测系统设计与实现摘要本文设计并实现了一个基于51单片机的光照强度检测系统,该系统利用光敏电阻作为光照强度检测元件,通过ADC转换器将模拟信号转换为数字信号,并由51单片机进行处理和显示。系统具备实时检测、数据转换、存储及显示功能,适用于各种需要......
  • UE5笔记-实现Lumen实时渲染GI下的的类UCanvasRenderTarget实现多场景/自定义分辨率/方
    默认的SceneCapture不能用于实时Lumen光照模式下为了实现实时渲染GI下的的类似于UCanvasRenderTarget2D类.可以参考GameViewport类的源码尝试使用UE的渲染逻辑和数据多渲染一份视口副本到直接的FSceneView上,封装一份UCaptureRenderTarget出来从而实现一些例如自定义分辨率的......
  • 【SkiaSharp绘图05】SKPaint详解(三)之ImageFilter(颜色、组合、膨胀、移位、光照、反射
    文章目录ImageFilterCreateColorFilter颜色滤镜CreateCompose滤镜组合CreateDilate膨胀滤镜CreateDisplacementMapEffect移位映射CreateDistantLitDiffuse光照CreateDistantLitSpecular反射光照CreateDropShadow阴影效果CreateDropShadowOnly只阴影效果CreateErod......
  • 渲染中的光照着色方式:PBR(Physically Based Rendering,物理基础渲染)与 传统经验渲染
    参考《UnityShader入门精要》十八章基于物理的渲染 与PBR(PhysicallyBasedRendering,物理基础渲染)对应的渲染方法通常被称为“传统渲染”或“基于经验的渲染”(EmpiricalRendering)。以下是两者的主要区别:传统渲染传统渲染方法基于经验规则和艺术调整,而不是物理定律。这种......
  • 基于51单片机的窗帘控制系统【温湿度,烟雾,红外,光照】(仿真)
    基于51单片机的窗帘控制系统【温湿度,烟雾,红外,光照】(仿真)给大家提供一些资料详细解释,有需要的自行提取,网盘地址我放在下面 链接:https://pan.baidu.com/s/1NigBeujDZTCFL0hdMiu7yg?pwd=syxp 提取码:syxp 分别利用温湿度传感器、烟雾传感器、光敏电阻、红外检测控制模块等......
  • 基于Matlab低光照夜间欧盟英国车牌识别系统
    欢迎大家点赞、收藏、关注、评论啦,由于篇幅有限,只展示了部分核心代码。文章目录一项目简介二、功能三、系统四.总结一项目简介  一、项目背景与意义在智能交通系统中,车牌识别技术扮演着至关重要的角色。然而,在夜间或低光照条件下,车牌识别面临着巨大的挑战......
  • 饮料添加剂新型褪色光照试验仪器太阳光模拟器
    太阳光模拟器的定义和功能太阳光模拟器是一种高科技设备,它可以模拟太阳光的光谱、光强和光照条件,用于实验室环境中对太阳能电池、光电器件以及其他需要太阳光条件的设备和材料进行评估。太阳光模拟器的主要功能包括模拟太阳光的光谱分布、辐照度、光束准直以及大面积照射能力,......