Blog

DLSS 2.0 w Unreal Engine 4.26

NVIDIA DLSS – Deep Learning Super Sampling

To przełomowa technologia renderowania z wykorzystaniem sztucznej inteligencji AI, która wynosi wierność oraz optymalizację wizualną na zupełnie nowy poziom dzięki dedykowanym procesorom Tensora Core AI w procesorach graficznych GeForce RTX. DLSS wykorzystuje moc sieci neuronowej do Deep Learningu, aby zwiększyć liczbę klatek na sekundę i generować dokładne, ostre obrazy w produkcjach.

To rozwiązanie AA zastępuje TAA i dlatego materiały typu ditered nie nadają się obecnie renderować tego samego DLSS. Pamiętaj, że sam aliasing występuje w wyniku rasteryzacji sceny na piksele. Mniej pikseli powoduje wyższy aliasing, więc fakt, że DLSS faktycznie naprawia większość aliasingu podczas gdy zapewnione jest znacznie niższe wejście niż natywne – jest to całkiem niesamowite.

Twórcy gier mają teraz dodatkowy zapas wydajności aby zmaksymalizować ustawienia Ray Tracingu czy zwiększyć rozdzielczość wyjściową. Główne funkcje to:

  • Jakość oraz wyższa wydajność – zapewnia jakość porównywalną z natywną rozdzielczością, a czasem nawet lepszą, podczas gdy konwencjonalnie renderuje tylko ułamek pikseli
  • Sam DLSS umożliwia wybór kilku trybów jakości obrazu od jakości po ultra wydajność. Tryb Performance zapewnia do 4X super rozdzielczość AI (czyli 1080p -> 4K), podczas gdy nowy tryb umożliwia do 9X super rozdzielczości AI czyli (1440p ->8K)

Plugin możemy pobrać bezpośrednio tutaj, natomiast dokumentacje instalacji znajdziemy pod tym linkiem.

W viewport otrzymamy opcję ustawiania presetów:

Widzimy tutaj 5 presetów skoncentrowanych na wydajności i jakości

Ustawienia projektu znajdziemy pod NVIDIA DLSS oraz odpowiedniku (Local)

Możemy również na testować to w GPU Visualizer wpisując komendę Profile GPU.

Macro UFUNCTION()

UFUNCTION () służy do implementacji funkcji w C ++. Możliwe jest tworzenie funkcji C ++, które będą wywoływane w edytorze Blueprints. Możliwe jest również wywołanie w C ++ funkcji, które zostały zaimplementowane w Blueprints.

Blueprint może reprezentować funkcję C ++ na trzy różne sposoby. Zdarzenia są zaimplementowane jako funkcje c ++, który nie zwraca wartości, to znaczy ich typ zwracany jest typu “void”:

Funkcja Blueprint z pinem wykonawczym jest implementowana jako Funkcja C ++, która nie jest oznaczona jako Blueprint “Pure”: 

Jeśli funkcja C ++ jest oznaczona za pomocą Blueprint Pure , jest reprezentowana jako funkcja bez pinu wykonywania, nie może modyfikować danych instancji i może być używana w wyrażeniach. Jest szeroko stosowana w funkcjach typu Get.

Porozmawiajmy teraz o specyfikatorach funkcji . Po pierwsze, każda UFUNCTION() musi mieć specyfikator Category, aby funkcja była poprawnie wyświetlana w menu kontekstowym Blueprint.

Aby funkcja UFUNCTION() została użyta w wykresie Blueprints, musi mieć jeden z tych dwóch specyfikatorów:

  • BlueprintCallable : pojawi się jako funkcja Blueprint z kodem wykonawczym.
  • BlueprintPure : Pojawi się jako pure function.

Możliwe jest zdefiniowanie funkcji C ++, która zostanie zaimplementowana w Blueprint. Aby to zrobić, użyj jednego z tych dwóch specyfikatorów w funkcji  UFUNCTION () :

  • BlueprintImplementableEvent : Funkcja jest zaimplementowana tylko w Blueprint. Jeśli zostanie znaleziona implementacja C ++, wygeneruje błąd kompilacji.
  • BlueprintNativeEvent : umożliwia implementację wersji C ++ funkcji, która będzie używana, jeśli wersja Blueprint nie zostanie zaimplementowana. Wersja C ++ musi mieć nazwę funkcji oraz przyrostek  _Implementation.

Jeśli zwracanym typem funkcji C ++ jest void , zostanie zaimplementowany jako Event w Blueprints. Jeśli funkcja C ++ zwróci wartość, zostanie zaimplementowana jako funkcja Blueprint. 

Sprawdzimy teraz te wszystkie specyfikatory w akcji w przykładowym użyciu.

Przykładowe użycie:

Utwórz klasę C ++ o nazwie TestUFunction, używając klasy Actor jako klasy nadrzędnej. W pliku TestUFunction.h dodaj deklaracje czterech funkcji poniżej funkcji Tick ​​() , jak pokazano w tym kodzie:

