700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Unity Shader零基础入门4:纹理贴图与法线贴图

Unity Shader零基础入门4:纹理贴图与法线贴图

时间:2019-09-09 10:16:51

相关推荐

Unity Shader零基础入门4:纹理贴图与法线贴图

纹理贴图:让模型拥有色彩、花纹等。

法线贴图:为减少资源消耗,模型本身的细节是比较少的。法线贴图可以增加模型的细节,让模型的表面出现更多的细节、阴影等。法线贴图一般是在切线空间下的,以便适合不同模型。如果是在模型空间下的,则只能配合对应的模型使用。切线空间的法线贴图看起来主要是蓝色,而模型空间的看起来五颜六色。

uv坐标:纹理坐标又称为uv坐标。u、v分别代表横轴、纵轴。贴图左下为原点,范围为0-1。比如贴图右上角为(1,1)。

贴图的平铺和偏移:

纹理贴图和法线贴图的属性:Tiling-平铺;Offset-平移;

Tiling能让贴图变为重复的多份。比如设置为x=1,y=2,则x方向不变,y方向变成重复平铺的两份,各占一半高度。如果要使用Tiling让贴图重复平铺,需要贴图文件的Wrap Mode设置为Repeat。

Offset自然是让贴图平移偏离原位置。

本文所需要的素材包下载:

链接:/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 和 transitionfloat4 _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时就比较夸张了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。