关于纹理贴图介绍

纹理坐标也叫UV坐标,UV坐标都是0~1,并不是我们所理解的像素坐标,相当于是一个百分比。

编写shader映射纹理

将纹理的颜色取代漫反射的颜色

Shader "AladdinShader/11 Single Texture Shader"
{
Properties
{
// _Diffuse("Diffuse Color", Color)=(1,1,1,1) //漫反射的颜色
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_Specular("Specular Color", Color)=(1,1,1,1)
_Gloss("Gloss",Range(10,200))=20
}
SubShader {
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
half _Gloss;
//顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
float3 normal:NORMAL; //模型空间下的法线 //纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
float4 worldVertex:TEXCOORD1; //将取到的纹理坐标传递到片元函数
float4 uv:TEXCOORD2;
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv = v.texcoord;
return f;
} //片元函数返回颜色
fixed4 frag(v2f f):SV_Target{
//漫反射
//漫反射颜色 先不管透明度
//_LightColor0 平行光的颜色 cos夹角 光的方向和视野的夹角
fixed3 normalDir = normalize(f.worldNormal);
//光的方向
fixed3 lightDir = normalize(WorldSpaceLightDir(f.worldVertex)); //返回贴图上某像素颜色的值
fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb; //漫反射的颜色
// fixed3 diffuse = _LightColor0.rgb *_Diffuse.rgb * max(dot(normalDir, lightDir),0);
fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(normalDir, lightDir), 0); //相机方向
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldVertex)); //光和相机方向的平分线
fixed3 halfDir = normalize(lightDir + viewDir);
//高光反射
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(normalDir,halfDir),0),_Gloss);
//环境光
// fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rgb; //使用了纹理之后 一般环境光也跟纹理做一个融合
fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,1);
}
ENDCG
}
}
FallBack "Specular"
}

我们找一个纹理贴图



然后将贴图赋值给_MainTex属性,调整一下高光颜色和整体贴图颜色属性并且查看效果

第一组效果:





第二组效果:



给纹理添加偏移和缩放

将一个贴图拖到模型上会自动创建跟名字一样的材质,Shader中创建一个2D属性会发现在Inspector面板上会有一个Tiling和Offset两个属性,Tiling是缩放属性,Offset是偏移属性。

将上面的例子修改一下Shader,支持纹理的旋转和缩放:

Shader "AladdinShader/11 Single Texture Shader"
{
Properties
{
// _Diffuse("Diffuse Color", Color)=(1,1,1,1) //漫反射的颜色
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_Specular("Specular Color", Color)=(1,1,1,1)
_Gloss("Gloss",Range(10,200))=20
}
SubShader {
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
//Tiling 和Offset ST 就是偏移和缩放的值
float4 _MainTex_ST;
half _Gloss;
//顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
float3 normal:NORMAL; //模型空间下的法线 //纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
float4 worldVertex:TEXCOORD1; //将取到的纹理坐标传递到片元函数
float2 uv:TEXCOORD2;
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; //乘以Tiling缩放 + Offset旋转
return f;
} //片元函数返回颜色
fixed4 frag(v2f f):SV_Target{
//漫反射
//漫反射颜色 先不管透明度
//_LightColor0 平行光的颜色 cos夹角 光的方向和视野的夹角
fixed3 normalDir = normalize(f.worldNormal);
//光的方向
fixed3 lightDir = normalize(WorldSpaceLightDir(f.worldVertex)); //返回贴图上某像素颜色的值
fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb; //漫反射的颜色
// fixed3 diffuse = _LightColor0.rgb *_Diffuse.rgb * max(dot(normalDir, lightDir),0);
fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(normalDir, lightDir), 0); //相机方向
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldVertex)); //光和相机方向的平分线
fixed3 halfDir = normalize(lightDir + viewDir);
//高光反射
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(normalDir,halfDir),0),_Gloss);
//环境光
// fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rgb; //使用了纹理之后 一般环境光也跟纹理做一个融合
fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,1);
}
ENDCG
}
}
FallBack "Specular"
}

说明:

1.pass中定义的新的变量 float4 _MainTex_ST; 是用来获取贴图的Tiling和Offset的值,因为是一个xyzw的四个值,所以我们用float4来定义,变量名_MainTex_ST是一个固定格式的变量,_MainTex是跟纹理贴图变量保持一致,_ST是缩放Scale和移动Translate的首字母。

2. f.uv = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; 这句是核心,意思是将纹理*Tiling的缩放系数加上偏移量就得到想要的效果。

