UE4绘制简单三角形(一)

UE4绘制简单三角形

自定义PrimitiveComponents组件,使用PrimitiveSceneProxy渲染一个简单的三角形。
效果图

创建PrimitiveComponents子类

//h
#pragma once

#include "CoreMinimal.h"
#include "Components/PrimitiveComponent.h"
#include "MyTestPrimitiveComponent.generated.h"

/**
 * 
 */
UCLASS(meta = (BlueprintSpawnableComponent))
class HELLOSLATE_API UMyTestPrimitiveComponent : public UPrimitiveComponent
{
	GENERATED_BODY()

	virtual class FPrimitiveSceneProxy* CreateSceneProxy() override;
};

//cpp
//override
FPrimitiveSceneProxy* UMyTestPrimitiveComponent::CreateSceneProxy()
{
	return new FMyTestPrimSceneProxy(this);
}

创建PrimitiveSceneProxy子类

#include "EngineGlobals.h"
#include "RHI.h"
#include "RenderingThread.h"
#include "RenderResource.h"
#include "VertexFactory.h"
#include "LocalVertexFactory.h"
#include "PrimitiveViewRelevance.h"
#include "PrimitiveSceneProxy.h"
#include "Engine/Engine.h"
#include "MaterialShared.h"
#include "Materials/Material.h"
#include "Engine/CollisionProfile.h"
#include "SceneManagement.h"
#include "DynamicMeshBuilder.h"
#include "UObject/UObjectHash.h"
#include "UObject/UObjectIterator.h"
#include "StaticMeshResources.h"
//顶点缓冲区
//class FTestVertexBuffer :public FVertexBuffer{
//public:
//	virtual void InitRHI() override
//	{
//		FRHIResourceCreateInfo CreateInfo;
//		VertexBufferRHI = RHICreateIndexBuffer(sizeof(FDynamicMeshVertex), Verts.Num() * sizeof(FDynamicMeshVertex), BUF_Static, CreateInfo);
//
//		void* Buffer = RHILockVertexBuffer(VertexBufferRHI, 0, Verts.Num() * sizeof(FDynamicMeshVertex), RLM_WriteOnly);
//		FMemory::Memcpy(Buffer, Verts.GetData(), Verts.Num() * sizeof(FDynamicMeshVertex));
//		RHIUnlockVertexBuffer(VertexBufferRHI);
//	}
//
//	TArray<FDynamicMeshVertex> Verts;
//};
//索引缓冲区
class FTestIndexBuffer : public FIndexBuffer
{
public:
	virtual void InitRHI() override
	{
		FRHIResourceCreateInfo CreateInfo;
		IndexBufferRHI = RHICreateIndexBuffer(sizeof(uint32), Indices.Num() * sizeof(uint32), BUF_Static, CreateInfo);
//静态绘制,BeginInitResource(&IndexBuffer)初始化时直接写入缓冲区
		void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, Indices.Num() * sizeof(uint32), RLM_WriteOnly);
		FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(uint32));
		RHIUnlockIndexBuffer(IndexBufferRHI);
	}
	
	TArray<uint32> Indices;
};

//class FTestLocalVertexFactory :FLocalVertexFactory {
//
//};
/** Represents a UMyTestPrimComponent to the scene manager. */
class FMyTestPrimSceneProxy final : public FPrimitiveSceneProxy
{
public:
	//Get-Type-Hash
	SIZE_T GetTypeHash() const override
	{
		static size_t UniquePointer;
		return reinterpret_cast<size_t>(&UniquePointer);
	}
	//PrimitivePoxy
	FMyTestPrimSceneProxy(UMyTestPrimitiveComponent* Component)
		: FPrimitiveSceneProxy(Component)
		, VertexFactory(GetScene().GetFeatureLevel(), "FMyTestPrimSceneProxy")
	{
		/** Can be set to false to skip some work only needed on lit primitives. */
		//设定为false则会跳过一些只被光照图元所需的工作
		bWillEverBeLit = false;
		//设置顶点信息:(只是一个简单的三角形)
		TArray<FDynamicMeshVertex> OutVerts;

		FDynamicMeshVertex V0, V1, V2;
		V0.Position = FVector(0, 0, 0);
		V0.Color = FColor(255, 0, 0);
		int32 I0 = OutVerts.Add(V0);
		V1.Position = FVector(100, 0, 0);
		V1.Color = FColor(0, 255, 0);
		int32 I1 = OutVerts.Add(V1);
		V2.Position = FVector(0, 100, 0);
		V2.Color = FColor(0, 0, 255);
		int32 I2 = OutVerts.Add(V2);


		IndexBuffer.Indices.Add(I0);
		IndexBuffer.Indices.Add(I1);
		IndexBuffer.Indices.Add(I2);

		//初始化顶点缓冲区属性
		VertexBuffers.InitFromDynamicVertex(&VertexFactory, OutVerts);
		//初始化索引
		// Enqueue initialization of render resource
		BeginInitResource(&IndexBuffer);
		/*void* Buffer = RHILockIndexBuffer(IndexBuffer.IndexBufferRHI, 0, IndexBuffer.Indices.Num() * sizeof(uint32), RLM_WriteOnly);
		FMemory::Memcpy(Buffer, IndexBuffer.Indices.GetData(), IndexBuffer.Indices.Num() * sizeof(uint32));
		RHIUnlockIndexBuffer(IndexBuffer.IndexBufferRHI);*/
	}

