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.PushMatrix和GL.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的对比
OPENGL | UNITY3D | 解释 |
---|---|---|
GL_LINE_STRIP | LINE_STRIP | 绘制线条带 |
GL_LINES | LINES | 绘制线条,每两点构成一条线段 |
GL_QUADS | QUADS | 绘制四边形 |
GL_TRIANGLES_STRIP | TRIANGLE_STRIP | 绘制三角形带 |
GL_TRIANGLES | TRIANGLES | 绘制三角形 |
GL_POINTS | 无 | 一系列独立的顶点 |
GL_POLYGON | 无 | 简单、凸多边形的边界 |
GL_LINE_LOOP | 无 | 顶点相连,连成一系列线段,头尾连 |
GL_TRINGLE_FAN | 无 | 相连的三角形扇形 |
GL_QUAD_STRIP | 无 | 相连的四边形 |
OpenGL与Unity在Begin与End间可调用的函数
glVertex | Vertex Vertex3 | 定义顶点坐标 |
glColor | Color | 设置当前颜色 |
glIndex | 无 | 设置当前颜色索引 |
glNormal | 无 | 定义法向向量 |
GlEvalCoord | 无 | 生成坐标 |
glCallList,glCallLists | 无 | 执行显示列表 |
glTexCoord | TexCoord,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 编辑器的描边是什么弄的-优快云博客
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