IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> (UE4 4.27)插件添加GlobalShder -> 正文阅读

[游戏开发](UE4 4.27)插件添加GlobalShder

前言

在上一节我们大致介绍了UE4 GlobalShader的情况, 并且在引擎代码做了一些修改来阐述GlobalShader的声明-定义-使用。实际上在UE4开发中, GlobalShader不一定使用在修改引擎代码,也可能是用在插件, 比如LensDistortion插件就是使用GlobalShader定制一个RenderToTexture的功能。当然在插件中,GlobalShader的使用场景不仅仅局限于RenderToTexture, 可以ComputeShader等等来加速某些并行计算(如基于GPU的植被插件等)。(UE4 4.27)自定义GlobalShadericon-default.png?t=L9C2https://blog.csdn.net/qq_29523119/article/details/120573174?spm=1001.2014.3001.5501

GlobalShader插件声明步骤

功能

下面做一个对图片进行调色并渲染到RenderTexture的功能

声明定义GlobalShader

#pragma once
#include "CoreMinimal.h"
#include "GlobalShader.h"
#include "ShaderParameters.h"
#include "Shader.h"

/**
 * 
 */
class FDrawVS : public FGlobalShader
{
	DECLARE_SHADER_TYPE(FDrawVS, Global);

public:
	FDrawVS() {};
	FDrawVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
		:FGlobalShader(Initializer)
	{

	}

	static bool ShouldCompilePermutation(const FShaderPermutationParameters& Parameters)
	{
		return true;
	}
};

class FDrawPS : public FGlobalShader
{
	DECLARE_SHADER_TYPE(FDrawPS, Global);

public:
	FDrawPS() {};
	FDrawPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
		:FGlobalShader(Initializer)
	{
		Color.Bind(Initializer.ParameterMap, TEXT("MyColor"));
		ColorScale.Bind(Initializer.ParameterMap, TEXT("MyColorScale"));
		Texture.Bind(Initializer.ParameterMap, TEXT("InTexture"));
		TextureSampler.Bind(Initializer.ParameterMap, TEXT("InTextureSampler"));
	}

	/** Should the shader be cached? Always. */
	static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
	{
		return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5);
	}

	void SetParam(FRHICommandList& RHICmdList, const FTexture* TextureValue, const FLinearColor& InColor, float InColorScale)
	{
		FRHIPixelShader* PS = RHICmdList.GetBoundPixelShader();
		SetTextureParameter(RHICmdList, PS, Texture, TextureSampler, TextureValue);
		SetShaderValue(RHICmdList, PS, Color, InColor);
		SetShaderValue(RHICmdList, PS, ColorScale, InColorScale);
	}

private:
	LAYOUT_FIELD(FShaderParameter, Color);
	LAYOUT_FIELD(FShaderParameter, ColorScale);
	LAYOUT_FIELD(FShaderResourceParameter, Texture);
	LAYOUT_FIELD(FShaderResourceParameter, TextureSampler);
};

重定向Shader路径和Shader代码

void FTestShader::StartupModule()
{
	FString PluginShaderDir = FPaths::Combine(IPluginManager::Get().FindPlugin(TEXT("TestShader"))->GetBaseDir(), TEXT("Shaders"));
	AddShaderSourceDirectoryMapping(TEXT("/Plugin/TestShader"), PluginShaderDir);
}
IMPLEMENT_SHADER_TYPE(, FDrawVS, TEXT("/Plugin/TestShader/DrawShader.usf"), TEXT("MainVS"), SF_Vertex);
IMPLEMENT_SHADER_TYPE(, FDrawPS, TEXT("/Plugin/TestShader/DrawShader.usf"), TEXT("MainPS"), SF_Pixel);

DrawShader.usf


#include "/Engine/Public/Platform.ush"

void MainVS(
	in float3 InPostion : ATTRIBUTE0, 
	in float2 UV : ATTRIBUTE1,
	out float2 OutUV : TEXCOORD0,
	out float4 Output : SV_POSITION)
{
	OutUV = UV;
    Output = float4(InPostion, 1.0f);
}

