unity 日常学习整理——GL

Unity Graphics API 深入浅出-GL(1)

https://zhuanlan.zhihu.com/p/575638246

unity中的 GL:

低级别图形库。

GL 绘制指令是立即执行。意思是如果您在 Update() 中调用它们,它们将在摄像机渲染之前执行(但该摄像机很可能会进行清屏操作,使 GL 绘制不可见)。

调用 GL 绘制的位置在添加摄像机的脚本OnPostRender() 中从调用, 或者在图像效果函数 (OnRenderImage) 内调用。

URP中调用 OnPostRender() :

在相机完成场景渲染之后被调用。OnPostRender可以是一个协同程序,在函数中调用yield语句即。

   void OnEnable()
    {
        RenderPipelineManager.endCameraRendering +=RenderPipelineManager_endCameraRendering;
    }
    void OnDisable()
    {
        RenderPipelineManager.endCameraRendering -= RenderPipelineManager_endCameraRendering;
    }
    private void RenderPipelineManager_endCameraRendering(ScriptableRenderContext context, Camera camera)
    {
        OnPostRender();
    }
  private void OnPostRender()
    {
    
    }
GL的运行:
public void OnRenderObject()
    {
        CreateLineMaterial();
        // Apply the line material
        lineMaterial.SetPass(0);

        GL.PushMatrix();
        // Set transformation matrix for drawing to
        // match our transform
        GL.MultMatrix(transform.localToWorldMatrix);

        // Draw lines
        GL.Begin(GL.LINES);
        for (int i = 0; i < lineCount; ++i)
        {
            float a = i / (float)lineCount;
            float angle = a * Mathf.PI * 2;
            // Vertex colors change from red to green
            GL.Color(new Color(a, 1 - a, 0, 0.8F));
            // One vertex at transform position
            GL.Vertex3(0, 0, 0);
            // Another vertex at edge of circle
            GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0);
        }
        GL.End();
        GL.PopMatrix();
    }
函数说明
1渲染矩阵的保存与恢复(使用栈的进出实现)
GL.PushMatrix();
......
GL.PopMatrix();

这两个成对出现的矩阵操作原起OpenGL的glPushMatrix与glPopMatrix,主要是对更改模型、视图或投影的矩阵现场保护。 通过使用GL.PushMatrixGL.PopMatrix保存和恢复这些现场数据。

2、可在PushMatrix与PopMatrix中使用的函数
特殊:GL.MultMatrix
GL.MultMatrix(transform.localToWorldMatrix);

以上代码其实就是把模型空间变成了世界空间,换句简单的话来说原来挂接的GameObject移动时GL绘制的线条并不移动,而使用以上的代码后GameObject位置一但改变了,使用GL绘制的线条就可以跟随GameObject移动而移动,相当于当前GL绘制的线条成了GameObject的子对象了。

PS:与OpenGL有差别,这里是直接设置当前对象矩阵,而不能像OpenGL叠加使用,Unity3D的几个Matrix都是设置而不是叠加。

其他:
函数名说明
GL.LoadPixelMatrix交矩阵加载到一个用于像素渲染的矩阵。
GL.LoadProjectionMatrix将任意矩阵加载到当前投影矩阵。
GL.LoadIdentity将标识加载到当前的模型和视图矩阵中。
GL.modelview获取或设置 modelview 矩阵
3画线前的准备
GL.Begin(GL.LINES);//开始绘制一个3D图元
......
GL.End();

Unity的GL.Begin(model), GL.End()与OpenGL的glBegin(),glEnd()功能相同,都应用于绘制基本3D图元,二者应用于绘图的函数有很多,都是通过使用Begin()和End()函数之间调用基本图元函数完成点、线、和多边形的绘制。

Begin的OpenGL与UNITY3D的对比
OPENGLUNITY3D解释
GL_LINE_STRIPLINE_STRIP绘制线条带
GL_LINESLINES绘制线条,每两点构成一条线段
GL_QUADSQUADS绘制四边形
GL_TRIANGLES_STRIPTRIANGLE_STRIP绘制三角形带
GL_TRIANGLESTRIANGLES绘制三角形
GL_POINTS一系列独立的顶点
GL_POLYGON简单、凸多边形的边界
GL_LINE_LOOP顶点相连,连成一系列线段,头尾连
GL_TRINGLE_FAN相连的三角形扇形
GL_QUAD_STRIP相连的四边形

OpenGL与Unity在Begin与End间可调用的函数
glVertexVertex Vertex3定义顶点坐标
glColorColor设置当前颜色
glIndex设置当前颜色索引
glNormal定义法向向量
GlEvalCoord生成坐标
glCallList,glCallLists执行显示列表
glTexCoordTexCoord,TexCoord2,TexCoord3
MultiTexCoord,MultiTexCoord2,MultiTexCoord3
定义纹理wwsf
glEdgeFlag控制边缘的绘制
glMaterial设置材质属性
画线
GL.Color(newColor(a,1- a,0,0.8F));// One vertex at transform position             
GL.Vertex3(0,0,0);// Another vertex at edge of circle             
GL.Vertex3(Mathf.Cos(angle)* radius, Mathf.Sin(angle)* radius,0);

简单的三角函数

在GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius,0);创建一个终点,

终于点X=Cos(angle)*radius Y=Sin(angle)*radius

GL实际应用-模型描边 

顶点的连线以及消除斜线(不需要的线)

