unity 日常学习整理----Graphics

本文详细介绍了Unity中Graphics渲染接口的使用,包括静态对象的设置、纹理绘制、Mesh处理、GPUinstancing的应用以及如何实现场景中的网格对齐效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础知识

Unity渲染绘制接口(三)Graphics - 知乎

1、静态对象

Graphics的静态对象提供了缓冲区数据与渲染Setting。

  • Graphics.activeColorBuffer:当前绘制区域颜色缓冲。
  • Graphics.activeColorGamut:当前绘制区域色域。
  • Graphics.activeDepthBuffer:当前绘制区域深度缓冲。
  • Graphics.minOpenGLESVersion:最低OpenGL ES版本,可在PlayerSettings中设置。
  • Graphics.preserveFramebufferAlpha:若勾选后可在Android平台中保留原生UI的缓冲alpha值,用以在原生UI上绘制对象。

2、纹理

  • Graphics.DrawTexture:在屏幕空间绘制纹理。
  • Graphics.Blit(source, dest,mat):使用着色器拷贝原纹理到RenderTexture
  • Graphics.CopyTexture(sre, dst):复制纹理(可对区域拷贝,无法改变分辨率)

    在绘制屏幕纹理时,需要注意API导致的坐标系变化。在默认坐标系中,顶点坐标原点在屏幕左上角,uv坐标原点在绘制对象的左下角。Graphics.DrawTexture只能在OnGUI以及之后的生命周期方法中调用,否则无法显示。
    Graphics.Blit通常用于后处理,需要注意的是使用后会修改RenderTexture.active,在此接口后直接使用Graphics绘制接口,不会生效。
    Graphics.Blit(texture, rt, mats[0]);
    RenderTexture.active = null;
    Graphics.DrawTexture(screenRects[0], rt, uiRects[0], 0, 0, 0, 0, null);
    Graphics.CopyTexture可以从一个纹理的像素数据拷贝到另一个纹理,也可以从mip或子区域中拷贝。拷贝对象时,不会进行放缩操作。因此原纹理与目标纹理的大小与格式必须匹配。当目标纹理与原纹理大小不一致时,只会读取目标纹理大小区域。若希望改变读取的纹理分辨率,只能手动创建与目标相同尺寸的RT,拷贝后再读取。

    QualitySettings.masterTextureLimit会影响Graphics.CopyTexture获取纹理的质量,具体见API说明

3、mesh

  • Graphics.DrawMesh:绘制Mesh
  • Graphics.DrawMeshInstanced:使用GPU instancing多次绘制相同的Mesh
  • Graphics.DrawMeshNow:立即绘制Mesh(对象无法逐像素光照着色,也无法接收与投射实时阴影)

    一般的,Graphics下的绘制命令不会立即绘制,更多的是“提交”渲染命令,后续在渲染阶段进行统一绘制。

    所以,一般的使用,在Update()方法中即可。

Graphics.DrawMesh在一帧中绘制网格,而无需创建GameObject。此接口不会立即绘制Mesh,只是将数据提交到正常的渲染流程中,如果希望立即绘制对象,使用Graphics.DrawMeshNow。

Graphics.DrawMeshInstanced使用GPU instancing特性绘制大量相同Mesh,同样为一帧渲染一次。需要注意的是,此接口将所有需要实例化的网格作为一组进行culling与sorting。在Mesh合并完成后,不会对其进行额外的视锥体剔除与遮挡剔除,也不会为透明度或深度对实例进行排序。单次调用实例数量上限为1023。

虽然看似Graphics.DrawMeshInstanced性能更高,但其没有Unity自带的视锥体剔除、LOD以及遮挡剔除等优化流程,因此要达到效率最优还需要额外的处理。

4、其他

  • Graphics.SetRenderTarget(rt/rb):设置渲染对象
  • Graphics.SetRandomWriteTarget(index, cb/rt):为Shader Model 4.5以上的PS设置随机渲染目标(UAV)
  • Graphics.ConvertTexture(sre, dst):转换纹理格式(RenderTextureFormat)
  • Graphics.CreateGraphicsFence(GraphicsFenceType,SynchronisationStage):创建一个GraphicsFence,在最后Blit、Clear、Draw、Dispatch或Texture Copy命令之后传递到GPU。通常用于GPU计算同步。
  • Graphics.WaitOnAsyncGraphicsFence:GPU等待GraphicsFence同步。

实际应用-实现Scence场景中的Grid 网格对齐效果

public class DrawGroundGrid : MonoBehaviour
{
    private Transform _cameraTR;
    public Material[] _lineMaterial;
    private Mesh lineMeshX;
    private Mesh lineMeshY;
    private bool _enabled_1 = false;
    private bool _enabled_10 = false;

    // Start is called before the first frame update
    void Start()
    {
        lineMeshX = new Mesh();
        lineMeshX.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(1000, 0, 0) };
        lineMeshX.SetIndices(new int[] { 0, 1 }, MeshTopology.Lines, 0);
        lineMeshX.UploadMeshData(true);

        lineMeshY = new Mesh();
        lineMeshY.vertices = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 0, 1000) };
        lineMeshY.SetIndices(new int[] { 0, 1 }, MeshTopology.Lines, 0);
        lineMeshY.UploadMeshData(true);
        _cameraTR = GetComponent<Transform>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Mathf.Abs(_cameraTR.position.y) < 10)
        {
            if (_enabled_1) _enabled_1 = false;
            Color linshi1 = _lineMaterial[0].color;
            linshi1.a = (float)(1 - Mathf.Abs(_cameraTR.position.y) / 10);//这个值随着相机Y轴的距离而变化 
            _lineMaterial[0].color=linshi1;
        }
        else
        {
            _enabled_1 = true;
            if (Mathf.Abs(_cameraTR.position.y) < 100)
            {
                if (_enabled_1) _enabled_10 = false;
                Color linshi2 = _lineMaterial[1].color;
                linshi2.a = (float)(1 - Mathf.Abs(_cameraTR.position.y) / 100);
                _lineMaterial[1].color=linshi2;
            }
            else
            {
                _enabled_10 = true;
            }
        }

        for (int i = -500; i < 501; i++)
        {
            if (i % 10 != 0)
            {
                if (!_enabled_1)
                {
                    Graphics.DrawMesh(lineMeshX, new Vector3(-500, 0, i), Quaternion.identity, _lineMaterial[0], 0);
                    Graphics.DrawMesh(lineMeshY, new Vector3(i, 0, -500), Quaternion.identity, _lineMaterial[0], 0);
                }
            }
            else if (i % 100 != 0)
            {
                if (!_enabled_10)
                {
                    Graphics.DrawMesh(lineMeshX, new Vector3(-500, 0, i), Quaternion.identity, _lineMaterial[1], 0);
                    Graphics.DrawMesh(lineMeshY, new Vector3(i, 0, -500), Quaternion.identity, _lineMaterial[1], 0);
                }
            }
            else
            {
                Graphics.DrawMesh(lineMeshX, new Vector3(-500, 0, i), Quaternion.identity, _lineMaterial[2], 0);
                Graphics.DrawMesh(lineMeshY, new Vector3(i, 0, -500), Quaternion.identity, _lineMaterial[2], 0);
            }
        }

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屋檐上的大修勾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值