纹理映射技术就是把一张图粘贴在模形的表面上
(一)用一张纹理来代替物体的漫反射颜色
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders Book/Chapter 6/Blinn-Phong" {
Properties {
_Color ("Color Tint ",Color) = (1,1,1,1)
_MainTex ("Main Tex",2D) = "white"{}//2D 是纹理属性
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader {
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 Color;
sampler2D _MainTex;
float4 _MainTex_ST;//纹理名_ST方式声明某个纹理的属性 _MainTex_ST.xy 存储的是缩放值,_MainTex_ST.zw存储的是偏移值
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;//将第一组纹理坐标存储在这个变量中
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;// 存储纹理的坐标
};
v2f vert(a2v v) {
v2f o;
// Transform the vertex from object space to projection space
o.pos = UnityObjectToClipPos(v.vertex);
// Transform the normal from object space to world space
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
// Transform the vertex from object spacet to world space
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//或者用o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);进行纹理坐标变换
return o;
}
fixed4 frag(v2f i) : SV_Target {
// Get ambient term
fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb;
//tex2D 用来对纹理进行采样,第一个参数_MainTex为纹理,i.uv为该点的纹素值,
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// Compute diffuse term
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));
// Get the view direction in world space
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
// Get the half direction in world space
fixed3 halfDir = normalize(worldLightDir + viewDir);
// Compute specular term
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
纹理的类型:Texture, Normal map, Cubemap等
Alpha from Grayscale:设置透明通道的
Wrap Mode:可以设置为Repeat ,也可以设置为Tiling平铺
Filter Mode :滤波,Point Bilinear Trilinear三种,滤波效果一次提升,耗费也会变大
多级渐远纹理:提前用滤波技术得到很多小的图像,形成一个金字塔形,每一层都是对上一层采样的结果。当摄像机距离较远时,会使用小的纹理。这种技术会占用很多内存,以空间换取时间。
Advance类型的纹理,可以设置 Generate Mip Maps多级渐远纹理
导入的纹理可以是非正方形的,但是长宽的大小应该是2的幂,例如2,4,8等。如果非2的幂,会占用更多的内存空间,GPU读取纹理的速度也会下降。
Format决定了压缩的格式
(二)凹凸映射
凹凸映射目的是用一张纹理来修改模型表面的法线,为模型提供更多的细节。基本思想是通过改变表面法线,而不是使用纹理来改变光照方程中的颜色分量
实现凹凸映射有两种方法:
高度映射:利用高度纹理来模拟表面位移,得到一个修改后的法线值。
法线映射:使用一张法线纹理来直接存储表面法线,这种方法为法线映射。
1.高度纹理:用一张高度图来实现,主要是颜色不同,浅色表明向外凸起,深色为凹陷
2.法线纹理:法线纹理存储的就是表面的法线方向,由于法线的方向分量范围在[-1,1],而像素的分量范围在[0,1],需要做一个映射。
pixel = (normal+1)/2 normal = pixel * 2 -1
模型空间中的表面法线存储在一张纹理中,为模型空间法线纹理。实际应用中常用模型顶点的切线空间来存储法线,称为切线空间的法线纹理。
(1)切线空间下光照模型
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders Book/Chapter 7/Normal Map In Tangent Space" {
Properties {
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) = "white" {}
_BumpMap ("Normal Map", 2D) = "bump" {}//bump是Unity自带法线纹理,没有提供任何法线纹理时。表示对应了模型自带的法线纹理
_BumpScale ("Bump Scale", Float) = 1.0//控制凹凸程度的
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader {
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float4 _BumpMap_ST;
float _BumpScale;
fixed4 _Specular;