当前位置:   article > 正文

Unity纹理基础_unity urp viewdir

unity urp viewdir

单张纹理材质实现:

 

  1. Shader "Custom/SimpleTextureMat"
  2. {
  3. Properties{
  4. //TintColor:色调
  5. _Color("TintColor", Color) = (1.0, 1.0, 1.0, 1.0)
  6. _MianTex("Maintex", 2D) = "white"{}
  7. _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
  8. _Gloss("Gloss", Range(8.0, 256)) = 20
  9. }
  10. SubShader{
  11. Pass{
  12. Tags{
  13. "LightMode" = "ForwardBase"
  14. }
  15. CGPROGRAM
  16. #pragma vertex vert
  17. #pragma fragment frag
  18. #include "Lighting.cginc"
  19. #include "UnityCG.cginc"
  20. half4 _Color;
  21. sampler2D _MianTex;
  22. float4 _MianTex_ST;
  23. half4 _Specular;
  24. half _Gloss;
  25. struct a2v{
  26. float4 vertex : POSITION;
  27. float3 normal : NORMAL;
  28. float2 texcoord : TEXCOORD0;
  29. };
  30. struct v2f{
  31. float4 vertex : SV_POSITION;
  32. float3 worldNormal : TEXCOORD0;
  33. float3 worldPos : TEXCOORD1;
  34. float2 uv : TEXCOORD3;
  35. };
  36. v2f vert(a2v i){
  37. v2f o;
  38. UNITY_INITIALIZE_OUTPUT(v2f, o);
  39. o.vertex = UnityObjectToClipPos(i.vertex);
  40. o.worldNormal = normalize(UnityObjectToWorldNormal(i.normal));
  41. o.worldPos = mul(unity_ObjectToWorld, i.vertex);
  42. o.uv = TRANSFORM_TEX(i.texcoord, _MianTex);
  43. //o.uv = i.texcoord;
  44. return o;
  45. }
  46. half4 frag(v2f i) : SV_TARGET{
  47. half3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  48. half3 albedo = tex2D(_MianTex, i.uv) * _Color;
  49. half3 diffuse = _LightColor0.rgb * albedo * saturate(dot(i.worldNormal, lightDir));
  50. half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
  51. half3 reflectDir = normalize(reflect(-lightDir, i.worldNormal));
  52. half3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
  53. half3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
  54. return half4(diffuse + ambient + specular, 1.0);
  55. }
  56. ENDCG
  57. }
  58. }
  59. FallBack "Specular"
  60. }

         部分代码段分析:

                o.uv = TRANSFORM_TEX(i.texcoord, _MianTex);

TRANSFROM_TEX:使用纹理的属性值 MianTex_ST 对顶点纹理坐标进行变化,使得可以在材质面板中对贴图进行缩放和偏移操作。

 TRANSFROM_TEX原理为:

ambient(环境光)diffuse(固有色)specular(高光)都可以选择性乘以纹素(Texel) 以达到不同的效果。

        ambient,diffuse:

         ambient,diffuse,specular: 

         diffuse,specular:

