1. 程式人生 > 程式設計 >Unity Shader實現素描效果

Unity Shader實現素描效果

本文例項為大家分享了Unity Shader實現素描效果的具體程式碼,供大家參考,具體內容如下

這是樂樂大佬書裡的非真實渲染,其中的演算法還是挺有意思的,感興趣的小夥伴可以試一試。

素描效果基本原理:先將物體進行描邊畫出輪廓,計算物體的漫反射部分,漫反射越暗表明顏色越暗,然後根據漫反射的值來設定取樣貼圖的權重。

取樣貼圖:

Unity Shader實現素描效果

Unity Shader實現素描效果

Unity Shader實現素描效果

shader部分:

Shader "Unlit/Sketch"
{
 Properties
 {
 _Color("Color",Color) = (1,1,1)
 //貼圖平鋪係數
   _TileFactor("TileFactor",Range(0,10)) = 1
 _Hatch0("Hatch0",2D)="white"{}
   _Hatch1("Hatch1",2D) = "white"{}
   _Hatch2("Hatch2",2D) = "white"{}
   _Hatch3("Hatch3",2D) = "white"{}
   _Hatch4("Hatch4",2D) = "white"{}
   _Hatch5("Hatch5",2D) = "white"{}
 //描邊係數
 _OutlineFactor("OutlineFactor",Range(0.0,0.1))=0.01
 }
 SubShader
 {
 Tags{ "Queue" = "Transparent" }
 //描邊使用兩個Pass,第一個pass沿法線擠出一點,只輸出描邊的顏色
 Pass
 {
  //剔除正面,只渲染背面
  Cull Front
  //關閉深度寫入
  ZWrite Off
  //控制深度偏移,描邊pass遠離相機一些,防止與正常pass穿插
  Offset 1,1

  CGPROGRAM
      #include "UnityCG.cginc"
      #pragma vertex vert
      #pragma fragment frag
   float _OutlineFactor;

   struct v2f
   {
    float4 pos : SV_POSITION;
   };

   v2f vert(appdata_full v)
   {
    v2f o;
    o.pos = UnityObjectToClipPos(v.vertex);
    //將法線方向轉換到視空間
    float3 vnormal = mul((float3x3)UNITY_MATRIX_IT_MV,v.normal);
    //將視空間法線xy座標轉化到投影空間
    float2 offset = TransformViewToProjection(vnormal.xy);
    //在最終投影階段輸出進行偏移操作
    o.pos.xy += offset * _OutlineFactor;
    return o;
   }

   fixed4 frag(v2f i) : SV_Target
   {
    return float4(0,1);
   }
  ENDCG
 }
 

 Pass
 {
  CGPROGRAM
      #include "UnityCG.cginc"
      #include "Lighting.cginc"
  //使用陰影需新增
      #include "AutoLight.cginc"
  #pragma vertex vert
  #pragma fragment frag
  //使主要平行光產生陰影
      #pragma multi_compile_fwdbase

  

  float4 _Color;
     float _TileFactor;
  sampler2D _Hatch0;
  sampler2D _Hatch1;
  sampler2D _Hatch2;
  sampler2D _Hatch3;
  sampler2D _Hatch4;
  sampler2D _Hatch5;

  struct v2f
  {
  float2 uv : TEXCOORD0;
  float4 vertex : SV_POSITION;
  //6張依次加深的貼圖
  float3 hatchWeights0:TEXCOORD1;
  float3 hatchWeights1:TEXCOORD2;
  //宣告陰影
  SHADOW_COORDS(4)
  float3 worldPos:TEXCOORD3;
  };
 
  v2f vert (appdata_full v)
  {
  v2f o;
  o.vertex = UnityObjectToClipPos(v.vertex);
  //平鋪係數越大,顯示的貼圖越密集
  o.uv = v.texcoord* _TileFactor;
  float3 worldLightDir = normalize(WorldSpaceLightDir(v.vertex));
  float3 worldNormal = UnityObjectToWorldNormal(v.normal);
  //漫反射
  float diffuse = max(0,dot(worldLightDir,worldNormal));
  o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz ;
  //六張圖片的權重
  o.hatchWeights0 = float3(0,0);
  o.hatchWeights1 = float3(0,0);
  //根據漫反射值計算權重,漫反射越暗,線條越密集
  float hatchFactor = diffuse * 7.0;
  if (hatchFactor > 6.0) {
  }
  else if (hatchFactor > 5.0) {
   o.hatchWeights0.x = hatchFactor - 5.0;
  }
  else if (hatchFactor > 4.0) {
   o.hatchWeights0.x = hatchFactor - 4.0;
   o.hatchWeights0.y = 1.0 - o.hatchWeights0.x;
  }
  else if (hatchFactor > 3.0) {
   o.hatchWeights0.y = hatchFactor - 3.0;
   o.hatchWeights0.z = 1.0 - o.hatchWeights0.y;
  }
  else if (hatchFactor > 2.0) {
   o.hatchWeights0.z = hatchFactor - 2.0;
   o.hatchWeights1.x = 1.0 - o.hatchWeights0.z;
  }
  else if (hatchFactor > 1.0) {
   o.hatchWeights1.x = hatchFactor - 1.0;
   o.hatchWeights1.y = 1.0 - o.hatchWeights1.x;
  }
  else {
   o.hatchWeights1.y = hatchFactor;
   o.hatchWeights1.z = 1.0 - o.hatchWeights1.y;
  }
  //把計算的陰影傳到fragment中
  TRANSFER_SHADOW(o);
  return o;
  }
  
  fixed4 frag (v2f i) : SV_Target
  { 
  float4 hatchTex0 = tex2D(_Hatch0,i.uv) * i.hatchWeights0.x;
  float4 hatchTex1 = tex2D(_Hatch1,i.uv) * i.hatchWeights0.y;
  float4 hatchTex2 = tex2D(_Hatch2,i.uv) * i.hatchWeights0.z;
  float4 hatchTex3 = tex2D(_Hatch3,i.uv) * i.hatchWeights1.x;
  float4 hatchTex4 = tex2D(_Hatch4,i.uv) * i.hatchWeights1.y;
  float4 hatchTex5 = tex2D(_Hatch5,i.uv) * i.hatchWeights1.z;
  //漫反射暗色部分權重越大,白色越少
  float4 whiteColor = float4(1,1)*(1 - i.hatchWeights0.x - i.hatchWeights0.y - i.hatchWeights0.z - i.hatchWeights1.x - i.hatchWeights1.y - i.hatchWeights1.z);
  float4 hatchColor = hatchTex0 + hatchTex1 + hatchTex2 + hatchTex3 + hatchTex4 + hatchTex5+ whiteColor;
  //使物體接受陰影
  UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
  return float4(hatchColor.rgb*_Color.rgb*atten,1.0);
  }
  ENDCG
 } 
 }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。