2016-09-22 1 views
7

셰이더로 원을 그렸지만 앤티 앨리어싱을 사용할 수 없습니다.셰이더 및 앤티 앨리어싱을 사용하여 원을 그리는 방법

답변을 찾으려고 여기 http://answers.unity3d.com/questions/521984/how-do-you-draw-2d-circles-and-primitives.html,하지만 난 원을 그리기 위해 폐기를 사용해야합니다.

picture

Shader "Unlit/CircleSeletor" 
{ 
Properties 
    { 
     _BoundColor("Bound Color", Color) = (1,1,1,1) 
     _BgColor("Background Color", Color) = (1,1,1,1) 
     _MainTex("Albedo (RGB)", 2D) = "white" {} 
     _BoundWidth("BoundWidth", float) = 10 
     _ComponentWidth("ComponentWidth", float) = 100 
    } 
SubShader{ 
Pass 
      { 
      Blend SrcAlpha OneMinusSrcAlpha 
      CGPROGRAM 
      #pragma vertex vert 
      #pragma fragment frag Lambert alpha 
      // make fog work 
      #pragma multi_compile_fog 
      #include "UnityCG.cginc" 
      sampler2D _MainTex; 
      float _BoundWidth; 
      fixed4 _BoundColor; 
      fixed4 _BgColor; 
      float _ComponentWidth; 
      struct appdata 
      { 
       float4 vertex : POSITION; 
       float2 uv : TEXCOORD0; 
      }; 
      struct v2f 
      { 
       float2 uv : TEXCOORD0; 
       UNITY_FOG_COORDS(1) 
       float4 vertex : SV_POSITION; 
      }; 
      float4 _MainTex_ST; 
      v2f vert(appdata v) 
      { 
       v2f o; 
       o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 
       o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
       UNITY_TRANSFER_FOG(o,o.vertex); 
       return o; 
      } 
      float antialias(float w, float d, float r) { 
        return 1-(d-r-w/2)/(2*w); 
      } 
      fixed4 frag(v2f i) : SV_Target 
      { 
       fixed4 c = tex2D(_MainTex,i.uv); 
       float x = i.uv.x; 
       float y = i.uv.y; 
       float dis = sqrt(pow((0.5 - x), 2) + pow((0.5 - y), 2)); 
       if (dis > 0.5) { 
        discard; 
       } else { 
        float innerRadius = (_ComponentWidth * 0.5 - _BoundWidth)/_ComponentWidth; 
        if (dis > innerRadius) { 
         c = _BoundColor; 
         //c.a = c.a*antialias(_BoundWidth, dis, innerRadius); 
        } 
        else { 
         c = _BgColor; 
        } 
       } 
       return c; 
      } 
      ENDCG 
      } 
} 
} 
+0

지방 현상금! :) – Fattie

답변

3

이 시도 :