Texture2D InTexture;
SamplerState InTextureSampler;

float4 MyColor;
float MyColorScale;
void MainPS(
	in float2 UV : TEXCOORD0,
	out float4 OutColor : SV_Target0)
{
	float4 TextureColor = InTexture.Sample(InTextureSampler, UV);
    OutColor = MyColor * TextureColor * MyColorScale;
	//return float4(1.0f, 1.0f, 1.0f, 1.0f);
}

蓝图库静态RT函数

void UMyShaderBPFunctionLibrary::DrawTestShaderToRenderTexture(
	const UObject* WorldContextObject,
	const UTexture2D* InTexture,
	class UTextureRenderTarget2D* OutputRenderTarget,
	const FLinearColor& Color,
	float ColorScale)
{
	UWorld* World = WorldContextObject->GetWorld();
	ERHIFeatureLevel::Type FeatureLevel = World->Scene->GetFeatureLevel();

	if (FeatureLevel < ERHIFeatureLevel::SM5)
	{
		UE_LOG(LogTemp, Warning, TEXT("FeatureLevel < ERHIFeatureLevel::SM5"));
		return;
	}

	if (nullptr == InTexture)
	{
		UE_LOG(LogTemp, Warning, TEXT("InTexture Is NULL"));
		return;
	}

	FTextureRenderTargetResource* TextureRenderTargetSource = OutputRenderTarget->GameThread_GetRenderTargetResource();
	FTexture* TextureSource = InTexture->Resource;

	ENQUEUE_RENDER_COMMAND(TestShaderCommand)(
		[TextureSource, TextureRenderTargetSource, FeatureLevel, Color, ColorScale](FRHICommandListImmediate& RHICmdList)
		{
			DrawTestShaderToRenderTexture_RenderThread(RHICmdList, TextureSource, TextureRenderTargetSource, FeatureLevel, Color, ColorScale);
		}
	);
}

这里?ENQUEUE_RENDER_COMMAND 表示从游戏线程向渲染线程发送渲染指令, 而FRHICommandListImmediate和上一节的FRHICommandList也有所不同,FRHICommandListImmediate代表的立即模式,代表发送到渲染线程后马上进行渲染,就能得到渲染结果。而FRHICommandList存在渲染指令的队列,会进行指令收集在进行延后的渲染有所不同。

顶点数据结构和VertexFormat声明

struct FCustomVertex
{
	FVector Pos;
	FVector2D UV;

	FCustomVertex()
	{
	}

	FCustomVertex(const FVector& VertexPos, const FVector2D& VertexUV)
		:Pos(VertexPos), UV(VertexUV)
	{
	}
};

//declare custom vertex format
class FMyTestVertexDeclaration : public FRenderResource
{
public:
	FVertexDeclarationRHIRef VertexDeclarationRHI;

	virtual void InitRHI() override
	{
		FVertexDeclarationElementList Elements;
		uint16 Stride = sizeof(FCustomVertex);

		//Pos-float3
		Elements.Add(FVertexElement(0, STRUCT_OFFSET(FCustomVertex, Pos), VET_Float3, 0, Stride));

		//UV-float2
		Elements.Add(FVertexElement(0, STRUCT_OFFSET(FCustomVertex, UV), VET_Float2, 1, Stride));
		VertexDeclarationRHI = PipelineStateCache::GetOrCreateVertexDeclaration(Elements);
	}

	virtual void ReleaseRHI() override
	{
		VertexDeclarationRHI.SafeRelease();
	}
};

TGlobalResource<FMyTestVertexDeclaration> GCustomVertexDeclaration;

渲染数据准备, Draw

