(五)CommandBuffer基本应用

1.前言

CommandBuffer为渲染命令缓冲区,我们将一些列渲染指令添加到CommandBuffer中,在需要执行时通过Camera或者Graphics类进行执行,进而实现对渲染流程的控制。同时可以实时生成我们需要的临时效果。本文完整代码在最后。

2.基本方法

目前只介绍CommandBuffer最基本的几个方法。首先定义一个CommandBuffer的实例:

cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };

2.1 DrawRenderer

2.1.1 ToScreen

示例代码如下:

    public void DrawRenderer()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }

入口参数cubeRenderer为一个立方体网格,cmdMat为一个unlit/texture的材质,相当于用cmdMat材质,对cubeRenderer的显示效果进行了重新生成。并将结果直接显示在屏幕上,位置为原cubeRenderer位置。

2.1.2 ToTarget

示例代码如下:

    public void DrawRendererToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }

此方法相当于在将2.1.1的计算结果绘制到一个RenderTexture类型的target上,将此Target可以赋值给其他对象上,如RawImage等。

2.2 DrawMesh

此方法表示绘制一个Mesh

2.2.1 ToScreen

示例代码如下:

    public void DrawMesh()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }

表示将mesh根据cmdMat材质定义的效果绘制到屏幕上,如果不需要坐标变换则采用 Matrix4x4.identity矩阵。

2.2.2 ToTarget

示例代码:

    public void DrawMeshToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);

        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }

此方法相当于在将2.2.1的计算结果绘制到一个RenderTexture类型的target上,将此Target可以赋值给其他对象上,如RawImage等。

3.使用方法

根据2.定义CommandBuffer指令,然后就可以进行调用了。调用时可以使用Camera也可以使用Graphics类,此文采用Camera来调用,Graphics类的调用后续会讲,稍微复杂一点。

        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };

        mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);

上述代码表示将此指令添加到Camera的执行序列中,即当渲染完不透明物体时执行此指令。此指令渲染的结果可能绘制到屏幕上,也可能绘制到一个RenderTexture上。

4.完整代码

4.1 使用代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public enum CameraCmdBuffer
{
        DRAW_RENDERER,
        DRAW_RENDERER_TARGET,
        DRAW_MESH,
        DRAW_MESH_TARGET
}

public class Graphics05CmdBufferCamera : MonoBehaviour
{
    public Camera mainCamera;
    public Material cmdMat;
    public Renderer cubeRenderer;
    public RenderTexture target;
    public Color clearColor = Color.red;
    public int triCount = 6;
    public float radius = 5;

    private CommandBuffer cmdBuffer;
    private Mesh mesh;

    public void DrawRenderer()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }

    public void DrawRendererToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);
        cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
    }

    public void DrawMesh()
    {
        cmdBuffer.Clear();
        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }

    public void DrawMeshToTarget()
    {
        cmdBuffer.Clear();
        cmdBuffer.SetRenderTarget(target);
        cmdBuffer.ClearRenderTarget(true, true, clearColor);

        cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
    }

    private void Start()
    {
        cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };

        mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);

        if (mesh==null)
        {
            mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
        }
    }

    private void OnValidate()
    {
        mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
    }

    private void OnDisable()
    {
        mainCamera.RemoveAllCommandBuffers();
    }
}

4.2 Mesh代码


