前言:本篇博客只是一个简单的实现普通纹理和光照纹理采样功能的例子,主要是当做笔记使用。
核心要点:
1.我们可以对1~4维纹理对象进行采样。其中采样采样接口分别为tex1D,tex2D,tex3D,texCUBE。采样对象类型分别为:sampler,sampler2D,sampler3D,samplerCUBE。采样坐标分别是x,xy,xyz,xyzw。其中光照纹理采样的最终颜色还要使用DecodeLightmap函数来对tex系列函数获取的颜色进行处理后获取。
2.采样坐标是不是有效主要看纹理的展开模式的。如果展开模式为Repeat的话,纹理就会在上下左右所有方向平铺,这样采样坐标是一定存在且有效的。如果展开模式为Clamp的话,采样坐标范围就是纹理大小区间,当采样坐标超过纹理大小区间时,采样坐标就是无效的。如图所示:
3.采样坐标对应位置的像素是根据纹理过滤模式来获取的。当过滤模式为Point的话,就会获取一个就近的整数像素值。当过滤模式为Bilinear的话,就会获取周围像素按照权重累加的像素值。如图所示:
4.采样坐标等于纹理原始采样坐标乘以平铺缩放系数再加上偏移系数。如果采样坐标可以对应到纹理上时,就会得到一个有效的像素,否则就会得到一个无效未知的像素。
5.光照纹理采样对象(unity_Lightmap)和采样系数(unity_LightmapST)都是unity自动传入的。普通纹理的采样系数(纹理对象变量名_ST)也是是unity自动传入的。采样系数变量中的xy代表平铺缩放系数,zw代表平移系数。
光照贴图制作流程:
1.构建光照贴图场景:
1>.新建一个cube作为平面,参数设置如图所示:
2>.新建一个cube和一个sphere,用来接收光照,参数设置如图所示:
3>.新建一个点光源来照射物体,并将颜色设置为亮色,启动烘焙。参数设置如图所示:
4>.将原先方向光设置成暖色,启动烘焙。参数设置如图所示:
5>.跳转摄像机位置,让摄像机看的平面向上一些。参数设置如图所示:
2.打开光照贴图制作工具(window->lighting),在Scene页签中将环境光也设置成烘焙模式。如图所示:
然后在Lightmaps页签中选择build来构建光照贴图。参数设置如图所示:
生成的光照纹理如图所示:
核心代码:如下所示:
// Upgrade NOTE: replaced tex2D unity_Lightmap with UNITY_SAMPLE_TEX2D
// Upgrade NOTE: commented out 'float4 unity_LightmapST', a built-in variable
// Upgrade NOTE: commented out 'sampler2D unity_Lightmap', a built-in variable
Shader "Custom/sample" {
Properties {
// 2d纹理,内部包含纹理贴图以及采样平铺和偏移系数
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f {
// 模型世界空间坐标
float4 pos:POSITION0;
// 2d纹理采样坐标
float2 uv_2d:TEXCOORD0;
// 光照纹理采样坐标
float2 uv_lm:TEXCOORD1;
};
// 2d纹理对象
sampler2D _MainTex;
// 2d纹理对象的采样系数,unity自动传入,其中xy分量代表平铺系数,zw、分量代表偏移系数
float4 _MainTex_ST;
// 2d光照纹理对象
sampler2D unity_Lightmap;
// 2d光照纹理对象采样系数,unity自动传入,其中xy分量代表平铺系数,zw、分量代表偏移系数
float4 unity_LightmapST;
v2f vert(appdata_full v)
{
v2f o;
// 将模型空间顶点坐标转换到世界空间中
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
// 获取2d纹理对象采样坐标:模型采样坐标乘以平铺系数再加上偏移系数
o.uv_2d = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
// 获取2d光照纹理对象采样坐标:模型采样坐标乘以平铺系数再加上偏移系数
o.uv_lm = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
return o;
}
fixed4 frag(v2f v):COLOR0
{
// 对2d纹理对象进行采样:采样坐标对应像素不存在就获取未知像素,否则如果纹理采用Point模式就会取采样坐标
// 位置对应的整数像素,如果纹理采用Bilinear模式就会取采样坐标附近像素按照权重累加的像素值
fixed4 col_2d = tex2D(_MainTex, v.uv_2d);
// 对2d光照纹理进行采样
fixed3 col_lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, v.uv_lm));
// 返回采样混合色
return fixed4(col_2d.rgb * col_lm, col_2d.a);
}
ENDCG
}
}
}
运行效果:将上面的shader代码对应材质拖到场景上具有光照纹理的对象上。效果如下图所示: