当前位置:   article > 正文

UnityShader切线空间和世界空间下的凹凸映射计算_unity 世界空间切线信息

unity 世界空间切线信息

##

1.在切线空间下计算

  1. Shader "Unity Shaders Book/Chapter 7/Normal Map In Tangent Space"
  2. {
  3. Properties
  4. {
  5. _Color ("Color Tint", Color) = (1,1,1,1)
  6. _MainTex("Main Tex", 2D) = "White" {}
  7. //法线纹理,bump是内置法线纹理
  8. _BumpMap ("Normal Map", 2D) = "bump" {}
  9. //控制凹凸程度,为0时则不会对光照产生影响
  10. _BumpScale("Bump Scale", Float) = 1.0
  11. _Specular("Specular", Color) = (1,1,1,1)
  12. _Gloss ("Gloss",Range(8.0,256)) = 20
  13. }
  14. SubShader
  15. {
  16. Pass
  17. {
  18. Tags{"LightMode" = "ForwardBase"}
  19. CGPROGRAM
  20. #pragma vertex vert
  21. #pragma fragment frag
  22. #include "Lighting.cginc"
  23. fixed4 _Color;
  24. sampler2D _MainTex;
  25. float4 _MainTex_ST;
  26. sampler2D _BumpMap;
  27. float4 _BumpMap_ST;
  28. float _BumpScale;
  29. fixed4 _Specular;
  30. float _Gloss;
  31. struct a2v
  32. {
  33. float4 vertex : POSITION;
  34. float3 normal : NORMAL;
  35. //存储切线信息,tangent.w分量决定副切线的方向性,所以是float4类型
  36. float4 tangent : TANGENT;
  37. float4 texcoord: TEXCOORD0;
  38. };
  39. struct v2f
  40. {
  41. float4 pos : SV_POSITION;
  42. float4 uv : TEXCOORD0;
  43. //存储变换后的光照和视角方向
  44. float3 lightDir : TEXCOORD1;
  45. float3 viewDir : TEXCOORD2;
  46. };
  47. //在顶点着色器中计算切线空间下的光照和视角方向
  48. v2f vert (a2v v)
  49. {
  50. v2f o;
  51. o.pos = UnityObjectToClipPos(v.vertex);
  52. //uv的xy存储主贴图的纹理坐标,zw存储法线贴图的纹理坐标
  53. o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
  54. o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
  55. //计算从模型空间到切线空间的变换矩阵
  56. //计算副切线
  57. //float3 binormal = cross(normalze(v.normal), normalize(v.tangent.xyz)) * v.tangent.w;
  58. //float3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);
  59. //或者可直接使用Unity内置的宏
  60. TANGENT_SPACE_ROTATION;
  61. //计算从模型空间到切线空间的光照方向
  62. o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
  63. //计算从模型空间到切线空间的视角方向
  64. o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
  65. return o;
  66. }
  67. //在片元着色器中采样得到切线空间下的发现方向,再在切下空间下进行光照计算
  68. fixed4 frag (v2f i) : SV_Target
  69. {
  70. fixed3 tangentLightDir = normalize(i.lightDir);
  71. fixed3 tangentViewDir = normalize(i.viewDir);
  72. //利用tex2D对法线纹理_BumpMap进行采样
  73. fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw);
  74. fixed3 tangentNormal;
  75. //如果法线纹理的类型没有被设置成“Normal map”,则需要在代码中手动进行操作
  76. //将法线纹理中存储的像素值反映射回来
  77. //tangentNormal.xy = (packedNormal.xy * 2 -1) * _BumpScale;
  78. //tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy,tangentNormal.xy)));
  79. //如果法线纹理的类型已经被设置成“Normal map”,使用上述方法就会出错,此时使用内置函数UnpackNormal
  80. tangentNormal = UnpackNormal(packedNormal);
  81. tangentNormal.xy *= _BumpScale;
  82. tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
  83. //纹理贴图
  84. fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
  85. //环境光
  86. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  87. //漫反射
  88. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal,tangentLightDir));
  89. //Blinn-Phong光照
  90. fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
  91. fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(tangentNormal,halfDir)), _Gloss);
  92. return fixed4(ambient + diffuse + specular,1.0);
  93. }
  94. ENDCG
  95. }
  96. }
  97. Fallback"Specular"
  98. }

