利用第三方后期处理材质(PostProcess Material)对物体进行描边【UE4】【C++】
发布日期:2021-07-01 05:53:50 浏览次数:2 分类:技术文章

本文共 6860 字,大约阅读时间需要 22 分钟。

 

效果图:

 

第一步,创建C++ Basic Code

 

第二步,定义键盘和鼠标输入的映射

 

第三步,修改 Rendering 中的 Custom Depth - Stencil Pass

 

第四步,找到GlobalPostProcessVolume [如果没有的话自行拖放一个PostProcessVolume组件] 

 

将 unbound 勾选上

 

再修改 Blendables 为 PPI_OutlineColored

 

 

完整代码如下:

MyPlayer.h

 

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "GameFramework/Character.h"#include "MyPlayer.generated.h"UCLASS()class OUTLINECPLUSPLUS_API AMyPlayer : public ACharacter{	GENERATED_BODY()public:	// Sets default values for this character's properties	AMyPlayer();	void MoveForward(float val);	void MoveRight(float val);	void LookYaw(float val);	void LookPitch(float val);	void Use();	class AInteractableActor* FindFocusedActor();	void HandleHighlight();	// Called when the game starts or when spawned	virtual void BeginPlay() override;		// Called every frame	virtual void Tick( float DeltaSeconds ) override;	// Called to bind functionality to input	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;private:	UPROPERTY(EditDefaultsOnly)	float InteractionDistance = 300.f;	// 交互的范围	class AInteractableActor* FocusedActor;	// 用于 LineTraceSingleByChannel	FCollisionQueryParams TraceParams;};

 

MyPlayer.cpp

 

 

 

