Git Product home page Git Product logo

unreal_camera_mode's Introduction

Camera Photo in Unreal C++

Index

Introduction

This all starts because I wanted to make a photography game in Unreal with C++, but none of the information I found about it was what I needed, so with this tutorial, I will try to help anyone who wants to implement this mechanic in their game.

In this tutorial you will learn how to take screenshots, save them in the game (not on disk) and display them on screen. As I progress in my other project I will be uploading new features.

This is what you will be able to achieve with the tutorial:

CurrentState.mp4

Future changes to be implemented in this tutorial:

NewState.mp4

Credits

Much of what is going to be done in this tutorial is taken from this series of videos: https://www.youtube.com/watch?v=kD6-YhuxQNs&t

What I have done is to translate from Blueprints to C++.

Work Flow

Unreal Version and template

To implement this I work in the 5.2.1 version and use the FirstPerson template.

Folder Hierarchy

Code
  • PhotoTest
    • Private/Public
      • Components
      • GameMode
      • UI
      • Widgets
Unreal Editor
  • Content
    • Core
      • Camera
        • Material
      • GameMode
      • UI

Nomenclature

The variables are lowerCamelCase, and if they are class variables they will end with a _, will have the prefix Category = " Design | " to be able to search them better in the editor.

e.g:

	UPROPERTY(VisibleAnywhere, Category = "Design | example")
		int32 exampleVar_;

All classes start with PH_ to make the classes related to this project clearer and easier to find.

e.g:

PH_ExampleClas

Tutorial

It would be best to have a class that handles the whole camera, but let's take the character as the main entity for taking pictures.

For this tutorial we will need to have 2 inputs already associated, one to take pictures and one to navigate between them.

The USceneCaptureComponent2D

Create a input to manage de shoot.

In order to capture an image from our camera we will need a USceneCaptureComponent2D, this component will give us everything we need to capture the scene and modify it.

In this case I put the scene capture in the Character base template.

in the h

class USceneComponent;

class APhotoTestCharacter : public ACharacter
{

private:

