zoukankan      html  css  js  c++  java
  • 简单的勾边算法

       下述代码列出了几种勾边的实现思路,实际游戏中在屏幕空间扩展法线的方案,基本上就够用了:

    Shader "Shader/Outline" 
    {
        Properties
        {
            _MainTex("MainTex", 2D) = "white" {}
            _Color("Color", Color) = (1, 1, 1, 1)
            _OutLine("OutLine", Float) = 0.1
            _OutLineColor("OutLineColor", Color) = (1, 1, 1, 1)
            _Factor("Factor", Range(0, 1)) = 0.5
        }
    
        SubShader 
        {
            Tags { "Queue" = "Opaque" }
            Pass
            {
                Cull Front
                ZWrite on
                CGPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float3 color : COLOR0;
                    float2 uv : TEXCOORD0;
                };
                
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float4 _Color;
                float _OutLine;
                float4 _OutLineColor;
                float _Factor;
    
                v2f vert(appdata_base v)
                {
                    /* // 沿法线方向扩展(问题:近粗远细 深度覆盖 发现分离)
                    v2f o;
                    v.vertex.xyz += v.normal * _OutLine;
                    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    return o;
                    */
    
                    /* // 在视空间挤出(问题:法线分离问题)
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    
                    float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
                    float2 offset = TransformViewToProjection(norm.xy);
                    o.pos.xy += offset * o.pos.z * _OutLine;
                    return o;
                    */
    
                    /*
                    // 使用顶点位置作为挤出方向(问题:等于从几何中心缩放,不一致)
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    
                    float3 dir = normalize(v.vertex.xyz);
                    dir = mul((float3x3)UNITY_MATRIX_IT_MV, dir);
    
                    float2 offset = TransformViewToProjection(dir.xy);
                    o.pos.xy += offset * o.pos.z * _OutLine;
                    return o;
                    */
    
                    // 在发现和顶点方向间插值
                    v2f o;
                    o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    
                    float3 dir = normalize(v.vertex.xyz);
                    float3 dir2 = v.normal;
                    dir = lerp(dir2, dir, _Factor);
    
                    dir = mul((float3x3)UNITY_MATRIX_IT_MV, dir);
    
                    float2 offset = TransformViewToProjection(dir.xy);
                    o.pos.xy += offset * o.pos.z * _OutLine;
                    return o;
                }
    
                half4 frag(v2f i) : COLOR
                {
                    return _OutLineColor;
                }
                
                ENDCG
            }
      Pass {...}
    }

      通过offset操作,来实现描边的效果:

    Shader "Shader/OutLine_Offset" 
    {
        Properties
        {
            _MainTex("MainTex", 2D) = "white" {}
            _Color("Color", Color) = (1, 1, 1, 1)
            _OutLine("OutLine", Float) = 0.1
        }
        SubShader 
        {
            Tags { "Queue" = "Opaque" }
            Pass
            {
                Cull Front
                Offset -1,-1
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                struct v2f
                {
                    float4 pos : SV_POSITION;
                };
                float4 _OutLine;
                v2f vert(appdata_base v)
                {
                    v2f o;
                    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                    return o;
                }
                half4 frag(v2f i) : COLOR
                {
                    return _OutLine;
                }
                ENDCG
            }
            Pass
            {
                Offset 2,-1
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float3 color : COLOR0;
                    float2 uv : TEXCOORD0;
                };
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float4 _Color;
                v2f vert(appdata_base v)
                {
                    v2f o;
                    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    return o;
                }
                half4 frag(v2f i) : COLOR
                {
                    float4 mainColor = tex2D(_MainTex, i.uv);
                    float4 finalColor = mainColor * _Color;
                    return finalColor;
                }
                ENDCG
            }
        } 
        FallBack "VertexLit"
    }

      这个方法不是太实用,只是一种实现思路。

      使用的方案是UnityPro提供的AssetsPackage中现成的ToonShader。

      http://wiki.unity3d.com/index.php/Silhouette-Outlined_Diffuse

  • 相关阅读:
    Generator 函数的异步应用
    Generator 函数的语法
    10 个最佳的 Node.js 的 MVC 框架
    Node.js 框架对比之 Express VS Koa
    JavaScript资源分享
    【转载】Web 研发模式演变
    学习资源整理
    超高影响力开源大放送,学习开发必备教科书
    LVS + KEEPALIVED + WINDOWS SERVER 2008 R2 ------高可用负载均衡(转)
    LVS DR模式 RealServer 为 Windows 2008 R2配置
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/6476321.html
Copyright © 2011-2022 走看看