zoukankan      html  css  js  c++  java
  • 【OpenGL】Shader实例分析(五)- 边缘检测

    转发请保持地址:http://blog.csdn.net/stalendp/article/details/23139953

    这里将介绍基于法线的边缘检测方法,这里的shader是参考官方的:http://wiki.unity3d.com/index.php/Outlined_Diffuse_3;运行效果如下:

    代码如下:

     

    1. Shader "Outlined/Diffuse" { // see http://wiki.unity3d.com/index.php/Outlined_Diffuse_3  
    2.     Properties {  
    3.         _Color ("Main Color", Color) = (.5,.5,.5,1)  
    4.         _OutlineColor ("Outline Color", Color) = (0,0,0,1)  
    5.         _Outline ("Outline width", Range (.002, 0.03)) = .005  
    6.         _MainTex ("Base (RGB)", 2D) = "white" { }  
    7.     }  
    8.    
    9.     CGINCLUDE  
    10.     #include "UnityCG.cginc"  
    11.        
    12.     struct appdata {  
    13.         float4 vertex : POSITION;  
    14.         float3 normal : NORMAL;  
    15.     };  
    16.        
    17.     struct v2f {  
    18.         float4 pos : POSITION;  
    19.         float4 color : COLOR;  
    20.     };  
    21.        
    22.     uniform float _Outline;  
    23.     uniform float4 _OutlineColor;  
    24.        
    25.     v2f vert(appdata v) {  
    26.         // just make a copy of incoming vertex data but scaled according to normal direction  
    27.         v2f o;  
    28.         o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
    29.        
    30.         float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);  
    31.         float2 offset = TransformViewToProjection(norm.xy);  
    32.           
    33.         o.pos.xy += offset * o.pos.z * _Outline;  
    34.         // following please refer to : http://unitygems.com/noobs-guide-shaders-6-toon-shader/  
    35.         // o.pos = mul( UNITY_MATRIX_MVP, v.vertex + (float4(v.normal,0) * _Outline));   
    36.         o.color = _OutlineColor;  
    37.         return o;  
    38.     }  
    39.     ENDCG  
    40.    
    41.     SubShader {  
    42.         //Tags {"Queue" = "Geometry+100" }  
    43.         CGPROGRAM  
    44.         #pragma surface surf Lambert  
    45.            
    46.         sampler2D _MainTex;  
    47.         fixed4 _Color;  
    48.            
    49.         struct Input {  
    50.             float2 uv_MainTex;  
    51.         };  
    52.            
    53.         void surf (Input IN, inout SurfaceOutput o) {  
    54.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;  
    55.             o.Albedo = c.rgb;  
    56.             o.Alpha = c.a;  
    57.         }  
    58.         ENDCG  
    59.    
    60.         // note that a vertex shader is specified here but its using the one above  
    61.         Pass {  
    62.             Name "OUTLINE"  
    63.             Tags { "LightMode" = "Always" }  
    64.             Cull Front  
    65.             ZWrite On  
    66.             ColorMask RGB  
    67.             Blend SrcAlpha OneMinusSrcAlpha  
    68.             //Offset 50,50  
    69.    
    70.             CGPROGRAM  
    71.             #pragma vertex vert  
    72.             #pragma fragment frag  
    73.             half4 frag(v2f i) :COLOR { return i.color; }  
    74.             ENDCG  
    75.         }  
    76.     }  
    77.    
    78.     SubShader {  
    79.         CGPROGRAM  
    80.         #pragma surface surf Lambert  
    81.            
    82.         sampler2D _MainTex;  
    83.         fixed4 _Color;  
    84.            
    85.         struct Input {  
    86.             float2 uv_MainTex;  
    87.         };  
    88.            
    89.         void surf (Input IN, inout SurfaceOutput o) {  
    90.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;  
    91.             o.Albedo = c.rgb;  
    92.             o.Alpha = c.a;  
    93.         }  
    94.         ENDCG  
    95.    
    96.         Pass {  
    97.             Name "OUTLINE"  
    98.             Tags { "LightMode" = "Always" }  
    99.             Cull Front  
    100.             ZWrite On  
    101.             ColorMask RGB  
    102.             Blend SrcAlpha OneMinusSrcAlpha  
    103.    
    104.             CGPROGRAM  
    105.             #pragma vertex vert  
    106.             #pragma exclude_renderers gles xbox360 ps3  
    107.             ENDCG  
    108.             SetTexture [_MainTex] { combine primary }  
    109.         }  
    110.     }  
    111.    
    112.     Fallback "Diffuse"  
    113. }  


    原理介绍:

     

    分两个pass进行渲染,第一个渲染边框,第二个渲染实物。

    1)边框的渲染

    在vertex Shader阶段,吧顶点按照法线的方向进行扩展, 这样物体就比原来要膨胀(关于膨胀效果,请参考Surface Shader Example中的Normal Extrusion with Vertex Modifier)。

     

    1. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
    2. float3 norm   = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);  
    3. float2 offset = TransformViewToProjection(norm.xy);  //计算法线的方向  
    4. o.pos.xy += offset * o.pos.z * _Outline; //按照法线的方向进行偏移  

    效果如下:

     

    边框盖住里原始物体,这里只要设置只渲染背面,就可以达到效果,在渲染边框的Pass中设置“Cull Front”就可以了。

    2)渲染实物

    当然这个只是适用于3d物体,图像的边缘检测,还有canny算法等,以后再补充,这里给个Canny的地址:Canny Edge Detection Tutorial

    另外一篇:http://en.wikipedia.org/wiki/Edge_detection;  还有: http://en.wikipedia.org/wiki/Canny_edge_detector

    关于图像的边缘检测,可以运用在Deferred shading中的anti-aliasing

    ======

    相关的文章:http://unitygems.com/noobs-guide-shaders-6-toon-shader/

    Silhouette-Outlined Diffuse

    OutlinedDiffuse

    Lighted Bumped Outline

    基于法线的边缘检测

    Code Snippet: Edge Detector/Antialiasing Shader

  • 相关阅读:
    CSS3的常用属性(一)
    Shiro授权认证原理和流程
    mysql存储引擎
    mysql索引的注意事项
    CSS的常用属性(三)
    CSS的常用属性(二)
    CSS的常用属性(一)
    常用文档站点
    Spring和SpringMVC父子容器关系初窥
    内部类学习资料分享
  • 原文地址:https://www.cnblogs.com/cooka/p/3673827.html
Copyright © 2011-2022 走看看