[小明学Shader]9.顶点方法(Vertex Function)和顶点色

  渲染过程中,Shader总是优先对每个顶点进行计算(这里如果我们用顶点方法,那么我们的顶点方法就会被调用);顶点计算出后按照一定的格式输出给下面的流程,其中的某一步就是我们放置的surfa方法,它接收的输入可以进行一定的控制(我们将用顶点方法输出).

  整个 shader 相关流程如下:
  1、 shader 准备对一个顶点进行计算。因我们自定义顶点方法,因此 vert 被调⽤
  2、 vert 的第一参数决定该顶点需要带进来哪些属性,我们得到这个属性里的顶点色,把这个顶点色放到 Input 结构中,以供后续的 surf 使用;
  

Shader代码:

Shader "Custom/11.30/0"{
    Properties{
        _MainTex("Base(RGB)",2D)="white"{}
    }
    SubShader{
        Tags{"RenderType"="Opaque"}
        LOD 200
        CGPROGRAM
        #pragma surface surf Lambert vertex:Vetx
        
        sampler2D _MainTex;
        
        struct Input{
            float2 uv_MainTex;
            float4 vertColor;
        };
        
        void surf(Input In,inout SurfaceOutput o){
            half4 c=tex2D(_MainTex,In.uv_MainTex);
            
            o.Albedo=c.rgb*In.vertColor;
        }
        
        void Vetx(inout appdata_full v,out Input o){
            UNITY_INITIALIZE_OUTPUT(Input,o);
            
            o.vertColor=v.color;
        }
        
        ENDCG
    }
}

  上述代码中,我们用到了这一行

#pragma surface surf Lambert vertex:vert

  在光照模型方法后我们加了 vertex:vert,其中 vertex 是关键词,后面跟冒号,再跟一个我们定义的名字,对应到下面的一个方法。这个用来告诉 Unity 编译我们的 shader 的时候,我们需要对顶点做一些相关的操作,所以请它在编译的时候,把我们指定的顶点方法编译,以便让 Unity 引擎执行该 shader 程序的时候用上我们的顶点方法。
再来看指定的这个方法的内容

void vert(inout appdata_full v, out Input o)
{
  UNITY_INITIALIZE_OUTPUT(Input,o);
  o.vertColor = v.color;
}

第一个参数的类型是 appdata_full,这个是从应用程序往 shader 中送入的数据的结构,如位置(vertex)、法线(normal),加上我们这在介绍的顶点色(color)。

struct appdata_full
{
  float4 vertex : POSITION;
  float4 tangent : TANGENT;
  float3 normal : NORMAL;
  float4 texcoord : TEXCOORD0;
  float4 texcoord1 : TEXCOORD1;
  fixed4 color : COLOR;
#if defined(SHADER_API_XBOX360)
  half4 texcoord2 : TEXCOORD2;
  half4 texcoord3 : TEXCOORD3;
  half4 texcoord4 : TEXCOORD4;
  half4 texcoord5 : TEXCOORD5;
#endif
};

      

  虽然有了shader,但是还要对模型传入顶点色,我们用一段c#代码实现.

      程序代码:

using UnityEngine;
using System.Collections;

public class Class11_30 : MonoBehaviour {

    // Use this for initialization
    void Start () {
        Mesh mesh = GetComponent<MeshFilter> ().mesh;

        Vector3[] vertices = mesh.vertices;
        Color[] colors = new Color[vertices.Length];

        colors [0] = Color.red;

        mesh.colors = colors;
    }

}

  效果图:

    因为顶点太多,而只赋值了第一个顶点的颜色,所以看起来只有第一个顶点到其它顶点的插值效果如图.

posted @ 2015-11-30 16:22  WongSiuming  阅读(621)  评论(0编辑  收藏  举报