纹理应用:凹凸映射 

        实现凹凸映射主要有两种方法:高度映射和法线映射。

        而法线纹理中有一种特殊的纹理,称为切线空间的法线纹理(tangent-space normal map) ,模型空间的法线纹理不同,切线空间的法线纹理记录的是每个点在各自的切线空间中的法线扰动方向,切线空间以顶点本身为原点,切线方向为x轴,法线方向为z轴。所以切线空间的法线贴图有大部分的蓝色区域,因为对于不变的法线,在切线空间中的矢量为(0,0,1),对应为RGB中的蓝色。

        基于切线空间法线贴图的材质:

  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  3. Shader "Custom/TangentSpaceNormalMapMat"
  4. {
  5. Properties{
  6. //TintColor:色调
  7. _Color("TintColor", Color) = (1.0, 1.0, 1.0, 1.0)
  8. _MianTex("Maintex", 2D) = "white"{}
  9. _BumpMap("BumpMap", 2D) = "blue"{}
  10. _BumpScale("BumpScale", float) = 1.0
  11. _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
  12. _Gloss("Gloss", Range(8.0, 256)) = 20
  13. }
  14. SubShader{
  15. Pass{
  16. Tags{
  17. "LightMode" = "ForwardBase"
  18. }
  19. CGPROGRAM
  20. #pragma vertex vert
  21. #pragma fragment frag
  22. #include "Lighting.cginc"
  23. #include "UnityCG.cginc"
  24. half4 _Color;
  25. sampler2D _MianTex;
  26. float4 _MianTex_ST;
  27. sampler2D _BumpMap;
  28. float4 _BumpMap_ST;
  29. float _BumpScale;
  30. half4 _Specular;
  31. half _Gloss;
  32. struct a2v{
  33. float4 vertex : POSITION;
  34. float3 normal : NORMAL;
  35. float4 tangent : TANGENT;
  36. float2 texcoord : TEXCOORD0;
  37. };
  38. struct v2f{
  39. float4 vertex : SV_POSITION;
  40. float3 tangentLightDir : TEXCOORD0;
  41. float3 tangentViewDir : TEXCOORD1;
  42. float4 uv : TEXCOORD2;
  43. };
  44. v2f vert(a2v i){
  45. v2f o;
  46. UNITY_INITIALIZE_OUTPUT(v2f, o);
  47. o.vertex = UnityObjectToClipPos(i.vertex);
  48. float3 binormal = cross(i.normal, i.tangent.xyz ) * i.tangent.w;
  49. float3x3 rotation = float3x3(i.tangent.xyz, binormal, i.normal);
  50. o.tangentLightDir = normalize(mul(rotation, ObjSpaceLightDir(i.vertex)).xyz);
  51. o.tangentViewDir = normalize(mul(rotation, ObjSpaceViewDir(i.vertex)).xyz);
  52. o.uv.xy = TRANSFORM_TEX(i.texcoord, _MianTex);
  53. o.uv.zw = TRANSFORM_TEX(i.texcoord, _BumpMap);
  54. //o.uv = i.texcoord;
  55. return o;
  56. }
  57. half4 frag(v2f i) : SV_TARGET{
  58. half3 albedo = tex2D(_MianTex, i.uv.xy) * _Color;
  59. half4 mapTangent = tex2D(_BumpMap, i.uv.zw);
  60. fixed3 normalTangentSpace;
  61. normalTangentSpace = UnpackNormal(mapTangent);
  62. normalTangentSpace.xy *= _BumpScale;
  63. normalTangentSpace.z = sqrt(1.0 - saturate(dot(normalTangentSpace.xy, normalTangentSpace.xy)));
  64. half3 diffuse = _LightColor0.rgb * albedo * saturate(dot(normalTangentSpace, i.tangentLightDir));
  65. half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
  66. half3 reflectDir = normalize(reflect(-i.tangentLightDir, normalTangentSpace));
  67. half3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(reflectDir, i.tangentViewDir)), _Gloss);
  68. return half4(diffuse + ambient + specular, 1.0);
  69. }
  70. ENDCG
  71. }
  72. }
  73. FallBack "Specular"
  74. }

         分析:以上实现是基于切线空间法线贴图完成的,在顶点着色器中将光照方向和视角方向变换到切线空间,然后在片元着色器中对模型求环境光,固有色和高光。同样,也可以将法线贴图求得的法线转换到世界空间中,来计算光照。

        Unity同样可以使用灰度(高度)图生成法线贴图。 

渐变纹理(BumpMap)实现

  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  3. Shader "Custom/RampMapMat"
  4. {
  5. Properties{
  6. //TintColor:色调
  7. _Color("TintColor", Color) = (1.0, 1.0, 1.0, 1.0)
  8. _MianTex("Maintex", 2D) = "white"{}
  9. _RampMap("RampMap", 2D) = "white"{}
  10. _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
  11. _Gloss("Gloss", Range(8.0, 256)) = 20
  12. }
  13. SubShader{
  14. Pass{
  15. Tags{
  16. "LightMode" = "ForwardBase"
  17. }
  18. CGPROGRAM
  19. #pragma vertex vert
  20. #pragma fragment frag
  21. #include "Lighting.cginc"
  22. #include "UnityCG.cginc"
  23. half4 _Color;
  24. sampler2D _MianTex;
  25. float4 _MianTex_ST;
  26. sampler2D _RampMap;
  27. float4 RampMap_ST;
  28. half4 _Specular;
  29. half _Gloss;
  30. struct a2v{
  31. float4 vertex : POSITION;
  32. float3 normal : NORMAL;
  33. float2 texcoord : TEXCOORD0;
  34. };
  35. struct v2f{
  36. float4 vertex : SV_POSITION;
  37. float3 worldNormal : TEXCOORD0;
  38. float3 worldPos : TEXCOORD1;
  39. float2 uv : TEXCOORD3;
  40. };
  41. v2f vert(a2v i){
  42. v2f o;
  43. UNITY_INITIALIZE_OUTPUT(v2f, o);
  44. o.vertex = UnityObjectToClipPos(i.vertex);
  45. o.worldNormal = normalize(UnityObjectToWorldNormal(i.normal));
  46. o.worldPos = mul(unity_ObjectToWorld, i.vertex);
  47. o.uv = TRANSFORM_TEX(i.texcoord, _MianTex);
  48. //o.uv = i.texcoord;
  49. return o;
  50. }
  51. half4 frag(v2f i) : SV_TARGET{
  52. half3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  53. half3 albedo = tex2D(_MianTex, i.uv) * _Color;
  54. half lightScale = 0.5 * dot(i.worldNormal, lightDir) + 0.5;
  55. half3 diffuseColor = tex2D(_RampMap, float2(lightScale, lightScale)).rgb * _Color.rgb;
  56. half3 diffuse = _LightColor0.rgb * diffuseColor;
  57. half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
  58. half3 reflectDir = normalize(reflect(-lightDir, i.worldNormal));
  59. half3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
  60. half3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
  61. return half4(diffuse + ambient + specular, 1.0);
  62. }
  63. ENDCG
  64. }
  65. }
  66. FallBack "Specular"
  67. }

 注意:使用渐变纹理时,渐变贴图需要设置Warp Mode为Clamp,而不是默认的Repeat。否则容易出现问题,在HalfLambert光照模型中可能无法明显体现出,但在Blinn-Phong模型中可以明显看出BUG。

