美文网首页
UE4绘制简单三角形

UE4绘制简单三角形

作者: wblong | 来源:发表于2021-04-03 14:56 被阅读0次

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

    原文链接

    UE4绘制简单三角形

    相关文章

      网友评论

          本文标题:UE4绘制简单三角形

          本文链接:https://www.haomeiwen.com/subject/dulhkltx.html