// Fill out your copyright notice in the Description page of Project Settings.#include "InteractableActor.h"#include "MyPlayer.h"// Sets default valuesAMyPlayer::AMyPlayer(){ 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.	PrimaryActorTick.bCanEverTick = true;	TraceParams = FCollisionQueryParams(FName(TEXT("TraceParams")), false, this);	TraceParams.bTraceComplex = false;	TraceParams.bTraceAsyncScene = false;	TraceParams.bReturnPhysicalMaterial = false;}// Called when the game starts or when spawnedvoid AMyPlayer::BeginPlay(){	Super::BeginPlay();	}// Called every framevoid AMyPlayer::Tick( float DeltaTime ){	Super::Tick( DeltaTime );	if (Controller && Controller->IsLocalController())	{		HandleHighlight();	}}// Called to bind functionality to inputvoid AMyPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent){	Super::SetupPlayerInputComponent(PlayerInputComponent);	InputComponent->BindAxis("MoveForward", this, &AMyPlayer::MoveForward);	InputComponent->BindAxis("MoveRight", this, &AMyPlayer::MoveRight);	InputComponent->BindAxis("LookYaw", this, &AMyPlayer::LookYaw);	InputComponent->BindAxis("LookPitch", this, &AMyPlayer::LookPitch);	InputComponent->BindAction("Use", IE_Pressed, this, &AMyPlayer::Use);}// 前后移动void AMyPlayer::MoveForward(float val){	FRotator Rotation(0, GetActorRotation().Yaw, 0);	// Roll, Yaw, Pitch	FVector forward = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);	AddMovementInput(forward, val);}// 左右移动void AMyPlayer::MoveRight(float val){	FRotator Rotation(0, GetActorRotation().Yaw, 0);	// Roll, Yaw, Pitch	FVector right = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);	AddMovementInput(right, val);}// 左右转向void AMyPlayer::LookYaw(float val){	AddControllerYawInput(val);}// 上下转向void AMyPlayer::LookPitch(float val){	// 注意方向相反	AddControllerPitchInput(val);}// 按 E 键与激活对象进行交互void AMyPlayer::Use(){	AInteractableActor* Interactable = FindFocusedActor();	if (Interactable)	{		// OnInteract_Implementation		Interactable->OnInteract(this);	}}AInteractableActor* AMyPlayer::FindFocusedActor(){	if (!Controller)	{		return nullptr;	}	FVector Location;	FRotator Rotation;	FHitResult Hit(ForceInit);	Controller->GetPlayerViewPoint(Location, Rotation);	FVector Start = Location;	FVector End = Start + (Rotation.Vector() * InteractionDistance);	// 通过 “射线拾取” 选定对象	GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Camera, TraceParams);	if (Hit.bBlockingHit)	// 击中	{		// 获取当前被击中的对象的引用		AInteractableActor* MyCastActor = Cast
(Hit.GetActor()); if (MyCastActor) { return MyCastActor; } } return nullptr;}void AMyPlayer::HandleHighlight(){ AInteractableActor* NewHighlight = FindFocusedActor(); if (NewHighlight) { // 如果当前描边和新激活的对象不是同一个 if (FocusedActor != NewHighlight) { if (FocusedActor) { // 当前描边对象取消描边 FocusedActor->OnEndFocus(); } // 描边新激活对象 NewHighlight->OnBeginFocus(); FocusedActor = NewHighlight; } } else { if (FocusedActor) { // 取消描边 FocusedActor->OnEndFocus(); FocusedActor = nullptr; } }}

 

 

 

InteractableActor.h

 

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "GameFramework/Actor.h"#include "OutlineCPlusPlus.h"#include "InteractableActor.generated.h"UCLASS()class OUTLINECPLUSPLUS_API AInteractableActor : public AActor{	GENERATED_BODY()	public:		// Sets default values for this actor's properties	AInteractableActor();	// Called when the game starts or when spawned	virtual void BeginPlay() override;		// Called every frame	virtual void Tick( float DeltaSeconds ) override;	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Interaction)	void OnInteract(AActor* Caller) ;	virtual void OnInteract_Implementation(AActor* Caller);	void OnBeginFocus();	void OnEndFocus();private:	UPROPERTY(EditDefaultsOnly)	uint32 bCanInteract : 1;	TArray
Meshes; UPROPERTY(EditDefaultsOnly) EStencilColor Color = EStencilColor::SC_Green;};

 

InteractableActor.cpp

 

 

 

// Fill out your copyright notice in the Description page of Project Settings.#include "MyPlayer.h"#include "InteractableActor.h"// Sets default valuesAInteractableActor::AInteractableActor(){ 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.	PrimaryActorTick.bCanEverTick = true;}// Called when the game starts or when spawnedvoid AInteractableActor::BeginPlay(){	Super::BeginPlay();		for (UActorComponent* Mesh : GetComponentsByClass(UMeshComponent::StaticClass()))	{		UMeshComponent* thisMesh = Cast
(Mesh); if (thisMesh) { Meshes.Push(thisMesh); } }}// Called every framevoid AInteractableActor::Tick( float DeltaTime ){ Super::Tick( DeltaTime );}void AInteractableActor::OnInteract_Implementation(AActor* Caller){ AMyPlayer* Player = Cast
(Caller); if (Player) { GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Now deleting the interactable actor! ")) ); // 销毁自己 Destroy(); }}void AInteractableActor::OnBeginFocus(){ if (bCanInteract) { for (UMeshComponent* Mesh : Meshes) { Mesh->SetRenderCustomDepth(true); Mesh->SetCustomDepthStencilValue((uint8)Color); } }}void AInteractableActor::OnEndFocus(){ if (bCanInteract) { for (UMeshComponent* Mesh : Meshes) { Mesh->SetRenderCustomDepth(false); } }}

 

 

 

颜色 的 Enum 

 

UENUM(BlueprintType)enum class EStencilColor : uint8{	SC_Green = 250  UMETA(DisplayName = "Green"),	SC_Blue = 251  UMETA(DisplayName = "Blue"),	SC_Red = 252  UMETA(DisplayName = "Red"),	SC_White = 253  UMETA(DisplayName = "White")};

 

 

 

 

 

 

 

 

 

 

 

转载地址:https://panda1234lee.blog.csdn.net/article/details/62444059 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:后期处理材质(Post Process Material)【UE4】
下一篇:动态材质实例(Dynamic Material Instance)【UE4】

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月12日 04时37分53秒