效果图:







纹理的属性

Texture Type

  • Default 就是默认的贴图/Texture
  • Normal map 法线贴图
  • Editor GUI and Legacy GUI 编辑器贴图
  • Sprite(2D and UI) 就是2D图
  • Cursor 就是鼠标贴图
  • Cubemap就是用来做环境盒子
  • Cookie 就是影子贴图
  • Lightmap 就是光照贴图,场景烘焙之后的光照贴图,就不用实时计算光照

Advanced

  • Read/Write Enabled 是否可读写
  • Generate Mip Maps适配贴图 会计算生成若干个贴图 更大效果更好

Wrap Mode

  • Repeat 当超过0-1的范围会周期循环读取贴图
  • Clap 当超过0-1的范围会使用边界像素

Filter Mode

滤波模式,当纹理拉伸之后图片显示的模式

  • Point(no filter) 像素风格
  • Bilinear 二线性
  • Triliner 三线行

    从上到下一次越来越耗费性能,但效果会越来越好,一般选用中间的格式。Triliner会经过插值计算,效果更好,但计算量也最大,如果选择Point格式,比较适合像素风格,但远处看的话效果还行,近看就会看出像素效果。

关于凹凸映射和法线映射

使用情况:我们在减少模型面的情况下使用凹凸映射会让模型看起来更加精细。会修改模型的法线,让模型看起来凹凸不平。

举例:比如我们生活中常见的石头模型,如果模型本身不是精细,因为精细的模型会显得顶点和面数会比较多,但这时候可以采用法线贴图来实现表面坑洼的效果。

石头原效果图:



使用我们自定义的Shader看到模型本身的棱角效果图会感觉石头模型比较光滑



图二就感觉效果跟图一相差很大,但模型是用的同一个模型,这就体现了法线贴图的重要性。

法线贴图

那么何为发现贴图,看下图:



法线贴图就是将贴图的法线用颜色值表现出来,但法线是-11,颜色是01是怎么对应上的呢?这里就需要做一个处理:

pixel(像素值) = (normal(法线值) + 1) / 2

经过这样的变化就能存到颜色里面,所以我们拿到一个发现贴图我们需要反向运算才能获得正确的法线值。

normal = pixel * 2 - 1

切线空间

切换空间最重要的用途之一,即法线映射(Normal Mapping)。在这个空间里,我们不需要考虑该模型在场景中可能出现的位置、朝向等众多因素,而专注于模型本身。详细的参见文章:https://www.cnblogs.com/naturelight/articles/5486469.html

我们称tangant轴(T)、bitangent轴(B)及法线轴(N)所组成的坐标系,即切线空间(TBN)。



在立方体中,每个面都有对应的切线空间,每个面由两个三角形组成,该两个三角形中的纹理坐标就基于相应的切线空间。

编写法线贴图Shader

Shader "AladdinShader/13 Rock Normal Map Shader"
{
Properties
{
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_NormalMap("NormalMap", 2D) = "bump"{} //bump这个位置没有使用法线贴图的时候就使用模型自带的法线 使用的是切线空间
}
SubShader {
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST; //法线贴图的ST //顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
//切线空间的确定是通过(存储到模型里面的)法线和(存储到模型里面的)切线确定的
float3 normal:NORMAL;
float4 tangent:TANGENT; //TANGENT.w是用来确定切线空间中坐标轴的方向的
//纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
//fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
//切线空间下 平行光的方向
float3 lightDir:TEXCOORD0;
float4 worldVertex:TEXCOORD1;
//将取到的纹理坐标传递到片元函数
float4 uv:TEXCOORD2; //xy 用来存储MainTex的纹理坐标 zw用来存存储NormalMap的纹理坐标
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
//f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv.xy = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; //乘以Tiling缩放 + Offset旋转
f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw; TANGENT_SPACE_ROTATION;//调用这个之后会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下 调用这个还必须要求a2v 的变量是V 并且它里面要有切线空间下的法线normal和切线tangent这两个变量 在这个方法里面会使用
//得到模型空间下的光的方向
//ObjSpaceLightDir(v.vertex) //得到模型空间下的平行光方向
f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
return f;
} //把所有跟法线方向有关的运算都放在切线空间下
//从法线贴图里取得的法线方向都是在切线空间下的
fixed4 frag(v2f f):SV_Target{
//取得贴图里面获得的法线
//获取颜色值
fixed4 normalColor = tex2D(_NormalMap,f.uv.zw); //切线空间下的法线
//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1); //unity里面直接将法线贴图设置成NormalMap就会做一些处理,然后用系统方法提取法线 而不用我们自己计算
//提取法线
fixed3 tangentNormal = UnpackNormal(normalColor);
tangentNormal = normalize(tangentNormal); //光的方向
fixed3 lightDir = normalize(f.lightDir); //返回贴图上某像素颜色的值
fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb; fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0); fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,1);
}
ENDCG
}
}
FallBack "Specular"
}

