Unity Shader 之 GL Mesh Shader 实现物体模型的线框效果(也适用于移动端)

 

 

Unity Shader 之 GL Mesh Shader 实现物体模型的线框效果(也适用于移动端)

 

目录

Unity Shader 之 GL Mesh Shader 实现物体模型的线框效果(也适用于移动端)

一、简单介绍

二、实现原理

三、使用说明

四、效果预览

六、关键代码

扫描二维码关注公众号,回复: 11566387 查看本文章

 

一、简单介绍

Shader Language的发展方向是设计出在便携性方面可以和C++、Java等相比的高级语言,“赋予程序员灵活而方便的编程方式”,并“尽可能的控制渲染过程”同时“利用图形硬件的并行性,提高算法效率”。

之前我们说了使用 Geometry Shader 实现物体线框效果,由于 Geometry Shader 在移动端收到限制,所以本节介绍使用 GL 实现在移动端也可以的线框效果。

 

二、实现原理

1、MeshFilter / SkinnedMeshRenderer 获取 mesh 数据

2、在通过 mesh 获取点数据

3、GL 把点数据绘制出来

 

三、使用说明

1、把脚本挂载到需要绘制的模型上

2、右键脚本,可以在编辑模式下自动获取meshes 和 lines 数据,可以节约一些性能

 

四、效果预览

 

五、实现步骤

1、打开Unity ,新建一个工程

 

2、在工程中,新建脚本和shader,shader 主要是控制 GL 线段的颜色,MeshWireframe 主要实现绘制模型线框

 

3、场景添加一个模型,把绘制线框脚本挂在上去

 

4、选中模型,鼠标放在脚本名称上,右键 获取模型的mesh 数据,生成 lines 数据

 

5、在 Test 的物体上添加 Test 脚本,并赋值

 

6、运行场景,效果如上

 

六、关键代码

1、MeshWireframe.cs

using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// 获取模型mesh数据,使用GL绘制模型线框
/// </summary>
[ExecuteInEditMode]
public class MeshWireframe : MonoBehaviour
{
    // 设置线框颜色
    public Color lineColor = Color.white;
    public Material lineMat;
    [ReadOnly]
    [Tooltip("(放在脚本名字上右键)根据当前模型自动获取mesh")]
    public List<Mesh> meshs;
    [ReadOnly]
    [Tooltip("(放在脚本名字上右键)根据当前模型自动算计line")]
    public List<Vector3> lines;

    private void Start()
    {
        
    }

    /// <summary>
    /// GL 绘制线框
    /// </summary>
    private void OnRenderObject()
    {
        // 设置 GL 线的颜色
        lineMat.SetColor("_LineColor", lineColor);
        lineMat.SetPass(0);
        GL.PushMatrix();

        //转换到世界坐标
        GL.MultMatrix(transform.localToWorldMatrix);
        GL.Begin(GL.LINES);
        for (int i = 0; i < lines.Count / 3; i++)
        {

            // 画三角形的方法
            GL.Vertex(lines[i * 3]);
            GL.Vertex(lines[i * 3 + 1]);
            GL.Vertex(lines[i * 3 + 1]);
            GL.Vertex(lines[i * 3 + 2]);
            GL.Vertex(lines[i * 3 + 2]);
            GL.Vertex(lines[i * 3]);
        }
        GL.End();
        GL.PopMatrix();
    }

    /// <summary>
    /// 获取模型的 mesh数据
    /// </summary>
    private void GenerateLines()
    {
        // 清空线数据。获取线数据
        if (lines != null)
            lines.Clear();
        else
            lines = new List<Vector3>();

        // 从 mesh 获取顶点数据
        foreach (var mesh in meshs)
        {
            var vertices = mesh.vertices;
            var triangles = mesh.triangles;
            for (int i = 0; i < triangles.Length / 3; i++)
            {
                // 从 三角形的数据点添加点数据
                lines.Add(vertices[triangles[i * 3]]);
                lines.Add(vertices[triangles[i * 3 + 1]]);
                lines.Add(vertices[triangles[i * 3 + 2]]);
            }
        }
    }

    /// <summary>
    /// 编辑状态下就获取到 Mesh  相关数据
    /// </summary>
    [ContextMenu("根据MeshFilter组件生成Line数据")]
    private void GetMeshesData()
    {
#if UNITY_EDITOR  // 编辑状态下执行
        GameObject o = UnityEditor.Selection.activeGameObject;
        if (o == null)
            return;

        // 获取 mesh 数据
        if (meshs != null)
            meshs.Clear();
        else
            meshs = new List<Mesh>();

        // 从 MeshFilter 获取 mesh 
        MeshFilter[] meshFilters = o.GetComponentsInChildren<MeshFilter>(true);
        if (meshFilters != null && meshFilters.Length > 0)
        {
            foreach (var mf in meshFilters)
            {
                meshs.Add(mf.sharedMesh);
            }
            GenerateLines();
        }
        else
        {
            Debug.LogError("选中物体及子物体没有MeshFilter组件,请添加");
        }

        // 从 SkinnedMeshRenderer 获取 mesh 
        SkinnedMeshRenderer[] skinnedMeshRenderers = o.GetComponentsInChildren<SkinnedMeshRenderer>(true);
        if (skinnedMeshRenderers != null && skinnedMeshRenderers.Length > 0)
        {
            foreach (var sr in skinnedMeshRenderers)
            {
                meshs.Add(sr.sharedMesh);
            }
            GenerateLines();
        }
        else
        {
            Debug.LogError("选中物体及子物体没有SkinnedMeshRenderer组件,请添加");
        }
#endif
    }
}

 

2、GL_LineColor.shader

Shader "Custom/GL_LineColor"
{


	Properties{
		_LineColor("Line Color", Color) = (1.0, 1.0, 1.0, 1.0)
	}

	SubShader{
		Pass {
			Tags { "RenderType" = "Opaque"}
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct v2f
			{
				half4 pos : SV_POSITION;
			};

			fixed4 _LineColor;

			v2f vert(appdata_base  v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : COLOR
			{
				return _LineColor;
			}

			ENDCG
		}
	}
	
}

 

 

 

猜你喜欢

转载自blog.csdn.net/u014361280/article/details/106533954
今日推荐