赞
踩
纹理贴图:让模型拥有色彩、花纹等。
法线贴图:为减少资源消耗,模型本身的细节是比较少的。法线贴图可以增加模型的细节,让模型的表面出现更多的细节、阴影等。法线贴图一般是在切线空间下的,以便适合不同模型。如果是在模型空间下的,则只能配合对应的模型使用。切线空间的法线贴图看起来主要是蓝色,而模型空间的看起来五颜六色。
uv坐标: 纹理坐标又称为uv坐标。u、v分别代表横轴、纵轴。贴图左下为原点,范围为0-1。比如贴图右上角为(1,1)。
贴图的平铺和偏移:
纹理贴图和法线贴图的属性:Tiling-平铺;Offset-平移;
Tiling能让贴图变为重复的多份。比如设置为x=1,y=2,则x方向不变,y方向变成重复平铺的两份,各占一半高度。如果要使用Tiling让贴图重复平铺,需要贴图文件的Wrap Mode设置为Repeat。
Offset自然是让贴图平移偏离原位置。
本文所需要的素材包下载:
链接:https://pan.baidu.com/s/1JOSWNaT9APrw25C8geYwhA
提取码:wwic
下载后导入到工程中。之后用包内的预制体在场景中生成一个模型。
然后我们新建一个材质并给模型替换上新材质。
之后创建一个Shader文件(Standard Surface Shader),并修改内容如下:
- Shader "Tutorial/04Texture"{
- Properties{
- //调整纹理贴图的颜色用
- _Color("Color",Color)=(1,1,1,1)
- //纹理贴图
- _MainTex("MainTex",2D)="white"{}
- //法线贴图。这里不能用"white"而要用"bump"表示没有法线贴图时默认使用模型本身的法线
- _NormalMap("NormalMap",2D)="bump"{}
- //控制使用法线贴图的法线的比例。如果为1则完全使用法线贴图。如果为0则完全使用模型本身的法线。
- //如果在0~1则法线贴图和模型法线按比例产生影响。如果大于1则会变得比完全使用法线贴图更加夸张。
- _BumpScale("BumpScale",Range(0,10))=1
- }
-
- SubShader{
- pass{
- Tags{
- "Lighting"="ForwardBase"
- }
- CGPROGRAM
- #include "Lighting.cginc"
- #pragma vertex vert
- #pragma fragment frag
- fixed4 _Color;
- //纹理贴图
- sampler2D _MainTex;
- //_MainTex_ST的前二维代表纹理贴图的平铺数,后二维代表纹理贴图的偏移数。
- //这个变量必须命名为纹理贴图变量名+"_ST"
- //ST表示scale 和 transition
- float4 _MainTex_ST;
- //法线贴图
- sampler2D _NormalMap;
- //法线贴图的平铺与偏移
- //与纹理贴图的情况类似,命名必须为法线贴图名+"_ST"
- float4 _NormalMap_ST;
- float _BumpScale;
-
- struct a2v{
- //模型空间下的顶点坐标
- float4 vertex:POSITION;
- //模型的法线
- //之后要用切线空间,切线空间是通过模型的法线和切线确定的。所以要获得法线和切线然后传输到片元函数。
- float3 normal:normal;
- //模型的切线
- //这里的方向不再用float3而用float4,因为需要第4维用来确定切线空间中坐标轴的方向
- float4 tangent:TANGENT;
- //通过语义:TEXCOORD 获得了uv坐标
- float2 texcoord:TEXCOORD;
- };
- struct v2f{
- //剪切空间下的顶点坐标
- float4 svPos:SV_POSITION;
- //存储切线空间下平行光的方向
- //用TEXCOORD、COLOR解释时,并不代表只能存储纹理坐标、颜色。这里存了方向。
- float3 lightDir:TEXCOORD0;
- //世界空间下的顶点坐标
- float4 worldVertex:TEXCOORD1;
- //存放uv坐标用,以便传递到片元函数中。xy存储纹理贴图坐标,zw存储法线贴图坐标。xyzw分别代表第1、2、3、4维。
- float4 uv:TEXCOORD3;
- };
- v2f vert(a2v v){
- v2f f;
- f.svPos=mul(UNITY_MATRIX_MVP,v.vertex);
- //v.texcoord即uv坐标在这里表示现在需要使用纹理/法线贴图的哪个位置
- //对现在需要使用纹理贴图的哪个位置的坐标进行缩放和平移
- //*_MainTex_ST.xy表示乘上平铺数,+_MainTex_ST.zw则表示加上偏移
- f.uv.xy=v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
- //对法线贴图也进行类似操作
- f.uv.zw=v.texcoord*_NormalMap_ST.xy+_NormalMap_ST.zw;
- //调用一个宏得到一个矩阵rotation用来把模型空间下的方向转换到切线空间下。
- //用这个宏必须配合v、f、normal、tangent这几个固定的变量名才能正常使用。
- //如果没有用这几个变量名或用来表示其它内容就可能报错。
- TANGENT_SPACE_ROTATION;
- //rotation就是之前得到的矩阵,用来把模型空间下的方向转换到切线空间的下。
- //ObjSpaceLightDir(v.vertex)表示得到该顶点的模型空间下的光源方向
- f.lightDir= mul(rotation,ObjSpaceLightDir(v.vertex));
-
- return f;
- }
- //因为从法线贴图取得的法线方向在切线空间下,所以把所有跟法线方向有关的运算都放在切线空间下进行。
- fixed4 frag(v2f f):SV_TARGET{
- //读取法线贴图的颜色
- //tex2D(贴图,坐标)就表示读取该贴图的相应坐标的颜色
- fixed4 normalColor=tex2D(_NormalMap,f.uv.zw);
- //使用unity自带的方法通过法线贴图的颜色得到切线空间下的法线
- fixed3 tangentNormal=UnpackNormal(normalColor);
- //切线空间下的法线的z轴实际就是模型空间下模型的法线
- //_BumpScale为使用法线贴图的比例,只需要将从法线贴图得到的切线空间下的法线的xy乘这个系数而不用管z
- //当_BumpScale为0时该向量只剩z轴自然就成了模型空间下模型的法线。
- tangentNormal.xy=tangentNormal.xy*_BumpScale;
- tangentNormal=normalize(tangentNormal);
- //顶点函数中已经将光源方向转换到了切线空间
- fixed3 lightDir=normalize(f.lightDir);
- //获得纹理贴图上对应的颜色
- fixed4 texcolor= tex2D(_MainTex,f.uv.xy)*_Color;
- //将纹理贴图的颜色融入到漫反射颜色中。
- //同时法线也影响着该点的明暗,从而在一些区域形成阴影以增加细节。
- fixed3 diffuse=_LightColor0.rgb*texcolor.rgb*max(0,dot(tangentNormal,lightDir));
- //通过漫反射颜色和环境光叠加得到最终颜色。这里让环境光颜色也融合了纹理贴图颜色。
- fixed3 tempColor=diffuse+UNITY_LIGHTMODEL_AMBIENT.rgb*texcolor;
-
- return fixed4(tempColor,1);
- }
- ENDCG
- }
- }
- Fallback "Diffuss"
- }
为模型选择新写的shader后,在工程面板中添加纹理贴图和法线贴图。先在工程面板中设置一下图片的类型,纹理贴图需要是Texture,法线贴图是Normal map。
然后给模型的这个Shader添加纹理贴图和法线贴图:
之后可以调整BumpScale,当为0时完全未使用法线贴图,模型的细节就比较少。当为1时完全使用法线贴图,模型表面的细节增加了很多。当大于1时就比较夸张了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。