利用第三方后期处理材质(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; TArrayMeshes; 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月12日 04时37分53秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Memory & MyISAM 引擎小注意! | OurMySQL
2019-05-04
Aerospike | Aerospike Chinese
2019-05-04
Database Connection Pool Library | Libzdb
2019-05-04
mysql 主从同步出问题,重新修复从库 - web架构研究
2019-05-04
主从mysql 同步设置
2019-05-04
使MYSQL能被外部访问_xeyuu_新浪博客
2019-05-04
圣迭戈_百度百科
2019-05-04
Xtrabackup使用指南 | 简单.生活
2019-05-04
圣迭戈_百度百科
2019-05-04
姜的青春——【仔姜炒肉丝】_大菜博客_新浪博客
2019-05-04
鲜姜炒肉丝的做法,鲜姜炒肉丝怎么做好吃,鲜姜炒肉丝的家常做法_豆豆糖_好豆网...
2019-05-04
Processing.js
2019-05-04
Processing_百度百科
2019-05-04
Qt移动版优化后台云服务、支持跨平台开发
2019-05-04
陈年查尔斯们,请考虑下记者们的感受 by 李斌
2019-05-04
青菜粥的做法
2019-05-04