效果图:



最左边是插件中的模型效果,最右边是自己实现的模型效果

法线贴图添加凹凸参数

添加凹凸参数属性控制凹凸力度

Shader "AladdinShader/13 Rock Normal Map Shader"
{
Properties
{
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_NormalMap("NormalMap", 2D) = "bump"{} //bump这个位置没有使用法线贴图的时候就使用模型自带的法线 使用的是切线空间
_BumpScale("Bump Scale", float) = 1
}
SubShader {
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST; //法线贴图的ST
float _BumpScale; //顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
//切线空间的确定是通过(存储到模型里面的)法线和(存储到模型里面的)切线确定的
float3 normal:NORMAL;
float4 tangent:TANGENT; //TANGENT.w是用来确定切线空间中坐标轴的方向的
//纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
//fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
//切线空间下 平行光的方向
float3 lightDir:TEXCOORD0;
float4 worldVertex:TEXCOORD1;
//将取到的纹理坐标传递到片元函数
float4 uv:TEXCOORD2; //xy 用来存储MainTex的纹理坐标 zw用来存存储NormalMap的纹理坐标
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
//f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv.xy = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; //乘以Tiling缩放 + Offset旋转
f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw; TANGENT_SPACE_ROTATION;//调用这个之后会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下 调用这个还必须要求a2v 的变量是V 并且它里面要有切线空间下的法线normal和切线tangent这两个变量 在这个方法里面会使用
//得到模型空间下的光的方向
//ObjSpaceLightDir(v.vertex) //得到模型空间下的平行光方向
f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
return f;
} //把所有跟法线方向有关的运算都放在切线空间下
//从法线贴图里取得的法线方向都是在切线空间下的
fixed4 frag(v2f f):SV_Target{
//取得贴图里面获得的法线
//获取颜色值
fixed4 normalColor = tex2D(_NormalMap,f.uv.zw); //切线空间下的法线
//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1); //unity里面直接将法线贴图设置成NormalMap就会做一些处理,然后用系统方法提取法线 而不用我们自己计算
//提取法线
fixed3 tangentNormal = UnpackNormal(normalColor);
tangentNormal = normalize(tangentNormal);
tangentNormal.xy = tangentNormal.xy * _BumpScale; //光的方向
fixed3 lightDir = normalize(f.lightDir); //返回贴图上某像素颜色的值
fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb; fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0); fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,1);
}
ENDCG
}
}
FallBack "Specular"
}

调整凹凸属性:





编写透明Shader

Shader "AladdinShader/14 Rock Alpha Shader"
{
Properties
{
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_NormalMap("NormalMap", 2D) = "bump"{} //bump这个位置没有使用法线贴图的时候就使用模型自带的法线 使用的是切线空间
_BumpScale("Bump Scale", float) = 1
_Alpha("Alpha", Range(0,1)) = 1
}
SubShader {
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" } ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST; //法线贴图的ST
float _BumpScale;
float _Alpha; //顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
//切线空间的确定是通过(存储到模型里面的)法线和(存储到模型里面的)切线确定的
float3 normal:NORMAL;
float4 tangent:TANGENT; //TANGENT.w是用来确定切线空间中坐标轴的方向的
//纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
//fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
//切线空间下 平行光的方向
float3 lightDir:TEXCOORD0;
float4 worldVertex:TEXCOORD1;
//将取到的纹理坐标传递到片元函数
float4 uv:TEXCOORD2; //xy 用来存储MainTex的纹理坐标 zw用来存存储NormalMap的纹理坐标
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
//f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv.xy = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; //乘以Tiling缩放 + Offset旋转
f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw; TANGENT_SPACE_ROTATION;//调用这个之后会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下 调用这个还必须要求a2v 的变量是V 并且它里面要有切线空间下的法线normal和切线tangent这两个变量 在这个方法里面会使用
//得到模型空间下的光的方向
//ObjSpaceLightDir(v.vertex) //得到模型空间下的平行光方向
f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
return f;
} //把所有跟法线方向有关的运算都放在切线空间下
//从法线贴图里取得的法线方向都是在切线空间下的
fixed4 frag(v2f f):SV_Target{
//取得贴图里面获得的法线
//获取颜色值
fixed4 normalColor = tex2D(_NormalMap,f.uv.zw); //切线空间下的法线
//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1); //unity里面直接将法线贴图设置成NormalMap就会做一些处理,然后用系统方法提取法线 而不用我们自己计算
//提取法线
fixed3 tangentNormal = UnpackNormal(normalColor);
tangentNormal = normalize(tangentNormal);
tangentNormal.xy = tangentNormal.xy * _BumpScale; //光的方向
fixed3 lightDir = normalize(f.lightDir); //返回贴图上某像素颜色的值
fixed4 texColor = tex2D(_MainTex, f.uv.xy) * _Color; fixed3 diffuse = _LightColor0.rgb * texColor.rgb * max(dot(tangentNormal, lightDir), 0); fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,texColor.a);
}
ENDCG
}
}
FallBack "Specular"
}