	UPROPERTY(VisibleAnywhere, Category = "Design | Capture")
		USceneCaptureComponent2D* sceneCapture_;

in the cpp

#include "Components/SceneCaptureComponent2D.h"
...
APhotoTestCharacter::APhotoTestCharacter()
{
	
	...template code...
	
//Attatch with the camare we want to follow and have the focus.
	sceneCapture_= CreateDefaultSubobject<USceneCaptureComponent2D>(TEXT("Photo"));
	sceneCapture_->SetupAttachment(FirstPersonCameraComponent);

}

You should get this in the blueprint.

01

Remember to do a dll cleanup if it doesn't show up, touching the constructor gives problems.

To save the image that we are taking, we will need a TextureRenderTarget2D(Render Target), can be created before or directly from the same tab( I use this) and name it CurrentRenderTarget .

02

Enter the texture and change the resolution to make it look good.

16

Now we create a function to be called when we press a button and we will make our first step to make captures.

In the h

UFUNCTION()
	void TakePicture(const FInputActionValue& Value);

In the cpp

void APhotoTestCharacter::TakePicture(const FInputActionValue& Value){
	sceneCapture_->CaptureScene();
}

Compile and It's time to test if it works.

03

Display picture on screen

Now every picture we take will be saved in that texture. But if we want to be able to take more pictures, save them and display them, we will need to save them in an array of RenderTextures.

But before that, we are going to create and configure a widget to manage the display.

Texture and material

The way we are doing it, we are going to need a material containing the RenderTarget, so let's create one and generate an instance of it. drag the texture and link it to the color, don't forget to parameterize and give it a name.

For this to be displayed on the screen we need the domain material to be a User Interface.

4,1

(I took this photo at the end of the tutorial, that's why the texture looks black). 04

05

Camera Widget

Let's create a class that inherits from UserWidget to display the pictures.

06

For now we only need one variable.

In the h

//Bind widget to use in the blueprint
public:
UPROPERTY(BlueprintReadOnly, meta = (BindWidget))
		class UImage* photoImage_;

Now create a Blueprint of this widget.

07

Create a canvas and insert an image. The most important thing is that it has the same name as the variable of our c++ class, which in my case is photoImage_.

08

In the image, in the appearance section, let's change the brush to the material instance we create before.

09

You can test that now the photos you take are saved in the material and in the widget image.

The HUD wrapper

We create a class that inherits from HUD and we will use it as a wrapper for the CameraWidget, for now, it will help us to display the widget on screen.

In the h:

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "Widgets/PH_CameraWidget.h"
#include "Engine/TextureRenderTarget2D.h"
#include "PH_HUD.generated.h"


UCLASS()
class PHOTOTEST_API APH_HUD : public AHUD
{
	GENERATED_BODY()

public:

	void BeginPlay() override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design")
		TSubclassOf<UPH_CameraWidget> cameraBP_;

	UPROPERTY()
		UPH_CameraWidget* cameraWidget_;
	
};

In the cpp:

#include "Widgets/PH_CameraWidget.h"
#include "Engine/TextureRenderTarget2D.h"


void APH_HUD::BeginPlay() {

	cameraWidget_ = CreateWidget<UPH_CameraWidget>(PlayerOwner, cameraBP_);

	if (cameraWidget_) {
		cameraWidget_->AddToViewport();
	}

}

And in the blueprint change the Camera BP to the CameraWidget BP.

11

Connect all with a game mode

We will create a class that inherits from GameMode and we will create a blueprint from it.

10

In the blueprint change HUD Class and Default Pawn Class to you BP.

12

Now in Project Settings->Maps & Modes change default GameMode to you BP.

13

And finally in the World Settings change the GameMode Override.

14

SceneCapture settings

If you run the game you should be able to see your image on the screen, but it looks more like a video, so let's change some settings in Scene Capture component.

Uncheck Capture every frame and Capture in motion and check Always persist rendering state (try unchecking to see the difference).

15

Save images in game

Now we are going to save all the photos we take and browse through them.

In the CameraWidget h:

		// Material we are going to use to create a dynamic material from it
		UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Image")
			class UMaterialInterface* baseMaterial_;

		// Function to set the texture of the image
		UFUNCTION(BlueprintCallable, Category = "Image")
			void SetImageTexture(UTextureRenderTarget2D* Texture);

In the cpp:

void UPH_CameraWidget::SetImageTexture(UTextureRenderTarget2D* Texture)
{
    if (photoImage_ && Texture)
    {
        
        // Create a dynamic material instance and set its texture parameter
        UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(baseMaterial_, this);
      
        
        DynamicMaterial->SetTextureParameterValue("PhotoTexture", Texture);

        photoImage_->SetBrushFromMaterial(DynamicMaterial);
    }

}

Now in the HUD h:

UFUNCTION()
		void SetImageTexture(UTextureRenderTarget2D* Texture);

In the cpp:

void APH_HUD::SetImageTexture(UTextureRenderTarget2D* Texture) {
	cameraWidget_->SetImageTexture(Texture);
}

Now we are going to change our TakePictures function, but for that we will need to some things.

In the h:

public:

	// To pass to the camera widget the material that we will use to create dynamic materials.
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Design")
		class UMaterialInterface* baseMaterial_;
		
private:

	// Link to pass the screenshots to the viewport
	UPROPERTY(VisibleAnywhere, Category = "Design | HUD")
		class APH_HUD* hud_;
		
	// Array to save all images
	UPROPERTY(VisibleAnywhere, Category = "Design | Capture")
			TArray<UTextureRenderTarget2D*> targets_;

In the cpp:

#include "Engine/TextureRenderTarget2D.h"
#include "UI/PH_HUD.h"
#include "Kismet/GameplayStatics.h"

...
void APhotoTestCharacter::BeginPlay()
{
	... Template Code ...

	hud_ = Cast<APH_HUD>(UGameplayStatics::GetPlayerController(GetOwner(), 0)->GetHUD());
	
	hud_->cameraWidget_->baseMaterial_ = baseMaterial_;
}

void APhotoTestCharacter::TakePicture(const FInputActionValue& Value){

	// Texture dimensions
	int32 Width = 1920;
	int32 Height = 1080;

	// Create render target 2D
	UTextureRenderTarget2D* MyRenderTarget = NewObject<UTextureRenderTarget2D>(this, UTextureRenderTarget2D::StaticClass());
	MyRenderTarget->InitAutoFormat(Width, Height);
	MyRenderTarget->UpdateResourceImmediate(true);

	// We will save the output of sceneCapture_ in this texture
	sceneCapture_->TextureTarget = MyRenderTarget;

	// Other settings you want to change on the SceneCaptureComponent2D
	
	
	// Capture the scene
	sceneCapture_->CaptureScene();

	// We add it to our texture array and pass it to the hud to handle the change.
	targets_.Add(MyRenderTarget);
	hud_->cameraWidget_->SetImageTexture(MyRenderTarget);

}

And now we just need to be able to switch between images.

In the h:

private:

		
	// Iterator to switch between images
	UPROPERTY(VisibleAnywhere, Category = "Design | Capture")
		int32 ite_;
		
	// Function to switch between images, REMEMBER TO CREATE A NEW INPUT TO TO LAUNCH THIS FUNCTION
	UFUNCTION()
		void NextImage(const FInputActionValue& Value);

In the cpp:

void APhotoTestCharacter::NextImage(const FInputActionValue& Value) {

	ite_ = (ite_ + 1) % targets.Num();

	hud->cameraWidget_->SetImageTexture(targets[ite_]);

}

You already have a camera!

Surely you have noticed that at the 4th picture you take, you get a shadow map error, and the pictures come out with black lines. In order to fix this, we will need to set r.Shadow.Virtual.Enable to 0 ( 1 to activate).

We have 2 ways, from the DefaultEngine.ini file (that we can find in the Config folder). engine

or from the command line in the editor to see it while we are playing.

comandos

But by doing this we will lose some quality in the shadows.

Fin

And that would be it! Now you should be able to take pictures, save them in the game and navigate through a visual interface. If you have any questions about the tutorial or how it has been explained, please contact me.

unreal_camera_mode's People

Contributors

cervath avatar

Stargazers

Nacho avatar mordi_18 avatar  avatar marcos avatar yuni avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.