延迟渲染到最终结果------1,2,分配渲染目标和初始化窗口(大象无形11.3.1)

2023-11-15

 

版本不同,我这里延迟渲染是FDeferredShadingSceneRenderer类

即函数

void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList);

逐渐填充大象无形中的注释

 

一,按需要重新分配渲染目标

void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)
{

.............

//获得渲染目标单例

    FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);
    ......

    //分配渲染目标
    SceneContext.AllocDummyGBufferTargets(RHICmdList);
....

}

查看其实现

static TGlobalResource<FSceneRenderTargets> SceneRenderTargetsSingleton;

FSceneRenderTargets& FSceneRenderTargets::Get(FRHICommandListImmediate& RHICmdList)
{
.......
    return SceneRenderTargetsSingleton;
}


void FSceneRenderTargets::AllocDummyGBufferTargets(FRHICommandList& RHICmdList)
{
    if (GBufferDummyResourcesUniformBuffer)
    {
        return;
    }

    FTextureRHIRef BlackDummy = GSystemTextures.BlackDummy->GetRenderTargetItem().ShaderResourceTexture;    

    FGBufferResourceStruct GBufferResourceStruct;

    GBufferResourceStruct.GBufferATexture = BlackDummy;

........

    GBufferResourceStruct.GBufferATextureSampler = TStaticSamplerState<>::GetRHI();

.......

    GBufferDummyResourcesUniformBuffer = FGBufferResourceStruct::CreateUniformBuffer(GBufferResourceStruct, UniformBuffer_SingleFrame);
}
 

二,初始化视口(可以多个),包括确定可见性与设置阴影相关参数


void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)

{

.......
    FGraphEventArray SortEvents;
    FILCUpdatePrimTaskData ILCTaskData;
    bool bDoInitViewAftersPrepass = InitViews(RHICmdList, ILCTaskData, SortEvents);

.........

}

现在看下initViews函数
bool FDeferredShadingSceneRenderer::InitViews(FRHICommandListImmediate& RHICmdList, struct FILCUpdatePrimTaskData& ILCTaskData, FGraphEventArray& SortEvents)
{    
........

   //预设置可见性

    PreVisibilityFrameSetup(RHICmdList);

    //可见性计算
    ComputeViewVisibility(RHICmdList);

.....

//完成可见性计算

    PostVisibilityFrameSetup(ILCTaskData);

.......
}
1, //预设置可见性
void FSceneRenderer::PreVisibilityFrameSetup(FRHICommandListImmediate& RHICmdList)

