Partage de cas d'herbe/pelouse Unity (code complet)

L'ancienne règle est de télécharger d'abord l'image.
insérez la description de l'image ici
Récemment, j'ai continué à travailler sur mon nouveau jeu indépendant. J'ai beaucoup profité de la lecture de nombreux cas de prairies sur Internet. Mais récemment, j'ai encore choisi de l'implémenter à ma manière.
Principalement parce que cette méthode peut mieux répondre à mes besoins avant et après. Il reste encore de nombreux points techniques intéressants, si vous avez le temps, je vous les partagerai.
Cette fois, parlons d'abord de la mise en œuvre de l'herbe :
puisque l'herbe doit s'adapter à la surface du modèle, elle part de la surface du modèle attaché :
1. Cycle Mesh triangle values, enregistre un ensemble de données en unités de triangles, le contenu est Trois positions de sommet et leurs informations normales.
insérez la description de l'image ici
code afficher comme ci-dessous:

private List<GlassPoint> myData;
        private RaycastHit Hit;
        private List<GameObject> objGlass;
        private void __CreateGlass(MeshFilter myTarget)
        {
    
    
            if (myTarget != null && myTarget.mesh != null)
            {
    
    
                int myLength = myTarget.mesh.triangles.Length;
                Vector3[] vector = myTarget.mesh.vertices;
                Vector3[] normal = myTarget.mesh.normals;
                int[] triangles = myTarget.mesh.triangles;
                myData = new List<GlassPoint>();
                for (int i = 0; i < myLength; i += 3)
                {
    
    
                    //取得索引
                    int index = triangles[i];
                    int index2 = triangles[i + 1];
                    int index3 = triangles[i + 2];
                    //修改为以第一个点为中心的相对值
                    Vector3 offset1 = vector[index];
                    Vector3 offset2 = vector[index2] - offset1;
                    Vector3 offset3 = vector[index3] - offset1;

                    //顶点沿法线偏移出去,再随机一定位置后再反射回来找位置
                    Vector3 startPos = offset1 + (normal[index].normalized*50) + (Vector3.one * UnityEngine.Random.Range(-10.0f, 10.0f));
                    if (Physics.Raycast(startPos, -normal[index], out Hit, 100))
                    {
    
    
                        GlassPoint point = new GlassPoint();
                        //通过射线取第一个点,并算出另外两个点
                        point.pos = Hit.point;
                        point.pos2 = point.pos + offset2;
                        point.pos3 = point.pos + offset3;
                        //记录法线
                        point.norm = normal[index];
                        point.norm2 = normal[index2];
                        point.norm3 = normal[index3];
                        myData.Add(point);
                    }
                }
            }
        }

Ce qui précède est que chaque ensemble de données enregistre les informations des trois sommets et leurs normales.
Il convient de mentionner que puisque l'emplacement est différent de la normale, ici le point de base est trouvé en décalant le sommet le long de la normale, puis en réfléchissant pour trouver l'emplacement à un emplacement aléatoire.
2. Après avoir trouvé l'emplacement et les informations, créez un Mesh pour écrire les informations de chaque herbe. Le nombre pouvant être très important, il peut être nécessaire de séparer plusieurs Mesh, le code est le suivant :

private void CreateGlassMesh(List<GlassPoint> data)
        {
    
    
            for (int i = 0; i < 100; i++)
            {
    
    
                CreateGlass(i, data);
            }
        }
private void CreateGlass(int index, List<GlassPoint> myGlassData)
        {
    
    
            int step = 9000;
            int startIndex = index * step;
            if (startIndex > myGlassData.Count) return;
            int endIndex = Mathf.Min(startIndex + step, myGlassData.Count);

            Mesh mesh = new Mesh();
            List<Vector3> vector = new List<Vector3>();
            List<int> triangle = new List<int>();
            List<Vector2> uv = new List<Vector2>();

            int length = endIndex - startIndex;
            for (int i = 0; i < length; i++)
            {
    
    
                SingleGlass(i, ref vector, ref triangle, ref uv, myGlassData[startIndex + i], UnityEngine.Random.Range(0.8f, 1.2f), UnityEngine.Random.Range(0.4f, 1f));
            }

            mesh.SetVertices(vector);
            mesh.SetIndices(triangle.ToArray(), MeshTopology.Triangles, 0);
            mesh.uv = uv.ToArray();

            GameObject ObjGlass = new GameObject();
            ObjGlass.name = "MyGlass" + index;
            MeshFilter meshFilter = ObjGlass.AddComponent<MeshFilter>();
            MeshRenderer ren = ObjGlass.AddComponent<MeshRenderer>();
            meshFilter.mesh = mesh;
            ren.material = Com.m_matGlass;
        }