static void DrawTestShaderToRenderTexture_RenderThread(
	FRHICommandListImmediate& RHICmdList,
	FTexture* InTextureResource,
	FTextureRenderTargetResource* OutTextureRenderTargetResource,
	ERHIFeatureLevel::Type FeatureLevel,
	const FLinearColor& Color,
	float ColorScale)
{
	check(IsInRenderingThread());

	FRHITexture2D* RenderTargetTexture = OutTextureRenderTargetResource->GetRenderTargetTexture();
	RHICmdList.Transition(FRHITransitionInfo(RenderTargetTexture, ERHIAccess::SRVMask, ERHIAccess::RTV));

	FRHIRenderPassInfo RPInfo(RenderTargetTexture, ERenderTargetActions::DontLoad_Store);
	RHICmdList.BeginRenderPass(RPInfo, TEXT("Render Test Shader To Texture"));
	{
		FIntPoint ViewportSize(OutTextureRenderTargetResource->GetSizeX(), OutTextureRenderTargetResource->GetSizeY());
	
		// Upate viewport
		RHICmdList.SetViewport(0, 0, 0.0f, ViewportSize.X, ViewportSize.Y, 1.0f);

		// Get Shaders
		FGlobalShaderMap* GlobalShaderMap = GetGlobalShaderMap(FeatureLevel);
		TShaderMapRef<FDrawVS> VertexShader(GlobalShaderMap);
		TShaderMapRef<FDrawPS> PixelShader(GlobalShaderMap);

		// Setup Pipeline state
		FGraphicsPipelineStateInitializer GraphicsPSOInit;
		RHICmdList.ApplyCachedRenderTargets(GraphicsPSOInit);
		GraphicsPSOInit.DepthStencilState = TStaticDepthStencilState<false, CF_Always>::GetRHI();
		GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
		GraphicsPSOInit.RasterizerState = TStaticRasterizerState<>::GetRHI();
		GraphicsPSOInit.PrimitiveType = PT_TriangleStrip;
		GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GCustomVertexDeclaration.VertexDeclarationRHI;
		GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
		GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
		SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit);

		// update shader uniform parameters
		PixelShader->SetParam(RHICmdList, InTextureResource, Color, ColorScale);

		// Create VertexBuffer and setup
		static const uint32 VERTEX_SIZE = sizeof(FCustomVertex) * 4;
		FRHIResourceCreateInfo CreateInfo;
		FVertexBufferRHIRef VertexBufferRHI = RHICreateVertexBuffer(VERTEX_SIZE, BUF_Static, CreateInfo);
		void* VoidPtr = RHILockVertexBuffer(VertexBufferRHI, 0, VERTEX_SIZE, RLM_WriteOnly);

		FCustomVertex Vertices[4];
		Vertices[0] = FCustomVertex(FVector(-1.0f, 1.0f, 0.0f), FVector2D(0.0f, 0.0f));
		Vertices[1] = FCustomVertex(FVector(1.0f, 1.0f, 0), FVector2D(1.0f, 0.0f));
		Vertices[2] = FCustomVertex(FVector(-1.0f, -1.0f, 0), FVector2D(0.0f, 1.0f));
		Vertices[3] = FCustomVertex(FVector(1.0f, -1.0f, 0), FVector2D(1.0f, 1.0f));
		FMemory::Memcpy(VoidPtr, (void*)Vertices, VERTEX_SIZE);
		RHIUnlockVertexBuffer(VertexBufferRHI);

		RHICmdList.SetStreamSource(0, VertexBufferRHI, 0);
		RHICmdList.DrawPrimitive(0, 2, 1);
	}
	RHICmdList.EndRenderPass();

	RHICmdList.Transition(FRHITransitionInfo(RenderTargetTexture, ERHIAccess::RTV, ERHIAccess::SRVMask));
}

?结果显示

总结?

总体而言各种渲染数据的声明定义和Directx11非常类似.

插件代码链接

https://download.csdn.net/download/qq_29523119/33147630

资料参考

【1】https://docs.unrealengine.com/4.27/en-US/ProgrammingAndScripting/Rendering/ShaderInPlugin/Overview/

【2】UE4的LensDistortion插件和Texture2DPreview.cpp

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:56:59  更:2021-10-16 19:59:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/28 0:55:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码