{

      //告诉RHI命令队列,开始渲染
        RHICmdList.BeginScene();

......

       //根据当前画质设置,设置TemporalAA的采样方式,同时确定采样位置,

       //这个采样位置用于微调接下来的矩阵,进行像素偏移,混合前面几帧的渲染结果,提高精度

      
    for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++)
    {
        FViewInfo& View = Views[ViewIndex];
        FSceneViewState* ViewState = View.ViewState;

......
        FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList);


        // set up the screen area for occlusion
        float NumPossiblePixels = SceneContext.UseDownsizedOcclusionQueries() && IsValidRef(SceneContext.GetSmallDepthSurface()) ? 
            (float)View.ViewRect.Width() / SceneContext.GetSmallColorDepthDownsampleFactor() * (float)View.ViewRect.Height() / SceneContext.GetSmallColorDepthDownsampleFactor() :
            View.ViewRect.Width() * View.ViewRect.Height();
        View.OneOverNumPossiblePixels = NumPossiblePixels > 0.0 ? 1.0f / NumPossiblePixels : 0.0f;

        // Still need no jitter to be set for temporal feedback on SSR (it is enabled even when temporal AA is off).
        View.TemporalJitterPixelsX = 0.0f;
        View.TemporalJitterPixelsY = 0.0f;

        if (ViewState)
        {
            ViewState->SetupDistanceFieldTemporalOffset(ViewFamily);
        }

        if( View.AntiAliasingMethod == AAM_TemporalAA && ViewState )
        {
            // Subpixel jitter for temporal AA
            int32 TemporalAASamples = CVarTemporalAASamples.GetValueOnRenderThread();
        
            if( TemporalAASamples > 1 && View.bAllowTemporalJitter )
            {
                float SampleX, SampleY;

                if (Scene->GetFeatureLevel() < ERHIFeatureLevel::SM4)
                {
                    // Only support 2 samples for mobile temporal AA.
                    TemporalAASamples = 2;
                }

                if( TemporalAASamples == 2 )
                {
                    #if 0
                        // 2xMSAA
                        // Pattern docs: http://msdn.microsoft.com/en-us/library/windows/desktop/ff476218(v=vs.85).aspx
                        //   N.
                        //   .S
                        float SamplesX[] = { -4.0f/16.0f, 4.0/16.0f };
                        float SamplesY[] = { -4.0f/16.0f, 4.0/16.0f };
                    #else
                        // This pattern is only used for mobile.
                        // Shift to reduce blur.
                        float SamplesX[] = { -8.0f/16.0f, 0.0/16.0f };
                        float SamplesY[] = { /* - */ 0.0f/16.0f, 8.0/16.0f };
                    #endif
                    ViewState->OnFrameRenderingSetup(ARRAY_COUNT(SamplesX), ViewFamily);
                    uint32 Index = ViewState->GetCurrentTemporalAASampleIndex();
                    SampleX = SamplesX[ Index ];
                    SampleY = SamplesY[ Index ];
                }
                else if( TemporalAASamples == 3 )
                {
                    // 3xMSAA
                    //   A..
                    //   ..B
                    //   .C.
                    // Rolling circle pattern (A,B,C).
                    float SamplesX[] = { -2.0f/3.0f,  2.0/3.0f,  0.0/3.0f };
                    float SamplesY[] = { -2.0f/3.0f,  0.0/3.0f,  2.0/3.0f };
                    ViewState->OnFrameRenderingSetup(ARRAY_COUNT(SamplesX), ViewFamily);
                    uint32 Index = ViewState->GetCurrentTemporalAASampleIndex();
                    SampleX = SamplesX[ Index ];
                    SampleY = SamplesY[ Index ];
                }
                else if( TemporalAASamples == 4 )
                {
                    // 4xMSAA
                    // Pattern docs: http://msdn.microsoft.com/en-us/library/windows/desktop/ff476218(v=vs.85).aspx
                    //   .N..
                    //   ...E
                    //   W...
                    //   ..S.
                    // Rolling circle pattern (N,E,S,W).
                    float SamplesX[] = { -2.0f/16.0f,  6.0/16.0f, 2.0/16.0f, -6.0/16.0f };
                    float SamplesY[] = { -6.0f/16.0f, -2.0/16.0f, 6.0/16.0f,  2.0/16.0f };
                    ViewState->OnFrameRenderingSetup(ARRAY_COUNT(SamplesX), ViewFamily);
                    uint32 Index = ViewState->GetCurrentTemporalAASampleIndex();
                    SampleX = SamplesX[ Index ];
                    SampleY = SamplesY[ Index ];
                }
                else if( TemporalAASamples == 5 )
                {
                    // Compressed 4 sample pattern on same vertical and horizontal line (less temporal flicker).
                    // Compressed 1/2 works better than correct 2/3 (reduced temporal flicker).
                    //   . N .
                    //   W . E
                    //   . S .
                    // Rolling circle pattern (N,E,S,W).
                    float SamplesX[] = {  0.0f/2.0f,  1.0/2.0f,  0.0/2.0f, -1.0/2.0f };
                    float SamplesY[] = { -1.0f/2.0f,  0.0/2.0f,  1.0/2.0f,  0.0/2.0f };
                    ViewState->OnFrameRenderingSetup(ARRAY_COUNT(SamplesX), ViewFamily);
                    uint32 Index = ViewState->GetCurrentTemporalAASampleIndex();
                    SampleX = SamplesX[ Index ];
                    SampleY = SamplesY[ Index ];
                }
                else
                {
                    ViewState->OnFrameRenderingSetup(TemporalAASamples, ViewFamily);
                    uint32 Index = ViewState->GetCurrentTemporalAASampleIndex();

                    float u1 = Halton( Index + 1, 2 );
                    float u2 = Halton( Index + 1, 3 );

                    // Generates samples in normal distribution
                    // exp( x^2 / Sigma^2 )
                    
                    static auto CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.TemporalAAFilterSize"));
                    float FilterSize = CVar->GetFloat();

                    // Scale distribution to set non-unit variance
                    // Variance = Sigma^2
                    float Sigma = 0.47f * FilterSize;

                    // Window to [-0.5, 0.5] output
                    // Without windowing we could generate samples far away on the infinite tails.
                    float OutWindow = 0.5f;
                    float InWindow = FMath::Exp( -0.5 * FMath::Square( OutWindow / Sigma ) );
                    
                    // Box-Muller transform
                    float Theta = 2.0f * PI * u2;
                    float r = Sigma * FMath::Sqrt( -2.0f * FMath::Loge( (1.0f - u1) * InWindow + u1 ) );
                    
                    SampleX = r * FMath::Cos( Theta );
                    SampleY = r * FMath::Sin( Theta );
                }

                View.TemporalJitterPixelsX = SampleX;
                View.TemporalJitterPixelsY = SampleY;

                View.ViewMatrices.HackAddTemporalAAProjectionJitter(FVector2D(SampleX * 2.0f / View.ViewRect.Width(), SampleY * -2.0f / View.ViewRect.Height()));
            }

.....

     //设置视口矩阵,包括视口投影矩阵和转换矩阵


                ViewState->PrevViewMatrices.ApplyWorldOffset(View.OriginOffsetThisFrame);
                ViewState->PendingPrevViewMatrices.ApplyWorldOffset(View.OriginOffsetThisFrame);

......

 

}

 