	virtual ~FMyTestPrimSceneProxy()
	{
		VertexBuffers.PositionVertexBuffer.ReleaseResource();
		VertexBuffers.StaticMeshVertexBuffer.ReleaseResource();
		VertexBuffers.ColorVertexBuffer.ReleaseResource();
		IndexBuffer.ReleaseResource();
		VertexFactory.ReleaseResource();
	}

	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_MyTestPrimSceneProxy_DrawDynamicElements);
/*void* Buffer = RHILockIndexBuffer(IndexBuffer.IndexBufferRHI, 0, IndexBuffer.Indices.Num() * sizeof(uint32), RLM_WriteOnly);
		FMemory::Memcpy(Buffer, IndexBuffer.Indices.GetData(), IndexBuffer.Indices.Num() * sizeof(uint32));
		RHIUnlockIndexBuffer(IndexBuffer.IndexBufferRHI);*/
		//得到材质
		auto MaterialRenderProxy = new FColoredMaterialRenderProxy(
			GEngine->ArrowMaterial->GetRenderProxy(),
			FLinearColor(0.0f, 1.0f, 1.0f, 1.0f),
			"GizmoColor"
		);
		//设定材质
		Collector.RegisterOneFrameMaterialProxy(MaterialRenderProxy);


		//针对于每一个View设定mesh顶点
		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
		{
			if (VisibilityMap & (1 << ViewIndex))
			{
				//申请一块新的内存来存放FMeshBatch
				FMeshBatch& Mesh = Collector.AllocateMesh();
				//获得第一个元素(也只有一个元素)
				FMeshBatchElement& BatchElement = Mesh.Elements[0];
				//设定索引缓冲与顶点缓冲
				BatchElement.IndexBuffer = &IndexBuffer;
				Mesh.VertexFactory = &VertexFactory;
				//设定材质
				Mesh.MaterialRenderProxy = MaterialRenderProxy;
				//设定UniformBuffer
				FDynamicPrimitiveUniformBuffer& DynamicPrimitiveUniformBuffer = Collector.AllocateOneFrameResource<FDynamicPrimitiveUniformBuffer>();
				DynamicPrimitiveUniformBuffer.Set(GetLocalToWorld(), GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, false, DrawsVelocity(), false);
				BatchElement.PrimitiveUniformBufferResource = &DynamicPrimitiveUniformBuffer.UniformBuffer;
				//设定索引的范围:
				BatchElement.FirstIndex = 0;
				BatchElement.NumPrimitives = IndexBuffer.Indices.Num() / 3;
				//设定顶点的范围:
				BatchElement.MinVertexIndex = 0;
				BatchElement.MaxVertexIndex = VertexBuffers.PositionVertexBuffer.GetNumVertices() - 1;
				//不使用线框
				Mesh.bWireframe = false;
				//是否反向剔除
				Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
				//设定图元类型
				Mesh.Type = PT_TriangleList;
				//设定深度优先级组?
				Mesh.DepthPriorityGroup = SDPG_World;
				//** Whether view mode overrides can be applied to this mesh eg unlit, wireframe. */
				Mesh.bCanApplyViewModeOverrides = false;
				//调用FMeshElementCollector的接口AddMesh
				Collector.AddMesh(ViewIndex, Mesh);
			}
		}
	}

	virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
	{
		FPrimitiveViewRelevance Result;

		//图元需要被画
		Result.bDrawRelevance = IsShown(View) && (View->Family->EngineShowFlags.BillboardSprites);

		//有动态的元素(true时GetDynamicMeshElements才会起效)
		Result.bDynamicRelevance = true;

		return Result;
	}

	/**
	 * Called to notify the proxy when its transform has been updated.
	 * Called in the thread that owns the proxy; game or rendering.
	 */
	virtual void OnTransformChanged() override
	{
		Origin = GetLocalToWorld().GetOrigin();
	}

	virtual uint32 GetMemoryFootprint(void) const override { return(sizeof(*this) + GetAllocatedSize()); }
	uint32 GetAllocatedSize(void) const { return(FPrimitiveSceneProxy::GetAllocatedSize()); }

private:
	//顶点数据:position,color,texture,tangents
	FStaticMeshVertexBuffers VertexBuffers;
	//索引数据
	FTestIndexBuffer IndexBuffer;
	//顶点属性
	FLocalVertexFactory VertexFactory;
	FVector Origin;
};

将内存数据拷贝到显存当中,可以在初始化之后的某个阶段写入。

		void* Buffer = RHILockIndexBuffer(IndexBuffer.IndexBufferRHI, 0, IndexBuffer.Indices.Num() * sizeof(uint32), RLM_WriteOnly);
		FMemory::Memcpy(Buffer, IndexBuffer.Indices.GetData(), IndexBuffer.Indices.Num() * sizeof(uint32));
		RHIUnlockIndexBuffer(IndexBuffer.IndexBufferRHI);

原文链接

UE4绘制简单三角形

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值