Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Unity3D - 顶点片段着色器(Vertex and Fragment Shaders)

$
0
0

顶点片段着色器运行于具有可编程渲染管线的硬件上,它包括顶点程序(Vertex Programs)和片段程序(Fragment Programs)。

当使用顶点程序和片段程序进行渲染时,图形硬件的固定功能管线将会馆关闭,具体来说就是用户编写的顶点程序将会替换掉固定管线标准中的3D变换、光照、纹理坐标生成等功能,而片段程序会替换掉SetTexture命令中的纹理混合模式,因此编写顶点片段着色器需要对3D变换、光照计算等有非常透彻的了解。

用户需要自行编写代码来替代D3D或则OpenGL原先在固定管线中要做的工作。

与表面着色器一枪,顶点片段着色器也需要用Cg/HLSL来编写实现代码,代码用CGPROGRAM ENDCG语句包围起来,放在ShaderLab的Pass命令中:

Pass {
    // 通道设置
    CGPROGRAM

    // 本段Cg代码的编译指令
    #pragma vertex vert
    #pragma fragment frag

    // Cg代码
    ENDCG

    // 其他通道设置
}

下面是顶点片段着色器中编译命令的一些说明:

编译命令(Compilation Directive)

命令 说明
pragma vertex name 将函数name的代码编译成顶点程序
pragma fragment name 将函数name的代码编译成片段程序
pragma geometry name 将函数name的代码编译成DX10的几何着色器(Geometry Shader)
pragma hull name 将函数name的代码编译成DX11的hull着色器
pragma domain name 将函数name的代码编译成DX11的domain着色器
pragma fragmentoption option 添加选项到编译的OpenGL片段程序。对于顶点程序或编译目标不是OpenGL的程序无效
pragma target name 设置着色器的编译目标
pragma only_renderers space separated names 仅编译到指定的渲染平台
pragma exclude_renderers space separated names 不编译到指定的渲染平台
pragma glsl 为桌面系统的OpenGL进行编译时,将Gl、HLSL代码转换成GLSL代码
pragma glsl_no_auto_normalizationi 编译到移动平台GLSL(iOS/Android),关闭在顶点着色器中对法线向量和切线向量自动进行规范化

编译目标(Shader Targets)

编译目标可以设置为#pragma target 2.0#pragma target 3.0#pragma target 4.0#pragma target 5.0
他们分别对应不同版本的着色器模型(Shader Modal)

渲染平台(Rendering Platforms)

Unity支持多重图形API:

  • d3d9 即Direct3D 9
  • d3d11 即Direct3D 11
  • opengl 即OpenGL
  • gles 即OpenGL ES 2.0
  • gles3 即OpenGL ES 3.0
  • metal 即 iOSMetal
  • d3d11_9x 即Direct3D 11 9.x feature level
  • xbox360 即Xbox360
  • xbox one 即Xbox One
  • ps3 即PlayStation3
  • ps4 即PlayStation4
  • psp2 即PlayStation Vita。

沿着法线方向移动顶点。

Shader "Example/Normal Extrusion" {
  Properties {
    _MainTex ("Texture", 2D) = "white" {}
    _Amount ("Extrusion Amount", Range(-1,1)) = 0.5
  }
  SubShader {
    // 渲染类型为不透明
    Tags { "RenderType" = "Opaque" }

    CGPROGRAM
    // 定义表面和顶点函数
    #pragma surface surf Lambert vertex:vert

    struct Input {
        // MainTex的UV坐标
        float2 uv_MainTex;
    };
    float _Amount;

    // 输入结构作为参数
    void vert (inout appdata_full v) {
        // 修改顶点位置
        v.vertex.xyz += v.normal * _Amount;
    }
    sampler2D _MainTex;
    void surf (Input IN, inout SurfaceOutput o) {
        // 输出漫反射颜色
        o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
    }
    ENDCG
  } 
  Fallback "Diffuse"
}

根据法线方向设置模型表面颜色

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Example/Display Normals" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct v2f {
                float4 pos : SV_POSITION;
                float3 color : COLOR0;
            };
            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos (v.vertex);
                o.color = v.normal * 0.5 + 0.5;
                return o;
            }

            // 片段程序代码,直接把输入的颜色返回,并把透明度设置为1
            half4 frag (v2f i) : COLOR
            {
                return half4 (i.color, 1);
            }
            ENDCG
        }
    }
    Fallback "VertexLit"
} 

根据切向方向设置模型表面颜色

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Example/Tangents" {
    SubShader {
        Pass {
            Fog { Mode Off }
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            // vertex input: position, tangent
            // 输入位置和切线数据
            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
            };

            // 定义顶点位置结构体
            struct v2f {
                float4 pos : SV_POSITION;
                fixed4 color : COLOR;
            };

            // 顶点函数程序
            v2f vert (appdata v) {
                v2f o;
                // 计算顶点位置
                o.pos = UnityObjectToClipPos( v.vertex );
                // 计算顶点颜色
                o.color = v.tangent * 0.5 + 0.5;
                return o;
            }

            // 片段程序,直接返回顶点颜色
            fixed4 frag (v2f i) : COLOR0 { return i.color; }
            ENDCG
        }
    }
}
作者:biezhihua 发表于2017/9/6 0:23:44 原文链接
阅读:23 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>