2016-03-27 9 views
1

Я пытаюсь закодировать шейдер, похожий на this one из руководства Unity, который «разрезает» объект, отбрасывая пиксели почти горизонтальными кольцами через функцию Clip().Unity worldPos относительное направление

Shader "Example/Slices" { 
    Properties { 
     _MainTex ("Texture", 2D) = "white" {} 
     _BumpMap ("Bumpmap", 2D) = "bump" {} 
    } 
    SubShader { 
     Tags { "RenderType" = "Opaque" } 
     Cull Off 
     CGPROGRAM 
     #pragma surface surf Lambert 
     struct Input { 
      float2 uv_MainTex; 
      float2 uv_BumpMap; 
      float3 worldPos; 
     }; 
     sampler2D _MainTex; 
     sampler2D _BumpMap; 
     void surf (Input IN, inout SurfaceOutput o) { 
      clip (frac((IN.worldPos.y+IN.worldPos.z*0.1) * 5) - 0.5); 
      o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; 
      o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); 
     } 
     ENDCG 
    } 
    Fallback "Diffuse" 
    } 

Вместо горизонтальных линий я хочу иметь возможность срезать под любым углом. Я обнаружил с помощью экспериментов (так как я новичок кодирования шейдеров), что множитель на worldPos Z действительно изменить угол среза, так что я установить переменную собственности на него:

clip (frac((IN.worldPos.y+IN.worldPos.z*_MYANGLEVARIABLE) * 5) - 0.5); 

Это, однако, имеет две проблемы , 1) Значения до 1.0 поворачивают линии до 45 градусов, но за этим линии начинают «squiggly» и свернутся во всевозможные шаблоны, а не на аккуратные линии и 2) это работает только в том случае, если лицо ориентировано на положительное или отрицательной оси X. При обращении к Z линии не двигаются, и когда они обращены к Y, они становятся больше, но не вращаются.

Изменение IN.worldPos.y к IN.worldPos.x делает то, что вы могли бы ожидать - аналогичная ситуация, но работает, как ожидалось в Z, а не X.

Любые идеи, как 1) Достижение произвольных углов? 2) Пусть они работают независимо от направления?

Я использую worlPos, потому что я всегда хочу, чтобы линии были относительно объекта, а не экрана, но, возможно, есть другой способ? Мой фактический шейдер - это фрагмент, а не поверхностный шейдер. & Я передаю worldPos от вершины до фрагмента.

Большое спасибо

+0

dat looks hard ... – Fattie

ответ

0

Чтобы получить произвольные углы можно определить плоскость, используя нормальный вектор и клип с помощью скалярного произведения.

Shader "Example/Slices" { 
    Properties { 
    _MainTex ("Texture", 2D) = "white" {} 
    _BumpMap ("Bumpmap", 2D) = "bump" {} 
    _PlaneNormal ("Plane Normal", Vector) = (0, 1, 0) 
    } 
    SubShader { 
    Tags { "RenderType" = "Opaque" } 
    Cull Off 
    CGPROGRAM 
    #pragma surface surf Lambert 
    struct Input { 
     float2 uv_MainTex; 
     float2 uv_BumpMap; 
     float3 worldPos; 
    }; 
    sampler2D _MainTex; 
    sampler2D _BumpMap; 
    float3 _PlaneNormal; 
    void surf (Input IN, inout SurfaceOutput o) { 
     float d = dot(_PlaneNormal, IN.worldPos); 
     clip (frac(d) - 0.5); 
     o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; 
     o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap)); 
    } 
    ENDCG 
    } 
    Fallback "Diffuse" 
} 

Чем дольше нормальный вектор здесь, тем чаще встречаются ломтики.

Если вы хотите, чтобы срезы были относительно объекта, вам нужно использовать набор координат, отличный от worldPos. Возможно, этот ответ помог бы: http://answers.unity3d.com/questions/561900/get-local-position-in-surface-shader.html