1.常见问题回答
问:
(1) TRANSFORM_TEX是做什么的
(2)float4 _MainTex_ST 中的_MainTex_ST变量也没有用到,为啥非要声明一下?
答:
(1)简单来说,TRANSFORM_TEX主要作用是拿顶点的uv去和材质球的tiling和offset作运算, 确保材质球里的缩放和偏移设置是正确的。 (v.texcoord就是顶点的uv)
下面这两个函数是等价的。
o.uv =
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
(2)而_MainTex_ST的ST是应该是SamplerTexture的意思 ,就是声明_MainTex是一张采样图,也就是会进行UV运算。 如果没有这句话,是不能进行TRANSFORM_TEX的运算的。_MainTex_ST.xy为 下图中的Tiling,zw为下图中的offset.
如果Tiling 和Offset你留的是默认值,即Tiling为(1,1) Offset为(0,0)的时候,可以不用
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
换成o.uv = v.texcoord.xy;也是能正常显示的;相当于Tiling 为(1,1)Offset为(0,0),但是如下图自己填的Tiling值和Offset值就不起作用了
2.Unity3d三种Shader对比
三种Shader共同点:
(1)都必须从唯一一个根Shader开始
(2)Properties参数部分,作用及语法完全相同
(3)具体功能都在SubShader里(Subshader: 子Shader,Shader会自上而下运行第一个硬件能支持的Subshader,主要作用是对不用硬件的支持。)
(4)都可以打标签,例如Tags { "RenderType" = "Opaque" } LOD 200 以及Lighting On等
(5)都可以Fallback
(6)都可以处理基本的功能,例如光照漫反射(Diffuse)以及镜面反射(Specular)。但是Vertex and Fragment和Surface都能实现Fixed function实现不了的高级功能,例如基于uv计算的效果等等。
三种Shader不同点:
(1)Fixed function shader以及Vertex and Fragment Shader在subshader下面还有pass{},但是SurfaceShader,由于已经将具体内容打包在光照模型了,不能加pass{},加了会报错。
(2)Fixed function shader每句代码之后没有分号';' 但是V&F shader以及Surface shader每句代码之后都必须加分号';'
(3)核心结构不同:
Fixed function shader的核心是
Material{} 以及 SetTexture[_MainTex]{}
Vertex and Fragment Shader的核心是
#pragma surface surf Lambert
ENDCG
或者(2)这套表示使用的是自己写的光照模型 lsyLightModel,并且使用了顶点处理函数vert
CGPROGRAM
// surface 表面处理函数 光照模型函数 顶点处理:函数
#pragma surface surf lsyLightModel vertex:vert
//执行顺序 顶点处理函数 -> 表面处理函数 -> 光照模型函数 ->颜色值
ENDCG
(1)都必须从唯一一个根Shader开始
(2)Properties参数部分,作用及语法完全相同
(3)具体功能都在SubShader里(Subshader: 子Shader,Shader会自上而下运行第一个硬件能支持的Subshader,主要作用是对不用硬件的支持。)
(4)都可以打标签,例如Tags { "RenderType" = "Opaque" }
(5)都可以Fallback
(6)都可以处理基本的功能,例如光照漫反射(Diffuse)以及镜面反射(Specular)。但是Vertex and Fragment和Surface都能实现Fixed function实现不了的高级功能,例如基于uv计算的效果等等。
三种Shader不同点:
(1)Fixed function shader以及Vertex and Fragment Shader在subshader下面还有pass{},但是SurfaceShader,由于已经将具体内容打包在光照模型了,不能加pass{},加了会报错。
(2)Fixed function shader每句代码之后没有分号';'
(3)核心结构不同:
Fixed function shader的核心是
Material{} 以及 SetTexture[_MainTex]{}
Vertex and Fragment Shader的核心是
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- ENDCG
appdata_base v ---> 结构体
- struct v2f {
-
float4 pos : SV_POSITION; -
float2 uv : TEXCOORD0; - } ;
- v2f vert (appdata_base v)
- {
-
v2f o; -
o.pos = mul(UNITY_MATRIX_MVP,v.vertex); - o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
-
return o; - }
- float4 frag (v2f i) : COLOR
- {
- float4 texCol = tex2D(_MainTex,i.uv);
-
float4 outp = texCol; -
return outp; - }
Surface Shader的核心是
(1)这套用的是Unity3d自带光照模型Lambert,也不做顶点处理,那么只需要一个表面处理函数surf即可
CGPROGRAM#pragma surface surf Lambert
ENDCG
或者(2)这套表示使用的是自己写的光照模型 lsyLightModel,并且使用了顶点处理函数vert
CGPROGRAM
//
#pragma surface
//执行顺序
ENDCG
- struct Input {
- float2 uv_MainTex;
- } ;
- 结构体--->SurfaceOutput o
- void surf (Input IN, inout SurfaceOutput o) {
- half4 c = tex2D (_MainTex, IN.uv_MainTex);
- o.Albedo = c.rgb;
- o.Alpha = c.a;
- }
3. 实现的一些效果
纹理的坐标
TexGen主要用于Fixed Function Shader. 有如下模式ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal .
- v2f
vert (appdata_base v) -
{ -
v2f o; -
o.pos = mul(UNITY_MATRIX_MVP,v.vertex); -
o.uv = v.vertex.xy; -
return o; -
}
- v2f
vert (appdata_base v) -
{ -
v2f o; -
o.pos = mul(UNITY_MATRIX_MVP,v.vertex); -
o.uv =mul(UNITY_MATRIX_MV,v.vertex); -
return o; -
}
4.流水线图形
坐标系的变换---->顶点变换后被着色的顶点--->图元装配---->光栅化(插值、着色)--->光栅化操作
5.
Render Path详细讲解
Vertex Lit:顶点光照
Forward Lighting:像素光照 阴影,法线贴图,light cookies
Deferred Lighting:不支持移动设备
6.alpha test alpha blend
Blend Off 不混合
Blend SrcFactor DstFactor SrcFactor是源系数,DstFactor是目标系数
最终颜色 = (Shader计算出的点颜色值 * 源系数)+(点累积颜色 * 目标系数)
Blend SrcAlpha zero:仅仅显示贴图,贴图含Alpha透明通道处理。但是贴图中的透明部分,即下图黑色部分没有颜色来显示,因为源颜色乘以alpha值0,为0;而混合目标的颜色乘以zero 0,也是0。所以透明部分显示的颜色为(0,0,0)
最终颜色 = 源颜色 * 源透明值 + 目标颜色*(1 - 源透明值)
最常用的透明混合方式。贴图alpha值高的部分,显示得实,而混合的背景很淡。而alpha值低的部分,贴图显示得淡,而背景现实得实。
7.
简而言之, Lambert是漫反射,BlinnPhong含镜面反射。
8.
Heightmap 灰度图 RGB位图 RGBA位图
Heightmap可以用3D软件(Unity的地形也可以)来绘制,或者Photoshop里的插件。
Unity自带的Shader是没有直接使用灰度图的,而提供能是灰度图转法线贴图的功能。原理是法线对光的反射很重要,用高度计算法线
Grabpass
(1)GrabPass{} 抓取当前屏幕内容,每次使用的开销都非常昂贵。 texture用_GrabTexture获取(2)GrabPass{"TextureName"}将抓取屏幕内容并保存至一张texture里。每帧只为第一次使用这张纹理的物体做一次,这种更高效
Blur模糊
UV的偏移(取4个)及alpha blend