Unity Shader 学习之旅-初探

Unity Shader 学习之旅-初探

美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉

最简单的顶点片元着色器

顶点片元着色器基本结构

Unity Shader基本结构:Shader ,Properties,SubShder,Fallback等。

结构

  1.  
  2. Shader "ShaderName"{ 
  3. Properties{ 
  4. //属性,暴露在inspector面板上 

  5.  
  6. SubShader{ 
  7. //针对显卡A的SubShader 
  8. Pass{ 
  9. //设置渲染状态和标签 
  10.  
  11. CGPROGRAM 
  12. //该代码的编译指令,如: 
  13. #pragma vertex vert 
  14. #pragma fragment frag 
  15.  
  16. //CG代码 
  17.  
  18.  
  19. ENDCG 
  20. //其他设置 


  21.  
  22. SubShader{ 
  23. //针对显卡B的SubShader 

  24.  
  25. //上述SubShader都失败后调用回调的Unity Shader 
  26. Fallback "VertexLit" 

一个简单的示例

  1. Shader "UnityShaderBoook/SimplerShader"{ 
  2.  
  3. //Properties并非必须,此shader中不声明任何材质属性 
  4. SubShader{ 
  5.  
  6. Pass{  
  7.  
  8. CGPROGRAM 
  9. //编译命令,指定顶点/片元着色器处理函数 
  10. #pragma vertex vert 
  11. #pragma fragment frag 
  12.  
  13. //顶点着色器代码,逐个顶点执行 
  14. //使用POSITION语义指定函数的输入参数v为顶点的位置信息 
  15. //SV_POSITION语义指明函数的返回值为顶点着色器输出的是裁剪空间中的位置 
  16. //UnityObjectToClipPos则是Unity内置的模型-观察-投影矩阵,帮我们完成操作(mul(UNITY_MATRIX_MVP,*)' 现已更新为'UnityObjectToClipPos(*)') 
  17. float4 vert(float4 v:POSITION):SV_POSITION{ 
  18. return UnityObjectToClipPos(v); 

  19.  
  20. //片元着色器,逐个面片执行 
  21. //此片元着色器没有任何输入参数 
  22. //SV_TARGET语义指定函数输出颜色存储一个渲染目标上 
  23. //这里仅仅简单的返回表示白色的fixed4的变量 
  24. fixed4 frag():SV_TARGET{ 
  25. return fixed4(1.0,1.0,1.0,1.0); 

  26.  
  27. ENDCG 


  28.  
  29.  

当我们把使用该shader的材质赋给场景物体时,物体仅仅表现出单纯的白色。我们在shader中没有赋予它更丰富的内容,如法线,纹理等,所以他不会表现出任何深度,阴影等,当然也不会受到光照的影响。

注意:

  1. POSITIONSV_POSITION都是CG/HLSL中的语义,他们是不可省略的,这些语义用来告诉系统输入值和输出值的含义。POSTION告诉Unity这里将模型的顶点数据传入到v参数,而SV_POSITION则告诉Unity顶点着色器输出的是裁剪空间中的顶点坐标。
  2. UnityObjectToClipPos(v) 是mul(UNITY_MATRIX_MVP,v)更新后的函数,他是Unity内置函数,用来帮我们进行顶点坐标从模型空间转换到裁剪空间的转换。
  3. SV_TARGETHLSL中的系统语义,它输出的是一个float4类型的变量,它等同于告诉渲染器,把用户的输出颜色存储到一个渲染目标中,有时也使用COLOR代替,考虑到平台的通用性最好使用SV_TARGET
  4. 模型空间:模型空间我们可以理解为模型自身的局部坐标,一个模型上的顶点位置信息,都是依托自身的局部坐标的,但当我们把它放到场景中的时候,就需要我们转换这些信息来使用。
  5. 裁剪空间:可以简单的理解为Unity中摄像机视椎体包围的空间,不在其空间内的信息将会被剔除,保留的信息后续会被投影到屏幕上被看到。

顶点着色器与片元着色器之间通信

片元着色器是无法直接获取陈模型的顶点信息的,这时就需要我们通过使用结构体作为媒介,有顶点着色器向片元着色器传递一些数据,如:模型法线,纹理坐标等。

示例

  1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 
  2.  
  3. Shader "UnityShaderBoook/vert2frag"{ 
  4. Properties { 
  5. _Color ("Color Tint", Color) = (1, 1, 1, 1

  6. //Properties并非必须,此shader中不声明任何材质属性 
  7. SubShader{ 
  8.  
  9.  
  10. Pass{  
  11.  
  12. CGPROGRAM 
  13. //编译命令,指定顶点/片元着色器处理函数 
  14. #pragma vertex vert 
  15. #pragma fragment frag 
  16.  
  17. uniform fixed4 _Color; 
  18. //结构体用于指定向顶点着色器传递的信息 
  19. struct a2v{ 
  20. float4 vertex:POSITION;//模型的顶点坐标 
  21. float4 normal:NORMAL;//模型的法线信息 
  22. float4 texcoord:TEXCOORD0;//模型的第一套纹理 
  23. }; 
  24.  
  25. //结构体指定了顶点着色器向片元着色器传出的信息 
  26. struct v2f{ 
  27. float4 pos:SV_POSITION;//裁剪空间中的坐标信息 
  28. fixed3 color:COLOR0;//COLOR0语义可用来存储颜色信息 
  29. }; 
  30.  
  31. v2f vert(a2v v) { 
  32. v2f o; 
  33. o.pos = UnityObjectToClipPos(v.vertex); 
  34. o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5); 
  35. return o; 

  36.  
  37.  
  38. //接收传入的信息 
  39. fixed4 frag(v2f i):SV_TARGET{ 
  40. fixed3 c = i.color; 
  41. c *= _Color.rgb; 
  42. return fixed4(c, 1.0); 

  43.  
  44. ENDCG 


  45.  
  46.  

注意: 顶点着色器是逐个顶点调用的,片元着色器是逐片元调用的。片元着色器中的输入实际是吧顶点着色器的输出插值后得到的结果。

猜你喜欢

转载自www.cnblogs.com/Firepad-magic/p/9349653.html