Shader "Unlit/CircleSeletor" 
{ 
    Properties 
    { 
     _BoundColor("Bound Color", Color) = (1,1,1,1) 
     _BgColor("Background Color", Color) = (1,1,1,1) 
     _MainTex("Albedo (RGB)", 2D) = "white" {} 
     _BoundWidth("BoundWidth", float) = 10 
     _ComponentWidth("ComponentWidth", float) = 100 
    } 

    SubShader 
    { 
     Pass 
     { 
      Blend SrcAlpha OneMinusSrcAlpha 
      CGPROGRAM 

      #pragma vertex vert 
      #pragma fragment frag Lambert alpha 
      // make fog work 
      #pragma multi_compile_fog 
      #include "UnityCG.cginc" 

      sampler2D _MainTex; 
      float _BoundWidth; 
      fixed4 _BoundColor; 
      fixed4 _BgColor; 
      float _ComponentWidth; 

      struct appdata 
      { 
       float4 vertex : POSITION; 
       float2 uv : TEXCOORD0; 
      }; 
      struct v2f 
      { 
       float2 uv : TEXCOORD0; 
       UNITY_FOG_COORDS(1) 
        float4 vertex : SV_POSITION; 
      }; 

      float4 _MainTex_ST; 
      v2f vert(appdata v) 
      { 
       v2f o; 
       o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 
       o.uv = TRANSFORM_TEX(v.uv, _MainTex); 
       UNITY_TRANSFER_FOG(o,o.vertex); 
       return o; 
      } 

      float antialias(float w, float d, float r) { 
       return 1 - (d - r - w/2)/(2 * w); 
      } 

      fixed4 frag(v2f i) : SV_Target 
      { 
       fixed4 c = tex2D(_MainTex,i.uv); 
      float x = i.uv.x; 
      float y = i.uv.y; 
      float dis = sqrt(pow((0.5 - x), 2) + pow((0.5 - y), 2)); 
      if (dis > 0.5) { 
       c.a = 0; 
       discard; 
      } 
      else { 
       float innerRadius = (_ComponentWidth * 0.5 - _BoundWidth)/_ComponentWidth; 
       if (dis > innerRadius) { 
        c = _BoundColor; 
        //c.a = c.a*antialias(_BoundWidth, dis, innerRadius); 
       } 
       else { 
        c = _BgColor; 
       } 
      } 
      return c; 
      } 

       ENDCG 
     } 
     GrabPass{ 
      "_MainTex2" 
     } 
     Pass 
     { 
       Blend One zero 
      CGPROGRAM 

      #pragma vertex vert 
      #pragma fragment frag 
      #include "UnityCG.cginc" 

      struct appdata 
      { 
       float4 vertex : POSITION; 
       fixed4 color : COLOR; 
      }; 
      struct v2f 
      { 
       float4 pos : SV_POSITION; 
       fixed4 color : COLOR; 
       float4 scrPos : TEXCOORD0; 
      }; 

      float4 _MainTex_ST; 
      v2f vert(appdata v) 
      { 
       v2f o; 
       o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
       o.scrPos = ComputeScreenPos(o.pos); 
       o.color = v.color; 
       return o; 
      } 

      sampler2D _MainTex2; 
      float4 _MainTex2_TexelSize; 

      fixed4 frag(v2f i) : SV_Target 
      { 
       float2 uv = (i.scrPos.xy/i.scrPos.w); 
       fixed4 c = tex2D(_MainTex2, uv); 
       fixed4 up = tex2D(_MainTex2, uv + fixed2(0, _MainTex2_TexelSize.y)); 
       fixed4 down = tex2D(_MainTex2, uv - fixed2(0, _MainTex2_TexelSize.y)); 
       fixed4 left = tex2D(_MainTex2, uv - fixed2(_MainTex2_TexelSize.x, 0)); 
       fixed4 right = tex2D(_MainTex2, uv + fixed2(_MainTex2_TexelSize.x, 0)); 

       c.rgb = (c.rgb + up.rgb + down.rgb + left.rgb + right.rgb)/5; 
       c.a = (c.a + up.a + down.a + left.a + right.a)/5; 

       return c; 
      } 
       ENDCG 

     } 
    } 
} 

첫 번째 패스 후 나는 결과 및 방지 적용 GrabPass 여기

내 현재 쉐이더 결과의 사진과 쉐이더 코드 테두리 픽셀을 평균하여 두 번째 패스의 별칭입니다.

+0

남자, 무슨 일류 셰이더 ....... 고마워! – Fattie

+0

아 - 불행히도이 쉐이더는 최신 iOS 장치에서 작동하지 않는다고 생각합니다. "만화경"효과를 얻었습니까? 불행! – Fattie

+0

무엇을 의미합니까? 스크린 샷을 제공 할 수 있습니까? – Krajca

4

서클에 앤티 앨리어스를 적용하는 것은 정말 쉽습니다.

