(一)GL简介

1.前言

Unity GL类是Low-Level图像类,提供了最基本的图形画法,其与OpenGL的直接画法类似。但是与Graphics类相比,Graphics类更高效。
GL类一般不能再update以及start等脚本方法中调用(可以调用,但是不会显示)。因为在Unity脚本的生命周期中,当开始渲染时camera会clear图像,如果在生命周期的渲染方法调用前调用GL类进行绘制,那么此时绘制的图像很大可能会被Clear掉,所以不会显示。

2.简单示例

本文以官方文档中的一个示例进行分析,并作了简单的修改。

2.1 基本方法

GL类提供了五种最基本的图像绘制种类,即线、三角形和四边形,绘制时以GL.Begin开始,以GL.End结束,中间通过GL.Color来更改颜色,通过GL.Vertex或者GL.Vertex3来添加顶点,如下所示。如果需要进行矩阵变换,则在GL.Begin之前进行矩阵变换,后续会对矩阵问题进行详细分析。

    private void DrawLines()
    {
        GL.Begin(GL.LINES);

        float angleDelta = 2 * Mathf.PI / lineCount;

        for (int i = 0; i < lineCount; i++)
        {
            float angle = angleDelta * i;
            GL.Color(new Color((float)i / lineCount, 1 - (float)i / lineCount, 1, 1));
            GL.Vertex3(0, 0, 0);
            GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0);
        }

        GL.End();
    }

2.2 调用位置

GL类的方法一般要在跟渲染有关的周期函数中调用,因为涉及的后期效果等问题,一般推荐在OnRenderObject方法中调用。所以使用GL的脚本要挂载在含有Camera的游戏物体上。

2.3 设置材质

调用位置和调用方法都已经明确,此时还需要设置渲染状态,即以什么样式或者效果进行渲染。所以此时要设置材质,示例采用内置的shader,并激活渲染的通道,即shader的Pass,如下所示:

    private void SetMaterialPass()
    {
        if (glMat == null)
        {
            glMat = new Material(Shader.Find("Hidden/Internal-Colored"));
            /*glMat.hideFlags = HideFlags.HideAndDontSave;
            glMat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            glMat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            glMat.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
            glMat.SetInt("_ZWrite", 0);*/
        }

        glMat.SetPass(0);
    }

原文中代码未注释。也有采用如下shader进行示例演示的,如下所示,但是此shader未进行颜色的传递,所以GL.Color无效。

Shader "Custom/Colored_Blended"
{
	SubShader
	{
		Pass
		{
			BindChannels { Bind "Color", color }
			Blend SrcAlpha OneMinusSrcAlpha
			ZWrite Off Cull Off Fog { Mode Off }
		}
	}
}

2.4 完整代码

可通过更改radius或者lineCount来产生变化,如果在保证脚本正确的情况下,图像未出现,检查脚本所在游戏物体是不是含有camera,以及绘制图像是否在camera的事业范围内。

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

public class Graphics01GLExample : MonoBehaviour
{
    public int lineCount = 10;
    public float radius = 3;

    private Material glMat;

    private void OnRenderObject()
    {
        SetMaterialPass();

        DrawLines();
    }

    private void SetMaterialPass()
    {
        if (glMat == null)
        {
            glMat = new Material(Shader.Find("Hidden/Internal-Colored"));
            /*glMat.hideFlags = HideFlags.HideAndDontSave;
            glMat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
            glMat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
            glMat.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
            glMat.SetInt("_ZWrite", 0);*/
        }

        glMat.SetPass(0);
    }

    private void DrawLines()
    {
        GL.Begin(GL.LINES);

        float angleDelta = 2 * Mathf.PI / lineCount;

        for (int i = 0; i < lineCount; i++)
        {
            float angle = angleDelta * i;
            GL.Color(new Color((float)i / lineCount, 1 - (float)i / lineCount, 1, 1));
            GL.Vertex3(0, 0, 0);
            GL.Vertex3(Mathf.Cos(angle) * radius, Mathf.Sin(angle) * radius, 0);
        }

        GL.End();
    }
}

发布了144 篇原创文章 · 获赞 0 · 访问量 2241

猜你喜欢

转载自blog.csdn.net/qq_37833413/article/details/104324850