Vertex and Fragment Shader Examples

创建一个Shader

    Shader "Custom/NewShader" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
            Tags { "RenderType" = "Opaque" }
            LOD 200

            CGPROGRAM
            #pragma surface surf Lambert

            sampler2D _MainTex;

            struct Input {
                float2 uv_MainTex;
            };

            void surf (Input IN, inout SurfaceOutput o) {
                half4 c = tex2D (_MainTex, IN.uv_MainTex);
                o.Albedo = c.rgb;
                o.Alpha = c.a;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

空的Shader

你可以看到在代码中ShaderLab材质的四个主要部分。


    Shader "Custom/Empty" {
        SubShader {
            Pass {
                CGPROGRAM
                ENDCG
            }
        }
    }

Shader

着色器命令包含一个字符串与Shader的名称。这个名字可以用“/”字符细分模拟一个文件夹结构,简化未来着色器的二次利用。在所有着色器的名称应该是唯一的。

SubShader

Shader可以包含一个或多个SubShaders,主要是用于实现着色器对不同GPU的能力。所有在场的SubShaders应该使用不同的技术类似的结果为每个架构。ShaderLab翻译的代码着色器自动到其他架构,但在某些情况下完全着色器的功能在移动架构不理想或一些输入是失踪,你将使用一个简单的SubShader在Shader中和执行桌面架构实现。

Pass

每个SubShader由passes,和每个pass代表顶点和片段代码的一个执行同一个对象呈现的材料材质。你应该实现传递的材质与最小的数可能由于性能的原因。

CGPROGRAM .. ENDCG

这些指令定义在ShaderLab着色器使用的语言。Unity可以使用Cg和GLSL的材质语言。Cg语言是推荐的,因为几个优化步骤实现不同的体系结构。

简单的 Shader

顶点之间的区别和片段着色器是一个过程开发的渲染管道。顶点着色器可以定义为着色器程序修改场景的几何形状,使3d投影。相关片段着色器渲染窗口,定义每个像素的颜色。片段和顶点着色器可以提供更多的功能在新的显卡,如移动顶点位置为每个像素或存储更多的数据。

Shader "Custom/SolidColor" {
    SubShader {
        Pass {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float4 v:POSITION) : SV_POSITION {
                return mul (UNITY_MATRIX_MVP, v);
            }

            fixed4 frag() : SV_Target {
                return fixed4(1.0,0.0,0.0,1.0);
            }

            ENDCG
        }
    }
}

pragma vertex vert

顶点着色器是一个着色器程序修改场景的几何形状。它为每个顶点在现场执行,和输出的坐标投影,颜色,纹理和其他数据传递到片段着色器。该指令# pragma顶点(函数名)是用于定义顶点函数的名称。

pragma fragment frag

片段着色器是一个着色器程序修改渲染图像属性窗口。是执行的每个像素和输出信息的像素的颜色是红色的。该指令# pragma片段定义的功能片段着色器的名称。

float4 vert(float4 v:POSITION) : SV_POSITION

变量v包含顶点的值,调用这个函数为每个顶点的场景呈现。返回值是一个float4变量与顶点的位置在屏幕上,使用四个浮点值存储在2d SV_POSITION coordinate窗口是因为预计的几何投影在齐次坐标像素在屏幕上使用两个值(x,y),一个值的深度(z)和一个值(w)的齐次空间。你可以将齐次坐标转换为三维坐标,但是你会失去获得未来3 d顶点的位置,也可以删除z值,但你会失去执行深度测试的能力在最后的渲染。齐次坐标用于几乎所有的gpu。

消除变量的顶点着色器输出着色器不代表任何代码的优化,而不是让代码不通用的,更难以理解。

return mul (UNITY_MATRIX_MVP, v);

这是顶点的核心函数,在3d坐标投影到二维窗口。这个过程包括乘以3d位置矩阵称为Model-View-Projection

fixed4 frag() : COLOR

这一行定义了函数的片段,也就是片段着色器使用的是其主要功能。在这节课中,没有分段函数的输入参数,输出是定义为一个颜色值定义在一个fixed4变量包含RGBA(红,绿,蓝,α)的颜色。可以使用颜色作为可视化的一个浮点数变量,甚至顶点之间传递信息和片段着色器。然而颜色变量值0和1之间的限制所以希望改变颜色变量中的值。