...

public:	
  // Called every frame
  virtual void Tick(float DeltaTime) override;
	
  UFUNCTION(BlueprintCallable, Category = Tutorial)
  int32 WelcomeMsg(FString PlayerName);
	
  UFUNCTION(BlueprintPure, Category = Tutorial)
  float CalculateDamage(float PowerAttack, float DefenseValue);
	
  UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = Tutorial)
  void TreasureFound();
	
  UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = Tutorial)
  FString NativeExample();
};

W pliku TestUFunction.cpp dodaj implementację trzech funkcji pokazanych poniżej: 

...

int32 ATestUFunction::WelcomeMsg(FString PlayerName)
{
  FString Message = FString::Printf(TEXT("Welcome %s."), *PlayerName);
  
  if(GEngine)
  {
    GEngine->AddOnScreenDebugMessage(-1, 10, FColor::Red, Message);
  }
  
  //Returns the number of characters in PlayerName
  return PlayerName.Len();
}

float ATestUFunction::CalculateDamage(float PowerAttack, float DefenseValue)
{
  return (PowerAttack * 10) / DefenseValue;
}

FString ATestUFunction::NativeExample_Implementation()
{
  return TEXT("NativeExample: C++ version");
}

Zauważ, że funkcja TreasureFound () nie została zaimplementowana. Dzieje się tak, ponieważ zostanie zaimplementowana tylko w Blueprint ze względu na specyfikator BlueprintImplementableEvent . Funkcja NativeExample () ma specyfikator BlueprintNativeEvent, który umożliwia jej implementację w językach C ++ i Blueprint. Wersja C ++ została zaimplementowana pod nazwą NativeExample_Implementation () .

Skompiluj kod C ++. Utwórz Blueprint na podstawie klasy TestUFunction  C ++  . Aby to zrobić, kliknij prawym przyciskiem myszy klasę TestUFunction i wybierz opcję  Utwórz klasę Blueprint na podstawie TestUFunction .

Kliknij prawym przyciskiem myszy Blueprint Event Graph i zobacz, że cztery funkcje zadeklarowane w C ++ są wymienione w kategorii Tutorial, jak pokazano na poniższym obrazku. Pojawiają się na tej liście, ponieważ mają specyfikator BlueprintCallable lub BlueprintPure .

Nazwiemy cztery funkcje w wydarzeniu BeginPlay w Blueprint . Dodaj funkcje do wykresu zdarzeń, jak pokazano na poniższym obrazku.

Przed testowaniem musimy zaimplementować funkcję TreasureFound () w Blueprint. Na karcie My Blueprint kliknij przycisk Override obok pozycji Funkcje . Zwróć uwagę, że na liście pojawiają się funkcje Treasure Found i Native Example . Kliknij Treasure Found

Zwracany typ funkcji TreasureFound () to void , więc jest zaimplementowany jako Event w Blueprint. Dodaj funkcję Print String z komunikatem:

Skompiluj Blueprint i dodaj instancję na poziomie. Uruchom grę i zobacz komunikaty na ekranie. Każda linia przedstawia wykonanie jednej z funkcji.

Ponieważ wersja Blueprint funkcji NativeExample () nie została zaimplementowana, użyto wersji C ++. Aby ukończyć ten przykład, zaimplementujemy wersję Blueprint NativeExample () .

Na karcie My Blueprint kliknij przycisk Override obok pozycji Functions i wybierz opcję Native Example . Jest implementowana jako funkcja, ponieważ ma wartość zwracaną. Zobacz węzeł Parent: Native Example na poniższym zrzucie ekranu. Ten węzeł wykona wersję C ++ NativeExample () . Pozwala to na dodanie funkcji w Blueprint do tej funkcji. Ale jeśli chcesz, aby wersja Blueprint zastąpiła wersję C ++, po prostu usuń ten węzeł. 

W naszym przykładzie usunę węzeł Parent: Native Example i napisze komunikat w parametrze  Return Value .

Skompiluj Blueprint i rozpocznij grę. Zwróć uwagę, że wywołano tylko wersję Blueprint NativeExample(). 


Źródło:https://romeroblueprints.blogspot.com/2020/10/the-ufunction-macro.html

Shape Traces

Tracing można również wykonać za pomocą określonych kształtów. Istnieją funkcje śledzenia dla kształtów box, capsule czy sphere shapes, ale te funkcje są droższe dla wydajności w wykonaniu niż przy liniach.


Dla wszystkich tych kształtów istnieją funkcje do śledzenia według kanału i typu obiektu. Istnieją również funkcje dla pojedynczych trafień lub wielu trafień.

Line Trace By Channel