或者属性面板控制:

Shader "AladdinShader/14 Rock Alpha Shader"
{
Properties
{
_MainTex("Main Tex", 2D) = "white"{} //纹理贴图 默认白色
_Color("Color", Color) = (1,1,1,1) //整体一个色调
_NormalMap("NormalMap", 2D) = "bump"{} //bump这个位置没有使用法线贴图的时候就使用模型自带的法线 使用的是切线空间
_BumpScale("Bump Scale", float) = 1
_Alpha("Alpha", Range(0,1)) = 1
}
SubShader {
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
Pass{
//只有正确定义Tags 才能获取跟光相关的属性
Tags { "LightMode"="ForwardBase" } ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag // fixed4 _Diffuse;
sampler2D _MainTex;
fixed4 _Color;
fixed4 _Specular;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST; //法线贴图的ST
float _BumpScale;
float _Alpha; //顶点函数参数
struct a2v{
float4 vertex:POSITION; //顶点位置
//切线空间的确定是通过(存储到模型里面的)法线和(存储到模型里面的)切线确定的
float3 normal:NORMAL;
float4 tangent:TANGENT; //TANGENT.w是用来确定切线空间中坐标轴的方向的
//纹理坐标只能在定点函数取到
float4 texcoord:TEXCOORD0;
}; struct v2f{
float4 svPos:SV_POSITION;
//fixed3 worldNormal:TEXCOORD0;//世界空间下的法线
//切线空间下 平行光的方向
float3 lightDir:TEXCOORD0;
float4 worldVertex:TEXCOORD1;
//将取到的纹理坐标传递到片元函数
float4 uv:TEXCOORD2; //xy 用来存储MainTex的纹理坐标 zw用来存存储NormalMap的纹理坐标
}; v2f vert(a2v v)
{
v2f f;
f.svPos = mul(UNITY_MATRIX_MVP,v.vertex); //模型空间位置到剪裁空间的顶点位置的转换
//f.worldNormal = UnityObjectToWorldNormal(v.normal); //模型空间的法线转成时间空间下的法线
f.worldVertex = mul(v.vertex,unity_WorldToObject);
f.uv.xy = v.texcoord.xy * _MainTex_ST.xy +_MainTex_ST.zw; //乘以Tiling缩放 + Offset旋转
f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw; TANGENT_SPACE_ROTATION;//调用这个之后会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下 调用这个还必须要求a2v 的变量是V 并且它里面要有切线空间下的法线normal和切线tangent这两个变量 在这个方法里面会使用
//得到模型空间下的光的方向
//ObjSpaceLightDir(v.vertex) //得到模型空间下的平行光方向
f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
return f;
} //把所有跟法线方向有关的运算都放在切线空间下
//从法线贴图里取得的法线方向都是在切线空间下的
fixed4 frag(v2f f):SV_Target{
//取得贴图里面获得的法线
//获取颜色值
fixed4 normalColor = tex2D(_NormalMap,f.uv.zw); //切线空间下的法线
//fixed3 tangentNormal = normalize(normalColor.xyz * 2 - 1); //unity里面直接将法线贴图设置成NormalMap就会做一些处理,然后用系统方法提取法线 而不用我们自己计算
//提取法线
fixed3 tangentNormal = UnpackNormal(normalColor);
tangentNormal = normalize(tangentNormal);
tangentNormal.xy = tangentNormal.xy * _BumpScale; //光的方向
fixed3 lightDir = normalize(f.lightDir); //返回贴图上某像素颜色的值
fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb; fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0); fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rbg * texColor;
return fixed4(tempColor,_Alpha);
}
ENDCG
}
}
FallBack "Specular"
}