这是由于采样时,虽然理论上lightScale的值在[0, 1]之间,但由于精度问题也可能会有1.0001这样的值出现,而Repeat模式下对将整数部分舍弃,只得到0.0001,对应渐变贴图最左侧的值。而Clamp模型下会将大于1的值按照1处理。

遮罩纹理(MaskMap) 

  1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  3. Shader "Custom/MaskMapMat"
  4. {
  5. Properties{
  6. //TintColor:色调
  7. _Color("TintColor", Color) = (1.0, 1.0, 1.0, 1.0)
  8. _MianTex("Maintex", 2D) = "white"{}
  9. _Specular("Specular", Color) = (1.0, 1.0, 1.0, 1.0)
  10. _MaskMap("MaskMap", 2D) = "white"{}
  11. _Gloss("Gloss", Range(8.0, 256)) = 20
  12. }
  13. SubShader{
  14. Pass{
  15. Tags{
  16. "LightMode" = "ForwardBase"
  17. }
  18. CGPROGRAM
  19. #pragma vertex vert
  20. #pragma fragment frag
  21. #include "Lighting.cginc"
  22. #include "UnityCG.cginc"
  23. half4 _Color;
  24. sampler2D _MianTex;
  25. float4 _MianTex_ST;
  26. sampler2D _MaskMap;
  27. float4 _MaskMap_ST;
  28. half4 _Specular;
  29. half _Gloss;
  30. struct a2v{
  31. float4 vertex : POSITION;
  32. float3 normal : NORMAL;
  33. float2 texcoord : TEXCOORD0;
  34. };
  35. struct v2f{
  36. float4 vertex : SV_POSITION;
  37. float3 worldNormal : TEXCOORD0;
  38. float3 worldPos : TEXCOORD1;
  39. float2 uv : TEXCOORD3;
  40. };
  41. v2f vert(a2v i){
  42. v2f o;
  43. UNITY_INITIALIZE_OUTPUT(v2f, o);
  44. o.vertex = UnityObjectToClipPos(i.vertex);
  45. o.worldNormal = normalize(UnityObjectToWorldNormal(i.normal));
  46. o.worldPos = mul(unity_ObjectToWorld, i.vertex);
  47. o.uv = TRANSFORM_TEX(i.texcoord, _MianTex);
  48. //o.uv = i.texcoord;
  49. return o;
  50. }
  51. half4 frag(v2f i) : SV_TARGET{
  52. half3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
  53. half3 albedo = tex2D(_MianTex, i.uv) * _Color;
  54. half mask = tex2D(_MaskMap, i.uv).r;
  55. half3 diffuse = _LightColor0.rgb * albedo * saturate(dot(i.worldNormal, lightDir));
  56. half3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
  57. half3 reflectDir = normalize(reflect(-lightDir, i.worldNormal));
  58. half3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
  59. half3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(reflectDir, viewDir)), _Gloss) * half3(mask, mask, mask);
  60. return half4(diffuse + ambient + specular, 1.0);
  61. }
  62. ENDCG
  63. }
  64. }
  65. FallBack "Specular"
  66. }

 本质上就是在高光绘制过程中增加了根据遮罩贴图某个通道的值,确定高光强度的方法。

        上图为主要对砖块部分添加高光,下图为主要对砖块间缝隙添加高光。

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

闽ICP备14008679号