```go
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Graphics00Mesh
{
    [Range(3, 100)]
    public int triCount = 6;
    public float radius = 5;
    public bool showHalf = false;

    private static Graphics00Mesh instance;

    public static Graphics00Mesh Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Graphics00Mesh();
            }

            return instance;
        }
    }

    public Mesh GetMesh(int triCount,float radius)
    {
        this.triCount = triCount;
        this.radius = radius;

        Mesh mesh = new Mesh();
        mesh.name = MeshName;
        mesh.vertices = Vertices;
        mesh.triangles = Triangles;
        mesh.uv = Uvs;

        return mesh;
    }

    protected string MeshName
    {
        get
        {
            return "Circle Mesh";
        }
    }

    protected Vector3[] Vertices
    {
        get
        {
            Vector3[] vertices = new Vector3[triCount + 1];
            vertices[0] = Vector3.zero;
            float angleDelta = 2 * Mathf.PI / triCount;

            for (int i = 0; i < triCount; i++)
            {
                float angle = angleDelta * i;
                float x = radius * Mathf.Cos(angle);
                float y = radius * Mathf.Sin(angle);

                vertices[i + 1] = new Vector3(x, y, 0);
            }

            return vertices;
        }
    }

    protected int[] Triangles
    {
        get
        {
            int[] triangles = new int[triCount * 3];

            for (int i = 0; i < triCount; i++)
            {
                if (showHalf)
                {
                    if (i % 2 == 0) continue;
                }

                triangles[i * 3] = 0;
                triangles[i * 3 + 2] = i + 1;

                if (i + 2 > triCount)
                {
                    triangles[i * 3 + 1] = 1;
                }
                else
                {
                    triangles[i * 3 + 1] = i + 2;
                }
            }
            return triangles;
        }
    }

    protected Vector2[] Uvs
    {
        get
        {
            Vector2[] uvs = new Vector2[triCount + 1];
            uvs[0] = new Vector2(0.5f, 0.5f);
            float angleDelta = 2 * Mathf.PI / triCount;

            for (int i = 0; i < triCount; i++)
            {
                float angle = angleDelta * i;
                float x = Mathf.Cos(angle) * 0.5f + 0.5f;
                float y = Mathf.Sin(angle) * 0.5f + 0.5f;

                uvs[i + 1] = new Vector2(x, y);
            }
            return uvs;
        }
    }
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些 C 语言代码,实现基本的文件管理功能。下面是示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_PATH 1024 void create_file(char *filename) { FILE *fp = fopen(filename, "w"); if (fp == NULL) { printf("Failed to create file: %s\n", filename); } else { printf("File created successfully: %s\n", filename); fclose(fp); } } void create_dir(char *dirname) { int res = mkdir(dirname, 0777); if (res == -1) { printf("Failed to create directory: %s\n", dirname); } else { printf("Directory created successfully: %s\n", dirname); } } void copy_file(char *src, char *dest) { FILE *fp1 = fopen(src, "r"); FILE *fp2 = fopen(dest, "w"); if (fp1 == NULL || fp2 == NULL) { printf("Failed to copy file: %s\n", src); } else { char buffer[1024]; size_t nread; while ((nread = fread(buffer, 1, sizeof(buffer), fp1)) > 0) { fwrite(buffer, 1, nread, fp2); } fclose(fp1); fclose(fp2); printf("File copied successfully: %s -> %s\n", src, dest); } } void copy_dir(char *src, char *dest) { char command[MAX_PATH]; sprintf(command, "cp -r %s %s", src, dest); int res = system(command); if (res == -1) { printf("Failed to copy directory: %s\n", src); } else { printf("Directory copied successfully: %s -> %s\n", src, dest); } } void move_file(char *src, char *dest) { int res = rename(src, dest); if (res == -1) { printf("Failed to move file: %s\n", src); } else { printf("File moved successfully: %s -> %s\n", src, dest); } } void move_dir(char *src, char *dest) { char command[MAX_PATH]; sprintf(command, "mv %s %s", src, dest); int res = system(command); if (res == -1) { printf("Failed to move directory: %s\n", src); } else { printf("Directory moved successfully: %s -> %s\n", src, dest); } } void delete_file(char *filename) { int res = remove(filename); if (res == -1) { printf("Failed to delete file: %s\n", filename); } else { printf("File deleted successfully: %s\n", filename); } } void delete_dir(char *dirname) { char command[MAX_PATH]; sprintf(command, "rm -r %s", dirname); int res = system(command); if (res == -1) { printf("Failed to delete directory: %s\n", dirname); } else { printf("Directory deleted successfully: %s\n", dirname); } } void list_dir(char *dirname) { char command[MAX_PATH]; sprintf(command, "ls -al %s", dirname); system(command); } void view_file(char *filename) { FILE *fp = fopen(filename, "r"); if (fp == NULL) { printf("Failed to open file: %s\n", filename); } else { char buffer[1024]; size_t nread; while ((nread = fread(buffer, 1, sizeof(buffer), fp)) > 0) { fwrite(buffer, 1, nread, stdout); } fclose(fp); } } void modify_permission(char *filename, int mode) { int res = chmod(filename, mode); if (res == -1) { printf("Failed to modify file permission: %s\n", filename); } else { printf("File permission modified successfully: %s\n", filename); } } void search_file(char *filename, char *dirname) { char command[MAX_PATH]; sprintf(command, "find %s -name %s", dirname, filename); system(command); } int main() { char command[1024]; char filename[MAX_PATH]; char dirname[MAX_PATH]; char dest[MAX_PATH]; int mode; while (1) { printf("> "); fgets(command, sizeof(command), stdin); command[strlen(command) - 1] = '\0'; if (strcmp(command, "exit") == 0) { break; } else if (sscanf(command, "create file %s", filename) == 1) { create_file(filename); } else if (sscanf(command, "create directory %s", dirname) == 1) { create_dir(dirname); } else if (sscanf(command, "copy file %s %s", filename, dest) == 2) { copy_file(filename, dest); } else if (sscanf(command, "copy directory %s %s", dirname, dest) == 2) { copy_dir(dirname, dest); } else if (sscanf(command, "move file %s %s", filename, dest) == 2) { move_file(filename, dest); } else if (sscanf(command, "move directory %s %s", dirname, dest) == 2) { move_dir(dirname, dest); } else if (sscanf(command, "delete file %s", filename) == 1) { delete_file(filename); } else if (sscanf(command, "delete directory %s", dirname) == 1) { delete_dir(dirname); } else if (sscanf(command, "list directory %s", dirname) == 1) { list_dir(dirname); } else if (sscanf(command, "view file %s", filename) == 1) { view_file(filename); } else if (sscanf(command, "modify permission %s %o", filename, &mode) == 2) { modify_permission(filename, mode); } else if (sscanf(command, "search file %s %s", filename, dirname) == 2) { search_file(filename, dirname); } else { printf("Invalid command: %s\n", command); } } return 0; } ``` 这段代码实现了基本的文件管理功能,包括创建文件、创建文件夹、复制文件及文件夹、移动文件及文件夹、删除文件及文件夹、显示文件夹中的内容、查看文件内容、修改文件权限、搜索文件等。您可以在终端中输入相应的命令,执行相应的操作。例如,输入 `create file test.txt` 可以创建一个名为 `test.txt` 的文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值