2.在世界空间下计算

  1. Shader "Unity Shaders Book/Chapter 7/Normal Map In World Space"
  2. {
  3. Properties
  4. {
  5. _Color ("Color Tint", Color) = (1,1,1,1)
  6. _MainTex("Main Tex", 2D) = "White" {}
  7. //法线纹理,bump是内置法线纹理
  8. _BumpMap ("Normal Map", 2D) = "bump" {}
  9. //控制凹凸程度,为0时则不会对光照产生影响
  10. _BumpScale("Bump Scale", Float) = 1.0
  11. _Specular("Specular", Color) = (1,1,1,1)
  12. _Gloss ("Gloss",Range(8.0,256)) = 20
  13. }
  14. SubShader
  15. {
  16. Pass
  17. {
  18. Tags{"LightMode" = "ForwardBase"}
  19. CGPROGRAM
  20. #pragma vertex vert
  21. #pragma fragment frag
  22. #include "Lighting.cginc"
  23. fixed4 _Color;
  24. sampler2D _MainTex;
  25. float4 _MainTex_ST;
  26. sampler2D _BumpMap;
  27. float4 _BumpMap_ST;
  28. float _BumpScale;
  29. fixed4 _Specular;
  30. float _Gloss;
  31. struct a2v
  32. {
  33. float4 vertex : POSITION;
  34. float3 normal : NORMAL;
  35. //存储切线信息,tangent.w分量决定副切线的方向性,所以是float4类型
  36. float4 tangent : TANGENT;
  37. float4 texcoord: TEXCOORD0;
  38. };
  39. //v2f需要包含从切线空间到世界空间的变换矩阵
  40. struct v2f
  41. {
  42. float4 pos : SV_POSITION;
  43. float4 uv : TEXCOORD0;
  44. //一个插值寄存器最多只能存储float4大小的变量,可以将矩阵按行拆成多个变量进行存储
  45. //TtoW0、TtoW1、TtoW2依次存储了从切线空间到世界空间的变换矩阵的每一行
  46. //其中float4中的w分量存储的是世界空间下的顶点位置
  47. float4 TtoW0 : TEXCOORD1;
  48. float4 TtoW1 : TEXCOORD2;
  49. float4 TtoW2 : TEXCOORD3;
  50. };
  51. //计算从切线空间到世界空间的变换矩阵
  52. v2f vert (a2v v)
  53. {
  54. v2f o;
  55. o.pos = UnityObjectToClipPos(v.vertex);
  56. //uv的xy存储主贴图的纹理坐标,zw存储法线贴图的纹理坐标
  57. o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
  58. o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
  59. //分别计算世界空间下的顶点位置、顶点切线、副切线、法线
  60. //将顶点切线、副切线、法线按列摆放得到从切线空间到世界空间的变换矩阵
  61. float3 worldPos = mul(_Object2World, v.vertex).xyz;
  62. fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
  63. fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
  64. fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
  65. //把上述矩阵按行存储在TtoW0、TtoW1、TtoW2中,顶点位置存储在w分量中
  66. o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
  67. o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
  68. o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
  69. return o;
  70. }
  71. //在世界空间下进行光照计算
  72. fixed4 frag (v2f i) : SV_Target
  73. {
  74. //从TtoW0、TtoW1、TtoW2的w分量中构建世界空间下的坐标
  75. float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
  76. //得到世界空间下的光照和视角方向
  77. fixed3 lightDir =normalize( UnityWorldSpaceLightDir(worldPos));
  78. fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
  79. //对法线纹理进行采样、解码、缩放
  80. fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
  81. bump.xy *= _BumpScale;
  82. bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
  83. //使用变换矩阵将法线变换到世界空间下
  84. bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
  85. //纹理贴图
  86. fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
  87. //环境光
  88. fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
  89. //漫反射
  90. fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump,lightDir));
  91. //Blinn-Phong光照
  92. fixed3 halfDir = normalize(lightDir + viewDir);
  93. fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(bump,halfDir)), _Gloss);
  94. return fixed4(ambient + diffuse + specular,1.0);
  95. }
  96. ENDCG
  97. }
  98. }
  99. Fallback"Specular"
  100. }

原文:UnityShader初级篇——凹凸映射_啦啦啦小聪聪的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/649794
推荐阅读
相关标签
  

闽ICP备14008679号