• ue4 Widget to RenderTarget


      需求是这样的,飞机机舱的mfcd,也就是3D UI显示,通常我们会使用world widget,不过widget要贴附到模型上,效果并不好。

      

      然后见过用材质做的,但当显示内容很复杂时,这种做法就很难进行下去。

      我的做法是将widget渲染到renderTarget,然后材质使用该renderTarget赋予模型,效果不错。

      1.新建组件FlightInstrumentSystem:  

    #pragma once
    
    #include "CoreMinimal.h"
    #include "System/FlightSubSystem.h"
    #include "FlightInstrumentSystem.generated.h"
    
    USTRUCT(BlueprintType)
    struct FInstrumentConfig
    {
       GENERATED_USTRUCT_BODY()
    
          UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          FString WidgetName;
       /*改widget的index 每个widget的index应该都是独一无二的,这样在座舱按键输入时才能找到正确的widget*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          FString WidgetIndex;
       /*显示屏是否打开  True为通电就启动*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          bool bOn;
       /*多功能显示器widget*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          TSubclassOf<class UFlightInstrumentContainer> WidgetClass;
       /*widget大小*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          FVector2D DrawSize;
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          FVector2D SeparateWindowDrawSize;
       /*该UI所要渲染到的目标*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          class UTextureRenderTarget2D* RenderTarget;
       /*显示屏在默认状态下颜色*/
       UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator")
          FLinearColor DefaultColor;
       /*widget实例化*/
       UPROPERTY(BlueprintReadOnly, Category = "FlightSimulator")
          class UFlightInstrumentContainer* InstrumentWidget;
       /*独立窗口是否打开*/
       bool bSeparateWindowsOn;
       /*独立窗口句柄*/
       TSharedPtr<SWindow> SeparateWindow;
    
       FInstrumentConfig()
       {
          WidgetName = TEXT("MFCD");
          WidgetIndex = TEXT("0");
          bOn = false;
          InstrumentWidget = nullptr;
          DrawSize = FVector2D(1000, 1600);
          SeparateWindowDrawSize = DrawSize / 2;
          RenderTarget = nullptr;
          DefaultColor = FLinearColor(0, 0.026042, 0.001792, 0);
          bSeparateWindowsOn = false;
          SeparateWindow = nullptr;
    
       }
    };
    
    
    /**
     *    多功能显示器系统
     */
    UCLASS(ClassGroup = (FlightSimulator), meta = (BlueprintSpawnableComponent))
    class FLIGHTSIMULATOR_API UFlightInstrumentSystem
    {
       GENERATED_UCLASS_BODY()
    
          virtual void BeginPlay() override;
        virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; /*打开一个独立的窗口用于显示UI*/ UFUNCTION(BlueprintCallable, Category = "FlightSimulator|Instrument") void ToggleSeparateUIWindowOnOff(FString WidgetIndex); public: UPROPERTY(EditDefaultsOnly, Category = "FlightSimulator") TArray<FInstrumentConfig> InstrumentConfig; };

      FlightInstrumentSystem.cpp  

    void UFlightInstrumentSystem::BeginPlay()
    {
       Super::BeginPlay();
    
       for (FInstrumentConfig& config : InstrumentConfig)
       {
          if (config.WidgetClass)
          {
             config.InstrumentWidget = CreateWidget<UFlightInstrumentContainer>(UGameplayStatics::GetPlayerController(this, 0), config.WidgetClass);
             config.InstrumentWidget->AddToViewport();
             //make widget out of screen
             config.InstrumentWidget->SetPositionInViewport(FVector2D(3000.0f, 3000.0f));
          }
          if (config.RenderTarget)
          {
             UKismetRenderingLibrary::ClearRenderTarget2D(this, config.RenderTarget, config.DefaultColor);
          }
       }
    }

      widget to rendertarget

    void UFlightInstrumentSystem::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
    {
       Super::TickComponent();
    
       for (FInstrumentConfig& config : InstrumentConfig)
       {
          if (config.bOn && config.InstrumentWidget && config.RenderTarget)
          {
             //不起作用 想透明 需在引擎中设置RT为透明
             //UKismetRenderingLibrary::ClearRenderTarget2D(this, config.RenderTarget, config.DefaultColor);
             UFlightBlueprintFunctionLibrary::WidgetRenderToTextureRenderTarget(config.RenderTarget, config.InstrumentWidget, config.DrawSize, GetWorld()->DeltaTimeSeconds);
    
          }
       }
    
    }
    

     

    WidgetRenderToTextureRenderTarget方法:
    bool UFlightBlueprintFunctionLibrary::WidgetRenderToTextureRenderTarget(UTextureRenderTarget2D* TextureRenderTarget, UUserWidget* const Widget, const FVector2D& DrawSize, const float DeltaTime)
    {
       // As long as the slate application is initialized and the widget passed in is not null continue...
       if (FSlateApplication::IsInitialized() && Widget != nullptr)
       {
          // Get the slate widget as a smart pointer. Return if null.
          TSharedPtr<SWidget> SlateWidget(Widget->TakeWidget());
          if (!SlateWidget) return false;
          // Create a new widget renderer to render the widget to a texture render target 2D.
          FWidgetRenderer* WidgetRenderer = new FWidgetRenderer(true);
          if (!WidgetRenderer) return false;
          // Update/Create the render target 2D.
          //TextureRenderTarget = WidgetRenderer->DrawWidget(SlateWidget.ToSharedRef(), DrawSize);
    
          WidgetRenderer->DrawWidget(TextureRenderTarget, SlateWidget.ToSharedRef(), DrawSize, DeltaTime);
    
          /* TSharedRef<SWidget> ref = Widget->TakeWidget();
           WidgetRenderer->DrawWidget(TextureRenderTarget, ref, DrawSize, DeltaTime);*/
    
          return true;
       }
       return false;
    }
    

      独立窗口显示

      

    void UFlightInstrumentSystem::ToggleSeparateUIWindowOnOff(FString WidgetIndex)
    {
       CHECK_FALSE_RETURN(GetIsSystemRunning());
       for (FInstrumentConfig& config : InstrumentConfig)
       {
          if (config.WidgetIndex != WidgetIndex) continue;
          if (config.InstrumentWidget && config.bOn)
          {
             if (config.bSeparateWindowsOn)
             {
                //关闭独立窗口
                   // Destroy window
                if (config.SeparateWindow.Get() != nullptr)
                {
                   if (GetWorld()->WorldType != EWorldType::Game)
                   {
                      config.SeparateWindow->RequestDestroyWindow();
                   }
                   else
                   {
                      config.SeparateWindow->DestroyWindowImmediately();
                   }
                   config.bSeparateWindowsOn = false;
                }
             }
             else
             {
                //打开独立窗口 
                const FSlateBrush* RT= new FSlateImageBrush((UObject*)config.RenderTarget, config.DrawSize);
             
                // 建立窗口
                TSharedPtr<SWindow> MainWindow = SNew(SWindow)
                   .ClientSize(config.SeparateWindowDrawSize)
                   .SizingRule(ESizingRule::FixedSize)
                   .Title(FText::FromString(config.WidgetName))
                   .CreateTitleBar(true)
                   .SupportsMaximize(false)
                   .SupportsMinimize(false)
                   .IsTopmostWindow(true)
                   [
                      SNew(SOverlay)
                      + SOverlay::Slot()
                   .HAlign(HAlign_Fill)
                   .VAlign(VAlign_Fill)
                   [
                      SNew(SImage)
                      .Image(RT)
                   ]
                   ];
    
    
    
                FSlateApplication::Get().AddWindow(MainWindow.ToSharedRef());
                config.SeparateWindow = MainWindow;
                config.bSeparateWindowsOn = true;
    
             }
          }
       }
    }
    

      效果:

      FlightInstrumentSystem组件:

      

       模型只需要在屏幕材质上将上边的RenderTarget应用就可以,不需要其他操作

      

       

     

      

     

      

  • 相关阅读:
    2016某天闲谈
    APP测试入门篇之APP基础知识(001)
    windows服务器下frp实现内网穿透
    nginx使用与配置
    spring boot 实现优雅的关闭
    spring boot 自定义sql分页查询
    java获取类加载路径和项目根路径的5种方法
    linux下 启动node 和关闭node
    docker 安装 fastdfs
    docker 常用命令和常用容器启动
  • 原文地址:https://www.cnblogs.com/LynnVon/p/14928013.html
Copyright © 2020-2023  润新知