2,可见性计算

void FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate& RHICmdList)

{

。。。。。。

//(1)初始化一系列用于可视化检测的缓冲区,(位数组,0和1代表是否可见
    int32 NumPrimitives = Scene->Primitives.Num();

    FPrimitiveViewMasks HasDynamicMeshElementsMasks;
    HasDynamicMeshElementsMasks.AddZeroed(NumPrimitives);

    FPrimitiveViewMasks HasDynamicEditorMeshElementsMasks;
        HasDynamicEditorMeshElementsMasks.AddZeroed(NumPrimitives);

    uint8 ViewBit = 0x1;
    for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ++ViewIndex, ViewBit <<= 1)
    {
        FViewInfo& View = Views[ViewIndex];

......
        View.PrimitiveVisibilityMap.Init(false,Scene->Primitives.Num());
。。。。。。

//(2)先用六棱锥进行筛选(a,b代表true或者false),不可见的对象的可视化检测缓冲区对应的比特位设置为0

int32  NumCulledPrimitivesForView = FrustumCull<true, false>(Scene, View);

........

//(3)对过小的线框直接剔除

//线框模式下,剔除所有的非线框

        if (View.Family->EngineShowFlags.Wireframe)
        {
            float ScreenSizeScale = FMath::Max(View.ViewMatrices.GetProjectionMatrix().M[0][0] * View.ViewRect.Width(), View.ViewMatrices.GetProjectionMatrix().M[1][1] * View.ViewRect.Height());
            for (FSceneSetBitIterator BitIt(View.PrimitiveVisibilityMap); BitIt; ++BitIt)
            {
                if (ScreenSizeScale * Scene->PrimitiveBounds[BitIt.GetIndex()].BoxSphereBounds.SphereRadius <= GWireframeCullThreshold)
                {
                    View.PrimitiveVisibilityMap.AccessCorrespondingBit(BitIt) = false;
                }
            }
        }

//(4)在非线框模式下,对于处于视口范围内,但是被其他对象遮挡的对象进行一次剔除

        if (!View.Family->EngineShowFlags.Wireframe)
        {
            int32 NumOccludedPrimitivesInView = OcclusionCull(RHICmdList, Scene, View);
            STAT(NumOccludedPrimitives += NumOccludedPrimitivesInView);
        }

//(5)根据所有的可见性位图,设置每个需要渲染的对象的可见性状况,即Hiddenflags


        FLODSceneTree& HLODTree = Scene->SceneLODHierarchy;

        if (HLODTree.IsActive())
        {
            QUICK_SCOPE_CYCLE_COUNTER(STAT_ViewVisibilityTime_HLOD);
            HLODTree.UpdateAndApplyVisibilityStates(View);
        }

。。。。

//(6)给每个对象返回自己是否可见的机会
        if (FPlatformProperties::SupportsWindowedMode() && ViewState && ViewState->IsViewParent())
        {
            for (FSceneDualSetBitIterator BitIt(View.PrimitiveVisibilityMap, View.PrimitiveDefinitelyUnoccludedMap); BitIt; ++BitIt)
            {
                ViewState->ParentPrimitives.Add(Scene->PrimitiveComponentIds[BitIt.GetIndex()]);
            }
        }

。。。。。。

//(7)获取所有动态对象的渲染信息
    GatherDynamicMeshElements(Views, Scene, ViewFamily, HasDynamicMeshElementsMasks, HasDynamicEditorMeshElementsMasks, MeshCollector);

.......

}