. 먼저이 작업을 수행하려면 3 변수가 필요합니다. 서클의 radius, distance을 가져옵니다. 또한 앤티 앨리어스가 얼마나 멀리 떨어져야하는지 결정하는 데 사용할 수있는 float 값을 만듭니다 (borderSize). radius, distanceborderSize은 세 가지 변수입니다.

2 .Find 1 3 개에서 그 변수를 사용 tsmoothstep와 기능.

float t = smoothstep(radius + borderSize, radius - borderSize, distance); 

3 .Mix을 반환하기 전에 색상.

_BoundColor이 원을 채우는 색이고 _BgColor이 배경색이라고 가정 해 봅시다.

mix 기능을 사용하는 GLSL을 사용하는 경우. Unity를 사용하는 경우 lerp 기능을 사용하십시오. 두 기능은 상호 교환되며 매개 변수는 동일합니다.

col = lerp(_BoundColor, _BgColor, t); 

t# 2에서입니다. 이제 조각 기능에서 col을 반환 할 수 있습니다. 앨리어싱 WITHOUT

if (dis > radius) { 
    float t = smoothstep(radius + borderSize, radius - borderSize, distance); 
    col = lerp(_BoundColor, _BgColor, t); 
} 
else { 
    float t = smoothstep(radius + borderSize, radius - borderSize, distance); 
    col = lerp(_BoundColor, _BgColor, t); 
} 
return col; 

OUTPUT : 앨리어싱 WITH

enter image description here

OUTPUT (4


합친 3 단계는 .5 임계 값)
:

enter image description here


마지막으로, PC 및하지만 안드로이드에서 테스트 전체 코드가 (너무 iOS에서 작동합니다)

디스크를 그립니다 셰이더에 대한
Shader "Unlit/Circle Anti-Aliasing" 
{ 
    Properties 
    { 
     _BoundColor("Bound Color", Color) = (0,0.5843137254901961,1,1) 
     _BgColor("Background Color", Color) = (0.1176470588235294,0,0.5882352941176471,1) 
     _circleSizePercent("Circle Size Percent", Range(0, 100)) = 50 
     _border("Anti Alias Border Threshold", Range(0.00001, 5)) = 0.01 
    } 
     SubShader 
    { 
     Tags { "RenderType" = "Opaque" } 
     LOD 100 

     Pass 
     { 
      CGPROGRAM 
      #pragma vertex vert 
      #pragma fragment frag 
      // make fog work 
      #pragma multi_compile_fog 

      #include "UnityCG.cginc" 

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

      float _border; 

      fixed4 _BoundColor; 
      fixed4 _BgColor; 
      float _circleSizePercent; 

      struct v2f 
      { 
       float2 uv : TEXCOORD0; 
      }; 

      v2f vert(
       float4 vertex : POSITION, // vertex position input 
       float2 uv : TEXCOORD0, // texture coordinate input 
       out float4 outpos : SV_POSITION // clip space position output 
      ) 
      { 
       v2f o; 
       o.uv = uv; 
       outpos = UnityObjectToClipPos(vertex); 
       return o; 
      } 

      float2 antialias(float radius, float borderSize, float dist) 
      { 
       float t = smoothstep(radius + borderSize, radius - borderSize, dist); 
       return t; 
      } 

      fixed4 frag(v2f i, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target 
      { 
       float4 col; 
       float2 center = _ScreenParams.xy/2; 

       float maxradius = length(center); 

       float radius = maxradius*(_circleSizePercent/100); 

       float dis = distance(screenPos.xy, center); 

       if (dis > radius) { 
        float aliasVal = antialias(radius, _border, dis); 
        col = lerp(_BoundColor, _BgColor, aliasVal); //NOT needed but incluse just incase 
       } 
       else { 
        float aliasVal = antialias(radius, _border, dis); 
        col = lerp(_BoundColor, _BgColor, aliasVal); 
       } 
       return col; 

      } 
      ENDCG 
     } 
    } 
} 
+1

fantastic @Programmer, thanks – Fattie

관련 문제