Unity 模型描边的几种方法. (Shader、GL、代码生成描绘边)_unity 编辑器的描边是什么弄的-CSDN博客

GL实际应用-使用GL实现Scence场景中的Grid Visual效果

public class GLhuizhi : MonoBehaviour
{
    private Transform _cameraTR;
    private Material _lineMaterial;
    private List<Vector3> _listNearPoints=new List<Vector3>();
    private float _nearAlpha = 1f;
    private List<Vector3> _listMiddlePoints=new List<Vector3>()  ;
    private float _middAlpha = 1f;
    private List<Vector3> _listFarPoints = new List<Vector3>();
    private bool _enabled_1 = false;
    private bool _enabled_10 = false;
    void Start()
    {
        _cameraTR = GetComponent<Transform>();
        _lineMaterial = new Material(Shader.Find("Hidden/Internal-Colored"));
        //GroundGrid长宽为1000*1000
        for (int i = -1000; i < 1001; i++)
        {          
            if (i % 10 != 0)//不是十的倍数 10 20 100.。。
            { //最小网格
                _listNearPoints.Add(new Vector3(i, 0, 1000));
                _listNearPoints.Add(new Vector3(i, 0, -1000));

                _listNearPoints.Add(new Vector3(1000, 0, i));
                _listNearPoints.Add(new Vector3(-1000, 0, i));
            }
            else if (i % 100 != 0)//十的倍数 筛查出不是百的倍数
            {//中间网格
                _listMiddlePoints.Add(new Vector3(i, 0, 1000));
                _listMiddlePoints.Add(new Vector3(i, 0, -1000));

                _listMiddlePoints.Add(new Vector3(1000, 0, i));
                _listMiddlePoints.Add(new Vector3(-1000, 0, i));
            }
            else//剩余百的倍数
            {//最大网格
                _listFarPoints.Add(new Vector3(i, 0, 1000));
                _listFarPoints.Add(new Vector3(i, 0, -1000));

                _listFarPoints.Add(new Vector3(1000, 0, i));
                _listFarPoints.Add(new Vector3(-1000, 0, i));
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        //Debug.Log(2);
    }
    private void LateUpdate()
    {
        if (Mathf.Abs(_cameraTR.position.y)<10)
        {
            if(_enabled_1) _enabled_1=false;
            _nearAlpha = (float)(1 - Mathf.Abs(_cameraTR.position.y) / 10);//这个值随着相机Y轴的距离而变化 
        }
        else
        {
            _enabled_1 = true;
            if(Mathf.Abs(_cameraTR.position.y) < 100)
            {
                if (_enabled_1) _enabled_10 = false;
                _middAlpha = (float)(1 - Mathf.Abs(_cameraTR.position.y) / 100);
            }
            else
            {
                _enabled_10 = true;
            }
        }  
        //Debug.Log(_nearAlpha);
        最小网格透明度  立方的目的是为了加快渐变效果
        //_nearAlpha = (float)Math.Min(Math.Pow(_disNear / _cameraTR.position.y, 3.0f), 1);

        //if (_nearAlpha < 0.1f)
        //{//当最小网格不可见时 开始计算中间网格透明度
        //    _nearAlpha = 0;
        //    _middAlpha = (float)Math.Min(Math.Pow(_disMiddle / _cameraTR.position.y, 3.0f), 1);
        //    _middAlpha = _middAlpha < 0.1f ? 0 : _middAlpha;
        //}
        //else
        //{
        //    _middAlpha = 1;
        //}
    }
    private void OnPostRender()
    {
        GL.PushMatrix();//渲染矩阵的保存 --->对应 PopMatrix
        _lineMaterial.SetPass(0);//激活给定的渲染通道 刷新渲染
        GL.Begin(GL.LINES);//开始绘制一个3d图元  GL.LINES线条 每两点构成一条线段   有多个选择

        //一直显示
        GL.Color(new Color(1f, 1f, 1f, 1));
        for (int i = 0; i < _listFarPoints.Count - 1; i++)
        {
            GL.Vertex(_listFarPoints[i]);
            GL.Vertex(_listFarPoints[i + 1]);
            i++;
        }
        if (!_enabled_1)//最小
        {
            GL.Color(new Color(1f, 1f, 1f, _nearAlpha));
            for (int i = 0; i < _listNearPoints.Count - 1; i++)
            {
                GL.Vertex(_listNearPoints[i]);
                GL.Vertex(_listNearPoints[i + 1]);
                i++;
            }
        }
        if (!_enabled_10)
        {
            GL.Color(new Color(1f, 1f, 1f, _middAlpha));
            for (int i = 0; i < _listMiddlePoints.Count - 1; i++)
            {
                GL.Vertex(_listMiddlePoints[i]);
                GL.Vertex(_listMiddlePoints[i + 1]);
                i++;
            }
        }
        GL.End();//绘制结束
        GL.PopMatrix();//渲染矩阵的回复
    }
}

GL实际应用-在Game窗口显示模型网格——类似Scene视口Wireframe的效果。

作者:叁拾柒度伍_农夫 https://www.bilibili.com/read/cv22788397/ 出处:bilibili

GL实际应用-屏幕画线

Unity实用案例之——屏幕画线和线框渲染_unity 屏幕 画线-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

屋檐上的大修勾

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

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

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

打赏作者

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

抵扣说明:

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

余额充值