return fixed4(1.0,0.0,0.0,1.0)

分段函数的核心功能,为每个像素处理的片段着色器定义了红色。

Window Coordinates

这个着色器定义了一个静态的颜色取决于窗口的像素坐标。这允许定义屏幕颜色的独立于几何渲染。如果你移动plane,你可以在屏幕上看到的颜色变化。


    Shader "Custom/WindowCoordinates/Base" {
        SubShader {
            Pass {
                CGPROGRAM

                #pragma vertex vert
                #pragma fragment frag
                #pragma target 3.0

                #include "UnityCG.cginc"

                float4 vert(appdata_base v) : POSITION {
                    return mul (UNITY_MATRIX_MVP, v.vertex);
                }

                fixed4 frag(float4 sp:VPOS) : SV_Target {
                    return fixed4(sp.xy/_ScreenParams.xy,0.0,1.0);
                }

                ENDCG
            }
        }
    }

pragma target 3.0

目标指令定义了硬件需求支持着色器。

include "UnityCG.cginc"

Include the file “UnityCG.cginc” inside the code of the shader.

appdata_base v

Unity定义了一个默认的结构设置顶点着色器的输入变量。

VPOS

Input argument for the frag function, which is declared as a float4 type and VPOS semantics. Semantics is a special clause of HLSL/Cg to define the default input values of a fragment/vertex Shader. VPOS fills the variable with the values of the pixel coordinates in the screen of the rendered shader. This position needs to be divided by the screen size, the values are transformed into 0 and 1 values so they can be mapped as the RG components of the output color. frag函数输入参数,声明为float4类型和VPOS语义。语义是一种特殊的条款HLSL / Cg定义默认的输入值的一个片段/顶点着色器。VPOS充满变量的值像素坐标的屏幕材质呈现。这个职位需要除以屏幕大小的值转换为0和1的值,这样他们就可以被映射的RG组件输出的颜色。

ScreenParams

The screen width and height values are stored in the variable _ScreenParams; this variable is declared in the UnityCG.cginc file. 屏幕的宽度和高度值存储在变量_ScreenParams;UnityCG中声明该变量。cginc文件。 

Examples Window coordinates are not commonly used in shaders, because normally the shaders work with the position of the texture as you will see in the next lessons. However some interesting effects like Render with a Mask or some other image effects use this property. 在着色器窗口坐标是不常用的,因为通常着色器使用纹理正如您将看到的位置在接下来的课程。然而一些有趣的效果,如用Mask渲染图或其他的形象影响使用这个属性。

Behind bars


    Shader "Custom/WindowCoordinates/Bars" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                struct vertOut {
                    float4 pos:SV_POSITION;
                    float4 scrPos;
                };

                vertOut vert(appdata_base v) {
                    vertOut o;
                    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                    o.scrPos = ComputeScreenPos(o.pos);
                    return o;
                }

                fixed4 frag(vertOut i) : SV_Target {
                    float2 wcoord = (i.scrPos.xy/i.scrPos.w);
                    fixed4 color;

                    if (fmod(20.0*wcoord.x,2.0)<1.0) {
                        color = fixed4(wcoord.xy,0.0,1.0);
                    } else {
                        color = fixed4(0.3,0.3,0.3,1.0);
                    }
                    return color;
                }

                ENDCG
            }
        }
    }

struct vertOut

定义一个新类型的变量,这是一个复合类型,代表一组其他变量与本地或复合类型。结构时使用超过一个本地数据需要通过从顶点到片段着色器。作为一个函数的返回数据只有一个变量,用结构的一组值可以表示成一个唯一值。

ComputeScreenPos

UnityCG函数定义。cginc文件,这个函数返回屏幕位置的片段着色器。与前面的例子的区别VPOS语义变量使用,这个函数是多平台,它不需要目标3.0。