Funkcja LineTraceByChannel sprawdza kolizję wzdłuż zdefiniowanej linii za pomocą kanału śledzenia, którym może być „Visibility” lub „Camera”, i zwraca strukturę Hit Result z danymi dla pierwszego trafienia Actor w teście kolizji.


Punkty wejścia:

  • Start oraz End: wektory lokalizacji definiujące początek i koniec linii, która ma być użyta do testu zderzenia.
  • Trace Channel: kanał używany do testu kolizji. Może to być „Widoczność” lub „Kamera”.
  • Trace Complex, Actors to Ignore, Draw Debug Type: te parametry są używane do debuowania

Break Hit Result

Kiedy funkcja śledzenia koliduje z czymś, zwraca jedną lub więcej struktur Hit Result. Break Hit Result może być użyty do uzyskania dostępu do elementów wyniku trafienia, jak widać na obrazku po prawej stronie.
Niektóre elementy Break Hit Result:

  • Blocking Hit: wartość logiczna Boolean, która wskazuje, czy nastąpiło trafienie blokujące.
  • Location: lokalizacja trafienia
  • Normal: normalny wektor trafienia w przestrzeni świata
  • Hit Actor: Odniesienie do Aktora trafionego przez trace

Blueprint Interface

Blueprint Interface (BPI) zawiera tylko definicje funkcji, bez implementacji.
Jeśli klasa Blueprint implementuje BPI, używa dostarczonej definicji, a następnie implementuje własną logikę dla tej funkcji.

Aby utworzyć nowy Blueprint Interface, kliknij Create New w Content Browser a nastepnie z Blueprints wybierz Blueprint Interface

Aby dodać Blueprint Interface do klasy Blueprint, kliknij przycisk Class Settings na pasku narzędzi w edytorze Blueprints. W sekcji Interfejsy w panelu Szczegóły kliknij przycisk Dodaj i wybierz klasę Blueprint Interface.

W przykładzie powyżej klasy Third Person Character mamy odziedziczony interface “Nav Agent Interface” od klasy Character

Istnieje kilka funkcji narzędziowych związanych z interfejsami Blueprint.

  • Does Implement Interface: sprawdza czy konkretny obiekt ma zaimplementowany Blueprint Interface
  • Get All Actors with Interface: znajduje wszystkich aktorów na bieżącym poziomie, które mają wdrożony Blueprint Interface

Random Numbers From Streams

Możliwe jest utworzenie sekwencji powtarzalnych liczb losowych za pomocą zmiennej Random Stream.


Aby to zrobić, utwórz zmienną typu „Random Stream”. Ustaw właściwość Initial Seed w sekcji Default Value panelu Details dla zmiennej.


Wartość właściwości Initial Seed definiuje sekwencję liczb losowych.

Random Numbers

Istnieją funkcje liczb losowych, które zwracają losową wartość. Parę najważniejszych z nich poniżej:

  • Random Integer: zwraca liczbę całkowitą z przedziału od „0” do „Max – 1”.
  • Random Integer in Range: Zwraca liczbę całkowitą z przedziału od „Min” do „Max”.
  • Random Float: Zwraca wartość zmiennoprzecinkową z przedziału od „0” do „1”.
  • Random Float in Range: Zwraca wartość zmiennoprzecinkową między „Min” i „Max”.

Save Game

Aby zapisać grę i jej zmienne, które będą przechowywane w naszym projekcie, muszą zostać określone w zmiennych typu Blueprint typu „SaveGame”.


Pierwszym krokiem do zapisywania i ładowania gier za pomocą Blueprints jest utworzenie nowego schematu przy użyciu „SaveGame” jako klasy nadrzędnej.

Funkcja Create Save Game Object tworzy Save Game Object na podstawie klasy Save Game.


Informacje, które mają zostać zapisane, zostaną zapisane w zmiennych tego obiektu.

Funkcja Save Game to Slot zapisuje zawartość obiektu Save Game Object do pliku na dysku.

Funkcja Does Save Game Exists, sprawdza, czy zapis gry istnieje w podanym parametrze Slot Name.


Jest to przydatny test przed próbą załadowania zapisanej gry.

Funkcja Load Game from Slot ładuje zawartość contentu i tworzy obiekt Save Game z zawartością.


Parametr wyjściowy Return Value jest odniesieniem do ogólnego obiektu Save Game, aby uzyskać dostęp do zmiennych, konieczne jest odniesienie do właściwego Save Game Blueprint.

Funkcja Delete Game in Slot służy do usuwania danych zapisu gry w slocie.


Parametr “Return Value” ma wartość „true”, jeśli plik został znaleziony i usunięty.

Retriggerable Delay

Funkcja Retriggerable Delay wykonuje czynności związane z pinem Completed tylko po upływie czasu określonego w parametrze Duration.


Różnica między funkcjami Retriggerable Delay i Delay polega na tym, że wartość odliczania parametru Duration zostanie zresetowana, jeśli funkcja Retriggerable Delay zostanie ponownie wywołana.