Ici, nous nous concentrons sur la façon dont chaque herbe est générée. Comme le montre la figure, il y a trois surfaces triangulaires inversées avec quatre points et sommets. Concentrez-vous sur l'UV inférieur. Le X ci-dessus est la plage de 0-0,5 et 0,5-1 respectivement. :
insérez la description de l'image ici
coder comme suit :

private void SingleGlass(int index, ref List<Vector3> vert, ref List<int> triangle, ref List<Vector2> uv, GlassPoint data, float w, float h)
        {
    
    
            Vector3 normal = ((data.norm + data.norm2 + data.norm3) / 3).normalized;

            Vector3 offset = normal * h;
            Vector3 pos4 = (data.pos + data.pos2 + data.pos3) / 3 - normal * 0.3f;//防止因误差出现飞天草
            Vector3 pos1 = data.pos + offset;
            Vector3 pos2 = data.pos2 + offset;
            Vector3 pos3 = data.pos3 + offset;

            vert.Add(pos1);
            vert.Add(pos2);
            vert.Add(pos3);
            vert.Add(pos4);

            uv.Add(new Vector2(0, 1));
            uv.Add(new Vector2(0.5f, 1));
            uv.Add(new Vector2(1, 1));
            uv.Add(new Vector2(0.5f, 0));

            index *= 4;
            triangle.Add(index);
            triangle.Add(index + 1);
            triangle.Add(index + 3);

            triangle.Add(index + 1);
            triangle.Add(index + 2);
            triangle.Add(index + 3);

            triangle.Add(index + 2);
            triangle.Add(index);
            triangle.Add(index + 3);
        }

Voici la partie matérielle. Utilisez le test de transparence pour découper la forme de l'herbe, puis utilisez l'UV supérieur oscillant pour créer l'effet du vent. Le code :

Shader "Custom/Glass" {
    
    
	Properties{
    
    
		[Header(Ground_Base)]
		_MainTex("RGB:基础色 A:透明通道",2D) = "white"{
    
    }
		_MainCol("基本色",Color) = (0.5,0.5,0.5,1.0)
		_Speed("速度 ",Range(0,10)) = 5
		_Scope("幅度 ",Range(0,1)) = 0.3
	}
		SubShader{
    
    
			Tags{
    
    "RenderType" = "Opaque"}

			Pass{
    
    
				Tags{
    
    "LightMode" = "ForwardBase"}
				//ZWrite off
			Cull off
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "Lighting.cginc"
				#include "AutoLight.cginc"
				#include "UnityCG.cginc"
				#pragma target 3.0
			//地面参数
			uniform sampler2D _MainTex; uniform half4 _MainTex_ST;
			uniform half3 _MainCol;
			uniform half _Speed;
			uniform fixed _Scope;

			//输入结构
			struct a2v {
    
    
				float4 vertex:       POSITION;				//顶点信息
				float2 uv0:          TEXCOORD0;				//UV信息
			};
			//输出结构
			struct v2f {
    
    
				float4 pos:SV_POSITION;						//屏幕定点位置
				float2 uv0:TEXCOORD0;						//UV
			};
			v2f vert(a2v v) {
    
    
				v2f o;																			//新输出结构
				o.pos = UnityObjectToClipPos(v.vertex);											//顶点位置    OS>CS
				o.uv0 = v.uv0 *_MainTex_ST.xy + _MainTex_ST.zw;									//传弟UV
				o.uv0.x = o.uv0.x + (sin(_Time.x*_Speed)*_Scope * o.uv0.y);						//摆动
				return o;
			}
			float4 frag(v2f i) :SV_TARGET{
    
    
				//纹理采样
				half4 var_MainTex = tex2D(_MainTex, i.uv0);
				//裁剪
				clip(var_MainTex.a - 0.1);
				//最终混合
				half3 finalRGB = var_MainTex * _MainCol;
				return half4(finalRGB ,1);
		}
	ENDCG
}

La texture de l'herbe est à peu près comme ça :
insérez la description de l'image ici
il y a un espace au milieu, parce que le visage va être changé... Hee hee.

Ce n'est peut-être pas une manière intelligente, mais c'est une manière qui répond aux besoins de mon projet, et j'espère que cela sera utile à tout le monde, merci.

Je suppose que tu aimes

Origine blog.csdn.net/ww1351646544/article/details/119875969
conseillé
Classement