Vignetting 渐晕


    Shader "Custom/WindowCoordinates/Vignetting" {
        SubShader {
            Pass {
                CGPROGRAM

                #pragma vertex vert
                #pragma fragment frag
                #pragma target 3.0

                #include "UnityCG.cginc"

                float4 vert(appdata_base v) : POSITION {
                    return mul (UNITY_MATRIX_MVP, v.vertex);
                }

                fixed4 frag(float4 sp:VPOS) : SV_Target {
                    float2 wcoord = sp.xy/_ScreenParams.xy;
                    float vig = clamp(3.0*length(wcoord-0.5),0.0,1.0);
                    return lerp (fixed4(wcoord,0.0,1.0),fixed4(0.3,0.3,0.3,1.0),vig);
                }
                ENDCG
            }
        }
    }

lerp

Standard function of the Cg language, this function is a linear interpolation between the first two arguments given the third as a factor. Many functions are implemented in the Cg language as standard functions. Cg语言的标准函数,这个函数是第一个两个参数之间的线性插值给定的第三个因素。实现许多功能在Cg语言作为标准功能。

Circles Mask

Some shaders need external information given in types like Variables, Arrays, Textures. These cases are covered by the use of uniforms and properties in ShaderLab. Properties define a set of types which can be passed to the shader in every run. The variables can modify the behavior of the shader. The following example shows how to change the values of a shader mask full of circles. The number of rows and columns can also change the size of the circles. 一些着色器需要外部信息的类型变量、数组、纹理。这些案例是由在ShaderLab 中uniforms和properties的使用。属性定义一组类型,可以传递给每个运行的材质。变量可以修改材质的行为。下面的例子显示了如何改变的值的shader mask。行和列的数量也可以改变大小的圆圈。


    Shader "Custom/WindowCoordinates/CirclesMask" {
        Properties {
            _CirclesX ("Circles in X", Float) = 20
            _CirclesY ("Circles in Y", Float) = 10
            _Fade ("Fade", Range (0.1,1.0)) = 0.5
        }
        SubShader {
            Pass {

                CGPROGRAM

                #pragma vertex vert
                #pragma fragment frag
                #pragma target 3.0

                #include "UnityCG.cginc"

                uniform float _CirclesX;
                uniform float _CirclesY;
                uniform float _Fade;

                float4 vert(appdata_base v) : POSITION {
                    return mul (UNITY_MATRIX_MVP, v.vertex);
                }

                fixed4 frag(float4 sp:VPOS) : SV_Target {
                    float2 wcoord = sp.xy/_ScreenParams.xy;
                    fixed4 color;
                    if (length(fmod(float2(_CirclesX*wcoord.x,_CirclesY*wcoord.y),2.0)-1.0)<_Fade) {
                        color = fixed4(sp.xy/_ScreenParams.xy,0.0,1.0);
                    } else {
                        color = fixed4(0.3,0.3,0.3,1.0);
                    } 
                    return color;
                }
                ENDCG
            }
        }
    }

uniform

ShaderLab属性定义为从应用程序转移到材质的值。属性定义等不同类型的颜色,浮动,2d等等。使用关键字值定义为材质的属性Unity应该使用声明的变量,所以编译器识别变量作为外部值应该在每个执行转移到材质。

Texture Coordinates(纹理坐标)

这节课介绍一套着色器使用纹理坐标画网格的面具有不同的影响。

在网状结构位置的变量texcoord0,每个顶点。顶点和片段着色器可以修改这个变量。你应该选择你修改texcoord0的材质,根据所需的变量操作,现场的顶点数量和屏幕分辨率。你应该选择修改寻找最小的执行数texcoord0值。


    Shader "Custom/TextureCoordinates/Base" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 3.0

                #include "UnityCG.cginc"

                struct vertexInput {
                    float4 vertex : POSITION;
                    float4 texcoord0 : TEXCOORD0;
                };

                struct fragmentInput{
                    float4 position : SV_POSITION;
                    float4 texcoord0 : TEXCOORD0;
                };

                fragmentInput vert(vertexInput i){
                    fragmentInput o;
                    o.position = mul (UNITY_MATRIX_MVP, i.vertex);
                    o.texcoord0 = i.texcoord0;
                    return o;
                }
                fixed4 frag(fragmentInput i) : SV_Target {
                    return fixed4(i.texcoord0.xy,0.0,1.0);
                }
                ENDCG
            }
        }
    }

