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 Verts;
//};
//索引缓冲区
class FTestIndexBuffer : public FIndexBuffer
{
public:
    virtual void InitRHI() override
    {
        FRHIResourceCreateInfo CreateInfo;
        IndexBufferRHI = RHICreateIndexBuffer(sizeof(uint32), Indices.Num() * sizeof(uint32), BUF_Static, CreateInfo);

        void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, Indices.Num() * sizeof(uint32), RLM_WriteOnly);
        FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(uint32));
        RHIUnlockIndexBuffer(IndexBufferRHI);
    }
    
    TArray 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(&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 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);
    }

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

    virtual void GetDynamicMeshElements(const TArray& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
    {
        QUICK_SCOPE_CYCLE_COUNTER(STAT_MyTestPrimSceneProxy_DrawDynamicElements);

        //得到材质
        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();
                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;
};

原文链接

UE4绘制简单三角形

你可能感兴趣的:(UE4绘制简单三角形)