欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

unity shader 学习笔记(一)

程序员文章站 2024-02-14 09:45:40
...

Unity3D Shader 可编程着色器

常用模板:(这里说明Unlit,standard surface 另算)

这里的着色器只能实现最基本的功能,即放置贴图Texture,以及通过Tiliing和Offset进行调整

//	Unlit类型的着色器写在 Pass 通道内,一个显示效果可用多个 Pass 通道叠加表示
Shader "MyShader/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}	//	贴图
    }
    SubShader	//	着色器都写在 SubShader 里面
    						//	可以存在多个SubShader,但一个材质最后只能按先后顺序采用一种SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass 	//	Unlit类型的着色器写在 Pass 通道内,一个显示效果可用多个 Pass 通道叠加表示
        {
            CGPROGRAM

            #pragma vertex vert	//	顶点着色器
 //          #pragma geometry geo//	几何着色器
            #pragma fragment frag	//	片段着色器


            #include "UnityCG.cginc"

            struct appdata	//	传入给顶点着色器的数据
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f	//	顶点(V)传入给片段(f)的
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
			
			//	顶点着色器,将处理过后的顶点数据输出给片段着色器
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);	//	坐标变换。又物体自身坐标变为裁剪坐标
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);	//	TRANSFORM_TEX方法比较简单,
              //  就是将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的定点uv。
			//	参考:https://blog.csdn.net/u010133610/article/details/78789940
                return o;	//	传递给片段着色器
            }

			//	片段着色器
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv); // 对贴图进行采样,得到顶点对应(UV)的颜色

                return col;	//	输出颜色值
            }
            ENDCG
        }
    }
}

顶点着色器

//声明
#pragma vertex vert
//传入传出数据
struct appdata // 传入给顶点着色器的数据
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f // 顶点(V)传入给片段(f)的
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

几何着色器

几何着色器的声明可放在顶点着色器和片段着色器之间(也可以打乱顺序),比如:
#pragma vertex vert // 顶点着色器
#pragma geometry geo// 几何着色器
#pragma fragment frag // 片段着色器
顶点数据会最先进入顶点着色器,然后经过几何着色器到片段着色器。如果没有编写几何着色器则直接进入片段着色器(如上例代码片段)

若有几何着色器则可写成如下最简单的形式:
// 参考: https://www.cnblogs.com/Firepad-magic/p/10698749.html

Shader "ShaderDemo/SimplePoint"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert 
            //-------声明几何着色器
            #pragma geometry geom 
            #pragma fragment frag 

            #include "UnityCG.cginc" 

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

    //-------顶点向几何阶段传递数据 
    struct v2g {
        float4 vertex:SV_POSITION;
        float2 uv:TEXCOORD0;
    };

    //-------几何阶段向片元阶段传递数据 
    struct g2f
    {
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
    };

    sampler2D _MainTex;
    float4 _MainTex_ST;

    v2g vert(appdata v)
    {
        v2g o;
        o.vertex = UnityObjectToClipPos(v.vertex);
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
        return o;
    }
    //-------静态制定单个调用的最大顶点个数 
    [maxvertexcount(3)]
    void geom(triangle v2g input[3], inout TriangleStream<g2f> outStream) {
        for (int i = 0; i < 3; i++) {
            g2f o = (g2f)0;
            o.vertex = input[i].vertex;
            o.uv = input[i].uv;

            //-----将一个顶点添加到输出流列表 
            outStream.Append(o);
        }

        //-------restart strip可以模拟一个primitives list 
        outStream.RestartStrip();
    }

    fixed4 frag(g2f i) : SV_Target
    {
        // sample the texture 
        fixed4 col = tex2D(_MainTex, i.uv);
        return col;
    }
    ENDCG
}
    }
}

这份代码最后的效果与之前一样,即这里的几何着色器函数 geom 没有实现特殊功能。关于几何着色器的描述可参考 https://www.cnblogs.com/Firepad-magic/p/10698749.html

几何着色器的输入输出为:
triangle v2g input[3], inout TriangleStream outStream

其中输入输出类型均可自己设置。
输入和输出都是图元类型,输入可以点,也可以是三角形,输出同样有多种类型。
此外还要指明输出多大顶点数
[maxvertexcount(3)]
这里几何着色器输入一个三角形即三个顶点,输出一个三角形,最大输出顶点数也是三个即一个三角形,所以这里既没有增加顶点也没有减少顶点。

片段着色器

// 声明
#pragma fragment frag
输入为顶点着色器或者几何着色器传入过来的数据
输出为SV_Target,通常是(fixed4)颜色值

此次shader示例图:
unity shader 学习笔记(一)