zoukankan      html  css  js  c++  java
  • [小明学Shader]15.基于Grid的地形混合shader

    1.写在前面

      好久没有写博客了,最近面试不太顺利,认识到应该把学习心得或者说是结果都落实到博客上来,一来加深印象,二来有利于自我展示.

      本片博客的内容是讲地形纹理混合,是关于手游sgl大地图的shader实现.

      slg大地图,如cok,是很大的.在渲染时,只渲染屏幕周围的一部分.

      在渲染屏幕地形时,会提供一组地形数据,shader会根据地形数据对地形进行混合.

    2.混合方法

      混合使用的方法是非常常见的纹理混合.

      基本原理是为shader提供多张可以选用的地形贴图.然后根据一张alpha贴图或者其它方式来决定纹理的如何混合.即选用哪个层级的地形纹理进行渲染.

    3.纹理选择

      前文有提到,本shader是在slg游戏中做地形混合的.

      在手游slg中,如cok,地形只是渲染在一个平面上的.

      如下图所示,其中每一个小的方格可以代表一个地形单位.

      

      而每一个小的地形单位,可以用一个标记位来表示地形所使用的纹理的种类.

    5.选择纹理混合信息标识

      那么要怎么告诉shader在渲染时要使用哪个纹理呢,

      本文所使用的方法是通过顶点色.

      在Unity当中,为每一个Mesh默认提供了一个顶点数组,一个三角形数组和一个顶点颜色数组,值得一提的是每一个Mesh还都拥有四个UV数组.

      顶点色有rgba四个通道,再加上1-(rgba的和)刚好可以用来表示五层纹理的混合参数.其中1-(rgba和)用来表示默认层纹理的混合参数.

    6.设置顶点颜色 

      决定了采用顶点色来表示混合参数之后,我们还要决定把哪些顶点设置颜色.

      以本文所用的square地形为例,每一个小的地形Cell都有两个三角形,四个顶点组成,那么既然如此,我们只需要把这四个顶点的顶点色中,代表该地块纹理的通道值+1即可.

      在遍历完所有地块,设置完定点后,需要对定点颜色执行约束操作,按比例缩放,保证和值不超过1.

      将得到的顶点色赋值给mesh即可.

    7.效果示意:

    8.参考

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

      https://www.cnblogs.com/luxishi/p/6670487.html

    9.源码:

      shader:

      

     1 Shader "SlpatMap/TerrainLab"
     2 {
     3     Properties
     4     {
     5         _Splat0 ("_SlpatTex0", 2D) = "white" {}
     6         _Splat1 ("_SlpatTex1", 2D) = "white" {}
     7         _Splat2 ("_SlpatTex2", 2D) = "white" {}
     8         _Splat3 ("_SlpatTex3", 2D) = "white" {}
     9         _Splat4 ("_SlpatTex4", 2D) = "white" {}
    10     }
    11     SubShader
    12     {
    13         Tags { "RenderType"="Opaque" }
    14         LOD 100
    15 
    16         Pass
    17         {
    18             CGPROGRAM
    19             #pragma vertex vert
    20             #pragma fragment frag
    21 
    22             #include "UnityCG.cginc"
    23 
    24             struct appdata
    25             {
    26                 float4 vertex : POSITION;
    27                 float2 texcoord : TEXCOORD0;
    28                 fixed4 color : COLOR;
    29             };
    30 
    31             struct v2f
    32             {
    33                 float4 vertex : SV_POSITION;
    34                 float2  uv[5] : TEXCOORD0;
    35                 fixed4 color : COLOR0;
    36                 fixed color2 : COLOR1;
    37             };
    38 
    39         
    40             sampler2D _Splat0;
    41             sampler2D _Splat1;
    42             sampler2D _Splat2;
    43             sampler2D _Splat3;
    44             sampler2D _Splat4;
    45 
    46             float4 _Splat0_ST;
    47             float4 _Splat1_ST;
    48             float4 _Splat2_ST;
    49             float4 _Splat3_ST;
    50             float4 _Splat4_ST;
    51             
    52             v2f vert (appdata v)
    53             {
    54                 v2f o;
    55                 o.vertex = UnityObjectToClipPos(v.vertex);
    56                 o.uv[0] = TRANSFORM_TEX(v.texcoord, _Splat0);
    57                 o.uv[1] = TRANSFORM_TEX(v.texcoord, _Splat1);
    58                 o.uv[2] = TRANSFORM_TEX(v.texcoord, _Splat2);
    59                 o.uv[3] = TRANSFORM_TEX(v.texcoord, _Splat3);
    60                 o.uv[4] = TRANSFORM_TEX(v.texcoord, _Splat4);
    61                 o.color = v.color;
    62                 o.color2 = (1 - (v.color.r + v.color.g + v.color.b + v.color.a));
    63                 return o;
    64             }
    65             
    66             fixed4 frag (v2f i) : SV_Target
    67             {
    68                 fixed3 zero = fixed3(0, 0, 0);
    69                 fixed3 splat1Col = i.color.r <= 0.001 ? zero : tex2D(_Splat0, i.uv[0]).xyz * i.color.r;
    70                 fixed3 splat2Col = i.color.g <= 0.001 ? zero : tex2D(_Splat1, i.uv[1]).xyz * i.color.g;
    71                 fixed3 splat3Col = i.color.b <= 0.001 ? zero : tex2D(_Splat2, i.uv[2]).xyz * i.color.b;
    72                 fixed3 splat4Col = i.color.a <= 0.001 ? zero : tex2D(_Splat3, i.uv[3]).xyz * i.color.a;
    73                 fixed3 splat5Col = i.color2 <= 0.001 ? zero : tex2D(_Splat4, i.uv[4]).xyz * i.color2;
    74                 fixed4 col;
    75                 col.xyz = splat1Col + splat2Col + splat3Col + splat4Col + splat5Col;
    76                 col.w = 1;
    77                 return col;
    78             }
    79             ENDCG
    80         }
    81     }
    82 }
    View Code

      c#代码:

     1 using System.Collections.Generic;
     2 using UnityEngine;
     3 
     4 public class SquarePlaneComponent : MonoBehaviour
     5 {
     6 
     7     static int[,] terrainType = new int[,]{
     8         {0,0,0,1,1,1,1,1,1,1},
     9         {1,1,1,1,1,1,1,1,1,1},
    10         {1,1,1,1,1,1,1,1,1,1},
    11         {1,1,2,2,1,1,1,1,1,1},
    12         {1,1,2,2,3,3,3,3,3,1},
    13         {1,1,1,2,1,1,1,1,1,1},
    14         {1,1,1,1,1,1,1,1,1,0},
    15         {1,1,1,1,1,1,1,1,1,0},
    16         {1,1,1,1,1,1,1,1,1,0},
    17         {1,1,1,1,1,1,1,1,1,1},
    18 
    19     };
    20     public int rows = 10;
    21 
    22     public int cols = 10;
    23 
    24     public MeshRenderer meshRenderer;
    25 
    26     public MeshFilter meshFilter;
    27 
    28 
    29     public int[] vertGridMappingArr;
    30 
    31     [ContextMenu("UpdateColorInfo")]
    32     public void UpdateUVInfo()
    33     {
    34         var vertices = meshFilter.sharedMesh.vertices;
    35         var colors = new Color[vertices.Length];
    36         var uv = meshFilter.sharedMesh.uv;
    37         var colorsV = new Vector4[vertices.Length];
    38         var VRowLength = rows + 1;
    39 
    40         var col = terrainType.GetLength(0);
    41         var row = terrainType.GetLength(1);
    42 
    43         for (int i = 0; i < col; i++)
    44         {
    45             for (int j = 0; j < row; j++)
    46             {
    47                 var index = (i + 1) * VRowLength - j - 1;
    48                 var leftTop = index;
    49                 var rightTop = index - 1;
    50                 var leftBottom = index + VRowLength;
    51                 var rightBottom = index + VRowLength - 1;
    52 
    53                 var indexList = new List<int>() { leftTop, rightTop, leftBottom, rightBottom };
    54                 foreach (var t in indexList)
    55                 {
    56                     colorsV[t] = Set(colorsV[t], terrainType[i, j]);
    57                 }
    58             }
    59         }
    60 
    61         for (int i = 0; i < vertices.Length && i < colors.Length; i++)
    62         {
    63             var cv = colorsV[i] / colorsV[i].magnitude;
    64             colors[i] = new Color(cv.x, cv.y, cv.z, cv.w);
    65         }
    66         meshFilter.sharedMesh.colors = colors;
    67     }
    68 
    69     public Vector4 Set(Vector4 v, int type)
    70     {
    71         switch (type)
    72         {
    73             case 0:
    74                 v.x += 1;
    75                 break;
    76             case 1:
    77                 v.y += 1;
    78                 break;
    79             case 2:
    80                 v.z += 1;
    81                 break;
    82             case 3:
    83                 v.w += 1;
    84                 break;
    85         }
    86         return v;
    87     }
    88 }
    View Code

      

     

  • 相关阅读:
    如何在iTerm2中配置oh my zsh?
    sublime中格式化jsx文件
    ES6 new syntax of Literal
    ES6 new syntax of Rest and Spread Operators
    How to preview html file in our browser at sublime text?
    ES6 new syntax of Default Function Parameters
    ES6 new syntax of Arrow Function
    七牛云2018春招笔试题
    Spring-使用注解开发(十二)
    Spring-声明式事物(十一)
  • 原文地址:https://www.cnblogs.com/WongSiuming/p/11018866.html
Copyright © 2011-2022 走看看