2.1对于第(2)步,剔除方式是Parrallefor线性剔除,而不是八叉树等树状结构


template<bool UseCustomCulling, bool bAlsoUseSphereTest>
static int32 FrustumCull(const FScene* Scene, FViewInfo& View)
{
.....

    ParallelFor(NumTasks, 
        [&NumCulledPrimitives, Scene, &View, MaxDrawDistanceScale](int32 TaskIndex)
        {

...
            for (int32 WordIndex = TaskWordOffset; WordIndex < TaskWordOffset + FrustumCullNumWordsPerTask && WordIndex * NumBitsPerDWORD < BitArrayNumInner; WordIndex++)
            {

.....


                for (int32 BitSubIndex = 0; BitSubIndex < NumBitsPerDWORD && WordIndex * NumBitsPerDWORD + BitSubIndex < BitArrayNumInner; BitSubIndex++, Mask <<= 1)
                {

....


                    if (DistanceSquared > FMath::Square(MaxDrawDistance + FadeRadius) ||
                        (DistanceSquared < Bounds.MinDrawDistanceSq) ||
                        (UseCustomCulling && !View.CustomVisibilityQuery->IsVisible(VisibilityId, FBoxSphereBounds(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.BoxExtent, Bounds.BoxSphereBounds.SphereRadius))) ||
                        (bAlsoUseSphereTest && View.ViewFrustum.IntersectSphere(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.SphereRadius) == false) ||
                        View.ViewFrustum.IntersectBox(Bounds.BoxSphereBounds.Origin, Bounds.BoxSphereBounds.BoxExtent) == false ||
                        (UseMonoCulling && Scene->Primitives[Index]->Proxy->RenderInMono()))
                    {
                        STAT(NumCulledPrimitives.Increment());
                    }

....


    return NumCulledPrimitives.GetValue();
 

}

3,完成可见性计算
void FSceneRenderer::PostVisibilityFrameSetup(FILCUpdatePrimTaskData& OutILCTaskData)

{

.......

//(1)对半透明对象进行排序,半透明对象的渲染由于涉及到互相遮挡,则必须按照从后往前的顺序来渲染,才能保证渲染结果的正确性,因此,必须在此时完成排序
        for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
        {        
            FViewInfo& View = Views[ViewIndex];

            View.TranslucentPrimSet.SortPrimitives();
            View.MeshDecalPrimSet.SortPrimitives();

            if (View.State)
            {
                ((FSceneViewState*)View.State)->TrimHistoryRenderTargets(Scene);
            }
        }

.....

//(2)对每个光照确定当前光照可见的对象列表,这里也是使用平截头体剔除,只需要测点光源和聚光灯,而平行光始终可见
    
        for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++)
        {        
            const FLightSceneProxy* Proxy = LightSceneInfo->Proxy;
            FViewInfo& View = Views[ViewIndex];
            FVisibleLightViewInfo& VisibleLightViewInfo = View.VisibleLightInfos[LightIt.GetIndex()];
            if (Proxy->GetLightType() == LightType_Point  
                || Proxy->GetLightType() == LightType_Spot)
            {
                const float Radius = Proxy->GetRadius();

                if (View.ViewFrustum.IntersectSphere(Proxy->GetOrigin(), Radius))
                {
                    if (View.IsPerspectiveProjection())
                    {
                        FSphere Bounds = Proxy->GetBoundingSphere();
                        float DistanceSquared = (Bounds.Center - View.ViewMatrices.GetViewOrigin()).SizeSquared();
                        float MaxDistSquared = Proxy->GetMaxDrawDistance() * Proxy->GetMaxDrawDistance() * GLightMaxDrawDistanceScale * GLightMaxDrawDistanceScale;
                        const bool bDrawLight = (FMath::Square(FMath::Min(0.0002f, GMinScreenRadiusForLights / Bounds.W) * View.LODDistanceFactor) * DistanceSquared < 1.0f)
                                                    && (MaxDistSquared == 0 || DistanceSquared < MaxDistSquared);
                            
                        VisibleLightViewInfo.bInViewFrustum = bDrawLight;
                    }
                    else
                    {
                        VisibleLightViewInfo.bInViewFrustum = true;
                    }
                }
            }
            else
            {
                VisibleLightViewInfo.bInViewFrustum = true;

....

//(3)初始化雾与大气的常量值
        InitFogConstants();

具体实现
void FSceneRenderer::InitFogConstants()
{
    float FogDensityOverride = -1.0f;
    float FogStartDistanceOverride = -1.

    for(int32 ViewIndex = 0;ViewIndex < Views.Num();ViewIndex++)
    {
        FViewInfo& View = Views[ViewIndex];
        InitAtmosphereConstantsInView(View);
        // set fog consts based on height fog components
        if(ShouldRenderFog(*View.Family))
        {

...

 

到这里为止,进行了重分配渲染目标和初始化视口两部分。估计看到这里,自己都要迷糊了。

总结下;

延迟渲染

void FDeferredShadingSceneRenderer::Render(FRHICommandListImmediate& RHICmdList)

一,按需要重新分配渲染目标
 1,void FSceneRenderTargets::AllocDummyGBufferTargets(FRHICommandList& RHICmdList)

    1.1, template<typename InitializerType,typename RHIRefType,typename RHIParamRefType> static RHIParamRefType TStaticStateRHI<typename InitializerType,typename RHIRefType,typename RHIParamRefType>::GetRHI();

    1.2,FGBufferResourceStruct::CreateUniformBuffer(GBufferResourceStruct, UniformBuffer_SingleFrame);

二,初始化视口(可以多个),包括确定可见性与设置阴影相关参数
1,bool FDeferredShadingSceneRenderer::InitViews(FRHICommandListImmediate& RHICmdList, struct FILCUpdatePrimTaskData& ILCTaskData, FGraphEventArray& SortEvents)

   1.1,预设置可见性
           void FSceneRenderer::PreVisibilityFrameSetup(FRHICommandListImmediate& RHICmdList)

       1.1.1,根据当前画质设置,设置TemporalAA的采样方式,同时确定采样位置,
                  1.1.1.1, uint32 FSceneViewState::GetCurrentTemporalAASampleIndex() const

                  1.1.1.2,void  FViewMatrices::HackAddTemporalAAProjectionJitter(const FVector2D& InTemporalAAProjectionJitter)  

        1.1.2,设置视口矩阵,包括视口投影矩阵和转换矩阵
                   void FViewMatrices::ApplyWorldOffset(const FVector& InOffset)

    1.2,可见性计算
           void FSceneRenderer::ComputeViewVisibility(FRHICommandListImmediate& RHICmdList)

          1.2.1,初始化一系列用于可视化检测的缓冲区,(位数组,0和1代表是否可见)

          1.2.2,用六棱锥进行筛选(a,b代表true或者false),不可见的对象的可视化检测缓冲区对应的比特位设置为0
         template<bool UseCustomCulling, bool bAlsoUseSphereTest>
         static int32 FrustumCull(const FScene* Scene, FViewInfo& View)

         1.2.3,线框模式下,对直接剔除,剔除所有的非线框和过小的线框

         1.2.4,在非线框模式下,对于处于视口范围内,但是被其他对象遮挡的对象进行一次剔除
               static int32 OcclusionCull(FRHICommandListImmediate& RHICmdList, const FScene* Scene, FViewInfo& View)

         1.2.5,根据所有的可见性位图,设置每个需要渲染的对象的可见性状况,即Hiddenflags
                     void FLODSceneTree::UpdateAndApplyVisibilityStates(FViewInfo& View)

         1.2.6,给每个对象返回自己是否可见的机会

         1.2.7,获取所有动态对象的渲染信息

              void FSceneRenderer::GatherDynamicMeshElements(
                         TArray<FViewInfo>& InViews, 
                          const FScene* InScene, 
                          const FSceneViewFamily& InViewFamily, 
                          const FPrimitiveViewMasks& HasDynamicMeshElementsMasks, 
                          const FPrimitiveViewMasks& HasDynamicEditorMeshElementsMasks, 
                          FMeshElementCollector& Collector)

        1.3,完成可见性计算
            void FSceneRenderer::PostVisibilityFrameSetup(FILCUpdatePrimTaskData& OutILCTaskData)

               1.3.1,对半透明对象进行排序,半透明对象的渲染由于涉及到互相遮挡,则必须按照从后往前的顺序来渲染,才能保                                   证渲染结果的正确性,因此,必须在此时完成排序
                          1.3.1.1,void FTranslucentPrimSet::SortPrimitives()
                          1.3.1.2,void FSceneViewState::TrimHistoryRenderTargets(const FScene* Scene)

               1.3.2,对每个光照确定当前光照可见的对象列表,这里也是使用平截头体剔除,只需要测点光源和聚光灯,而平行光始                          终可见
                     bool FConvexVolume::IntersectSphere(const FVector& Origin,const float& Radius) const

               1.3.3,初始化雾与大气的常量值
                      void FSceneRenderer::InitFogConstants()

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

延迟渲染到最终结果------1,2,分配渲染目标和初始化窗口(大象无形11.3.1) 的相关文章

随机推荐

  • angular路由参数路由跳转

    路由参数及跳转 本节介绍路由参数及跳转相关 准备工作 首先 我们需要将上一节的 CommentService UserService抽离成单独的文件 以便多处使用 ng g s components router study comment
  • Python入门_使用while循环计算1-100之间偶数和

    案例 计算1 100之间所有偶数的和 i 1 定义一个变量sum为0 用来存放和 sum 0 while i lt 100 每次sum和i相加 if i 2 0 sum i i 1 执行完之后 打印sum的值 print 1 100之间偶数
  • Nginx实现反向代理和负载均衡

    Nginx安装 本文章主要介绍下 如何使用Nginx来实现反向代理和负载均衡 Nginx安装和基础知识 可参考我的这篇文章 Nginx安装 Nginx实现反向代理 实现反向代理需要准备两台Nginx服务器 一台Nginx服务器A ip为 1
  • leetcode33. 搜索旋转排序数组

    整数数组 nums 按升序排列 数组中的值 互不相同 在传递给函数之前 nums 在预先未知的某个下标 k 0 lt k lt nums length 上进行了 旋转 使数组变为 nums k nums k 1 nums n 1 nums
  • 【Python编程】如何在 Jupyter Notebook 中切换虚拟环境

    如何在 Jupyter Notebook 中切换虚拟环境 一 操作步骤 1 首先切换到想要在 Jupyter Notebook 里使用的虚拟环境 conda activate 环境名称 2 安装 ipykernel conda instal
  • TCP详解(一)服务和首部介绍

    文章目录 引言 TCP的服务 TCP首部 引言 TCP全称传输控制协议 Transmission Control Protocol 它是一种传输层通信协议 提供了面向连接的 可靠的字节流服务 本文将会简要介绍TCP为应用层提供的服务以及TC
  • node基础之三:http 模块

    1 导入模块 const http require http 2 创建服务 const server http createServer request response gt 获取请求方法 request method 获取请求 url
  • 阿里云1核1G内存1M宽带可以支持多少IP访问量?

    阿里云1核CPU 1G内存 1M公网宽带云服务器够用吗 1M宽带可以支持多少IP的访问量 来说说1M宽带可以跑多少流量及1核1G服务器配置性能 1核 1G 1M宽带配置能跑多少IP 一般来讲 如果图片不多 每天3000PV是没问题的 如果将
  • 优秀的CobaltStrike插件推荐:编程

    优秀的CobaltStrike插件推荐 编程 CobaltStrike是一款功能强大的渗透测试工具 广泛应用于红队行动和网络安全评估 它的灵活性和可扩展性使得开发者可以编写自己的插件来增强其功能 在这篇文章中 我将向你推荐一些好用的Coba
  • java并发包:重入锁与Condition条件

    本文转载至 http blog csdn net a910626 article details 51900941 重入锁 这里介绍一下synchronized wait notify方法的替代品 或者说是增强版 重入锁 重入锁是可以完全替
  • redis--13--Jedis使用

    redis 13 Jedis使用 代码位置 https gitee com DanShenGuiZu learnDemo tree master redis learn jedis 1 redis conf 修改 允许远程连接 bind 1
  • Java异常-Exception

    一 异常介绍 基本概念 Java语言中 将程序执行中发生的不正常情况称为 异常 注 开发过程中的语法错误和逻辑错误不是异常 执行过程中所发生的异常事件可分为两大类 Error 错误 Java虚拟机无法解决的严重问题 如 JVM系统内部错误
  • 2023-05-18 题目

    2023 05 18 题目 1 String 字符串 String 不是基本数据类型 且是不能被继承的 因为string类被final修饰 源码 public final class String implements java io Se
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • qt实现opengl播放yuv视频

    qt使用opengl播放yuv视频 文章目录 qt使用opengl播放yuv视频 toc 1 实现效果 2 pro文件 3 xvideowidget h 4 xvideowidget cpp 更多精彩内容 个人内容分类汇总 1 实现效果 2
  • VS2022编译GDAL库报错: fatal error U1050: PROJ_INCLUDE should be defined. PROJ >= 6 is a required depende

    目录 场景复现 定位问题 解决方案 踩过的坑 场景复现 使用VS2022的Native Tools command prompt for 2022工具编译GDAL库时 报 fatal error U1050 PROJ INCLUDE sho
  • RTSP视频边缘计算网关EasyNVR在5G时代有什么运用价值?

    5G和互联网的发展在近几年一直被按下了加速键 物联网正在成为主流 毋庸置疑 云计算为越来越多智能设备的连接提供了基础 给我们生活带来了极大便利 而边缘计算是云计算物联当中的一个关键应用 当我们在考虑云计算带来的数据过度集中 信息传输堵塞问题
  • 2018年最好用的5个python网站开发框架

    python作为解释型脚本语言 是一种通用的编程语言 由于python社区拥有大量的库文件 框架和其他的一些实用工具 我们可以用python完成各种各样的任务 另外 由于python的代码构成和结构就像英语句子一样自然 这种语言的学习曲线也
  • Spring(三)-IOC使用

    目录 基于XML管理bean 入门案例 引入依赖 创建类HelloWorld 创建Spring的配置文件 在Spring的配置文件中配置bean 创建测试类测试 思路 获取bean 方式一 根据id获取 方式二 根据类型获取 方式三 根据i
  • 延迟渲染到最终结果------1,2,分配渲染目标和初始化窗口(大象无形11.3.1)

    版本不同 我这里延迟渲染是FDeferredShadingSceneRenderer类 即函数 void FDeferredShadingSceneRenderer Render FRHICommandListImmediate RHICm