跟透明相关的代码块

Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}

ZWrite Off

Blend SrcAlpha OneMinusSrcAlpha

Shader学习交流群:

316977780

【Aladdin Unity3D Shader编程】之四 贴图纹理的更多相关文章

  1. 【Aladdin Unity3D Shader编程】之一 基本入门

    OpenGL.DirectX以及GLSL.HLSL.CG OpenGL和DirectX是图像应用编程接口,用于渲染二维或者三维图形. GLSL着色语言是用来在OpenGL中着色编程的语言,有点在于跨平 ...

  2. 【Aladdin Unity3D Shader编程】之三 光照模型(二)

    高光反射模型 Specular=直射光*pow(cosθ,高光的参数) θ:是反射光和视野方向的夹角 编写高光反射Shader Shader "AladdinShader/07 Specul ...

  3. 【Aladdin Unity3D Shader编程】之二 光照模型(一)

    光照模型 光照模型就是一个公式,使用这个公式来计算在某个点的光照效果. 在标准光照模型里面,我们把进入摄像机的光分为下面四个部分: 自发光 类似生活中的萤火虫等自己能够发光 高光反射 类似生活中的镜子 ...

  4. 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 & 纹理混合

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1117/120.html 作者:毛星云 ...

  5. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 & 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)  ...

  6. 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)  ...

  7. 【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 & 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)  ...

  8. [Unity3D]Shader编程之动态屏幕遮罩

    转载 https://blog.csdn.net/u012741077/article/details/78425834 屏幕可视范围跟随目标物体移动,可修改可视范围大小,边缘渐变大小.以及遮罩颜色, ...

  9. Unity3d之Shader编程:子着色器、通道与标签的写法 & 纹理混合

    一.子着色器 Unity中的每一个着色器都包含一个subshader的列表,当Unity需要显示一个网格时,它能发现使用的着色器,并提取第一个能运行在当前用户的显示卡上的子着色器. 我们知道,子着色器 ...

随机推荐

  1. ubuntu服务器全部署

    一.nginx+php+redis+phpredis 二.安装mysql 三.上传web文件 cd /var mkdir www cd www/ mkdir html cd html/ rz (apt ...

  2. linux使用crontab实现PHP执行计划定时任务

    linux使用crontab实现PHP执行计划定时任务 前几天写过一篇文章,利用单纯的php实现定时执行任务,但是效率不佳,对于linux来说用crontab实现更加合理 首先说说cron,它是一个l ...

  3. Python学会之后,一般能拿到多少工资?

    Python在约40年前出现以来,已经有数以千计基于这项技术的网站和软件项目,Python因其独有的特点从众多开发语言中脱颖而出,深受世界各地的开发者喜爱. 随着Python的技术的流行,Python ...

  4. 原来 JS 是这样的 - 关于 this

    引子 习惯了别的语言的思维习惯而不专门了解 JavaScript 的语言特性的话,难免踩到一些坑. 上一篇文章 中简单总结了关于 提升, 严格模式, 作用域 和 闭包 的几个常见问题,当然这仅仅是了解 ...

  5. 39页第3题 求x的n次幂

    /*计算x的n次幂*/ #include<stdio.h> main(void) { int i,n; double x,y; printf("Enter x:");/ ...

  6. 07.C语言:结构体、共用体、枚举

    一.结构体 是一种复合的数据类型,由多个不同类型的数据(为结构体的成员)组成的集合. 在c语言中没有给出结构体这种类型具体的形式(名称),但是给出类定义该结构体类型的方法(格式). 在使用结构体类型时 ...

  7. springcloud(十二):Ribbon客户端负载均衡介绍

    springcloud(十二):Ribbon客户端负载均衡介绍 Ribbon简介 使用分布式微服务脚骨的应用系统,在部署的时候通常会为部分或者全部微服务搭建集群环境,通过提供多个实例来提高系统的稳定型 ...

  8. ansible playbooks loop循环

    在一个task中循环某个操作 1.标准循环 - name: add several users user: name: "{{ item }}" state: present gr ...

  9. BNUOJ 17286 Dollars

    Dollars Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVA. Original ID: 1 ...

  10. [luoguP1373] 小a和uim之大逃离(DP)

    传送门 题解 代码 #include <cstdio> #include <iostream> #define N 802 #define mod 1000000007 int ...