texcoord0的值的范围从0到1,它们映射到一个特定的纹理。纹理图像存储在内存的GPU代表一个正方形或矩形图像,片段着色器的材质也可以用作程序纹理,使用数学函数来定义每个像素在屏幕上的颜色。在上面的代码中您texcoord0值被用来设置的颜色红色和绿色通道,每个颜色的渐变效果。

Examples Chess


    Shader "Custom/TextureCoordinates/Chess" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag

                #include "UnityCG.cginc"

                struct vertexInput {
                    float4 vertex : POSITION;
                    float4 texcoord0 : TEXCOORD0;
                };

                struct fragmentInput{
                    float4 position : SV_POSITION;
                    float4 texcoord0 : TEXCOORD0;
                };

                fragmentInput vert(vertexInput i){
                    fragmentInput o;
                    o.position = mul (UNITY_MATRIX_MVP, i.vertex);
                    o.texcoord0 = i.texcoord0;
                    return o;
                }

                fixed4 frag(fragmentInput i) : SV_Target {
                    fixed4 color;
                    if ( fmod(i.texcoord0.x*8.0,2.0) < 1.0 ){
                        if ( fmod(i.texcoord0.y*8.0,2.0) < 1.0 )
                        {
                            color = fixed4(1.0,1.0,1.0,1.0);
                        } else {
                            color = fixed4(0.0,0.0,0.0,1.0);
                        }
                    } else {
                        if ( fmod(i.texcoord0.y*8.0,2.0) > 1.0 )
                        {
                            color = fixed4(1.0,1.0,1.0,1.0);
                        } else {
                            color = fixed4(0.0,0.0,0.0,1.0);}
                        }
                    return color;
                }
                ENDCG
            }
        }
    }

    Shader "Custom/TextureCoordinates/ChessOpt" {
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert_img
                #pragma fragment frag

                #include "UnityCG.cginc"

                fixed4 frag(v2f_img i) : SV_Target {
                    bool p = fmod(i.uv.x*8.0,2.0) < 1.0;
                    bool q = fmod(i.uv.y*8.0,2.0) > 1.0;

                    return fixed4(fixed3((p && q) || !(p || q)),1.0);
                }
                ENDCG
            }
        }
    }

Mandelbrot Fractal 曼德布洛特碎片形


    Shader "Custom/TextureCoordinates/Mandelbrot" {

        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert_img
                #pragma fragment frag
                #pragma target 3.0

                #include "UnityCG.cginc"

                float4 frag(v2f_img i) : SV_Target {
                    float2 mcoord;
                    float2 coord = float2(0.0,0.0);
                    mcoord.x = ((1.0-i.uv.x)*3.5)-2.5;
                    mcoord.y = (i.uv.y*2.0)-1.0;
                    float iteration = 0.0;
                    const float _MaxIter = 29.0;
                    const float PI = 3.14159;
                    float xtemp;
                    for ( iteration = 0.0; iteration < _MaxIter; iteration += 1.0) {
                        if ( coord.x*coord.x + coord.y*coord.y > 2.0*(cos(fmod(_Time.y,2.0*PI))+1.0) )
                        break;
                        xtemp = coord.x*coord.x - coord.y*coord.y + mcoord.x;
                        coord.y = 2.0*coord.x*coord.y + mcoord.y;
                        coord.x = xtemp;
                    }
                    float val = fmod((iteration/_MaxIter)+_Time.x,1.0);
                    float4 color;

                    color.r = clamp((3.0*abs(fmod(2.0*val,1.0)-0.5)),0.0,1.0);
                    color.g = clamp((3.0*abs(fmod(2.0*val+(1.0/3.0),1.0)-0.5)),0.0,1.0);
                    color.b = clamp((3.0*abs(fmod(2.0*val-(1.0/3.0),1.0)-0.5)),0.0,1.0);
                    color.a = 1.0;

                    return color;
                }
                ENDCG
            }
        }
    }

Texture


    Shader "Custom/TextureCoordinates/ActualTexture" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
            Pass {
                CGPROGRAM
                #pragma vertex vert_img
                #pragma fragment frag

                #include "UnityCG.cginc"

                uniform sampler2D _MainTex;

                fixed4 frag(v2f_img i) : SV_Target {
                    return tex2D(_MainTex, i.uv);
                }
                ENDCG
            }
        }
    }