Unity 5.1之前的版本,OpenGL ES2.0 、3.0、desktop OpenGL的渲染都是分别的版本。而5.1,unity使用统一的OpenGL Core,所以一些渲染的新功能DX和OpenGL都可以使用:
Tessellation Shader:细分曲面。GeometryShader:几何Shader。
Compute Shader:计算Shader。
(1)使用要求:
【Tessellation Shader/GeometryShader】
PC/Console:Shader Model 4.6+DX11/OpenGL Core
安卓平台:OpenGLES 3.1 +AEP(Android Extension Pack)
【Compute Shader】
PC/Console:DX11/OpenGLdesktop 4.3+
安卓平台:OpenGL ES 3.1+
(2)开启:
最好是在Player Settings里关掉Auto Graphics API.
做PC/Console的话
直接选择例如DX11即可
移动端的话
Computer Shader建议用Vulkan
Tessellation/Geometry建议用 OpenGLES3 + Require ES3.1 + AEP
简而言之,Instancing/Compute Shader/Tessellation Shader/GeometryShader
在电脑/家用机/移动端都可以运行(只要显卡支持)
下面用一张图说明这些Shader的关系。
本讲就来介绍Tessellation细分曲面。
当我们显示普通的模型时,效果一般,于是有了法线贴图。但是法线贴图有局限性,例如入视角。而DX11的
Tessellation是真正的生成更细致的mesh。一句话就是把模型的三角面细分成一组更小的面,再配合Displace贴图等信息进行处理。
Unity的Surface Shader支持Tessellation,例子如下
[例一:基本细分曲面]
步骤
1:准备Displacement和Normal 两张贴图。Displacement根据亮度决定细分曲面的高度或者说凸起程度。2:代码中添加
tessellate:tessFixed
float_Tess;
float4tessFixed()
{
return_Tess;
}
这个表示每个三角面细分的量级
3:对
Displacement进行纹理采样,并沿法线方向作相应偏移。voiddisp(inoutappdatav)
{
floatd=tex2Dlod(_DispTex,float4(v.texcoord.xy,0,0)).r*_Displacement;
v.vertex.xyz+=v.normal*d;
}
Shader"Tessellation/1FixedAmount"{
Properties{
_Tess("Tessellation",Range(1,32))=4
_MainTex("Base(RGB)",2D)="white"{}
_DispTex("DispTexture",2D)="gray"{}
_NormalMap("Normalmap",2D)="bump"{}
_Displacement("Displacement",Range(0,1.0))=0.3
_Color("Color",color)=(1,1,1,0)
_SpecColor("Speccolor",color)=(0.5,0.5,0.5,0.5)
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD300
CGPROGRAM
#pragmasurfacesurfBlinnPhongaddshadowfullforwardshadowsvertex:disptessellate:tessFixednolightmap
structappdata{
float4vertex:POSITION;
float4tangent:TANGENT;
float3normal:NORMAL;
float2texcoord:TEXCOORD0;
};
float_Tess;
float4tessFixed()
{
return_Tess;
}
sampler2D_DispTex;
float_Displacement;
voiddisp(inoutappdatav)
{
floatd=tex2Dlod(_DispTex,float4(v.texcoord.xy,0,0)).r*_Displacement;
v.vertex.xyz+=v.normal*d;
}
structInput{
float2uv_MainTex;
};
sampler2D_MainTex;
sampler2D_NormalMap;
fixed4_Color;
voidsurf(InputIN,inoutSurfaceOutputo){
half4c=tex2D(_MainTex,IN.uv_MainTex)*_Color;
o.Albedo=c.rgb;
o.Specular=0.2;
o.Gloss=1.0;
o.Normal=UnpackNormal(tex2D(_NormalMap,IN.uv_MainTex));
}
ENDCG
}
FallBack"Diffuse"
}
基于相机距离进行细分,离相机越近细分面数越多。
float4tessDistance(appdatav0,appdatav1,appdatav2){
floatminDist=10.0;
floatmaxDist=25.0;
returnUnityDistanceBasedTess(v0.vertex,v1.vertex,v2.vertex,minDist,maxDist,_Tess);
}
Shader"Tessellation/2Distance"{
Properties{
_Tess("Tessellation",Range(1,32))=4
_MainTex("Base(RGB)",2D)="white"{}
_DispTex("DispTexture",2D)="gray"{}
_NormalMap("Normalmap",2D)="bump"{}
_Displacement("Displacement",Range(0,1.0))=0.3
_Color("Color",color)=(1,1,1,0)
_SpecColor("Speccolor",color)=(0.5,0.5,0.5,0.5)
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD300
CGPROGRAM
#pragmasurfacesurfBlinnPhongaddshadowfullforwardshadowsvertex:disptessellate:tessDistancenolightmap
#include"Tessellation.cginc"
structappdata{
float4vertex:POSITION;
float4tangent:TANGENT;
float3normal:NORMAL;
float2texcoord:TEXCOORD0;
};
float_Tess;
float4tessDistance(appdatav0,appdatav1,appdatav2){
floatminDist=10.0;
floatmaxDist=25.0;
returnUnityDistanceBasedTess(v0.vertex,v1.vertex,v2.vertex,minDist,maxDist,_Tess);
}
sampler2D_DispTex;
float_Displacement;
voiddisp(inoutappdatav)
{
floatd=tex2Dlod(_DispTex,float4(v.texcoord.xy,0,0)).r*_Displacement;
v.vertex.xyz+=v.normal*d;
}
structInput{
float2uv_MainTex;
};
sampler2D_MainTex;
sampler2D_NormalMap;
fixed4_Color;
voidsurf(InputIN,inoutSurfaceOutputo){
half4c=tex2D(_MainTex,IN.uv_MainTex)*_Color;
o.Albedo=c.rgb;
o.Specular=0.2;
o.Gloss=1.0;
o.Normal=UnpackNormal(tex2D(_NormalMap,IN.uv_MainTex));
}
ENDCG
}
FallBack"Diffuse"
}
[例三:边缘长度曲面]
根据三角面的边缘长度进行细分,也就是越大的三角细分越多
float4tessEdge(appdatav0,appdatav1,appdatav2)
{
returnUnityEdgeLengthBasedTess(v0.vertex,v1.vertex,v2.vertex,_EdgeLength);
}
Shader"Tessellation/3EdgeLength"{
Properties{
_EdgeLength("Edgelength",Range(2,50))=15
_MainTex("Base(RGB)",2D)="white"{}
_DispTex("DispTexture",2D)="gray"{}
_NormalMap("Normalmap",2D)="bump"{}
_Displacement("Displacement",Range(0,1.0))=0.3
_Color("Color",color)=(1,1,1,0)
_SpecColor("Speccolor",color)=(0.5,0.5,0.5,0.5)
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD300
CGPROGRAM
#pragmasurfacesurfBlinnPhongaddshadowfullforwardshadowsvertex:disptessellate:tessEdgenolightmap
#include"Tessellation.cginc"
structappdata{
float4vertex:POSITION;
float4tangent:TANGENT;
float3normal:NORMAL;
float2texcoord:TEXCOORD0;
};
float_EdgeLength;
float4tessEdge(appdatav0,appdatav1,appdatav2)
{
returnUnityEdgeLengthBasedTess(v0.vertex,v1.vertex,v2.vertex,_EdgeLength);
}
sampler2D_DispTex;
float_Displacement;
voiddisp(inoutappdatav)
{
floatd=tex2Dlod(_DispTex,float4(v.texcoord.xy,0,0)).r*_Displacement;
v.vertex.xyz+=v.normal*d;
}
structInput{
float2uv_MainTex;
};
sampler2D_MainTex;
sampler2D_NormalMap;
fixed4_Color;
voidsurf(InputIN,inoutSurfaceOutputo){
half4c=tex2D(_MainTex,IN.uv_MainTex)*_Color;
o.Albedo=c.rgb;
o.Specular=0.2;
o.Gloss=1.0;
o.Normal=UnpackNormal(tex2D(_NormalMap,IN.uv_MainTex));
}
ENDCG
}
FallBack"Diffuse"
}
[例四:Phong细分曲面]
如果是low poly的模型的话,沿着法线方向去细分效果并不好。
而我们可以用Phong Tesselation去细分,该方法尤其适用于low poly模型。
tessphong:_Phong
#pragmasurfacesurfLambertvertex:dispNonetessellate:tessEdgetessphong:_Phongnolightmap
Shader"Tessellation/4Phong"{
Properties{
_EdgeLength("Edgelength",Range(2,50))=5
_Phong("PhongStrengh",Range(0,1))=0.5
_MainTex("Base(RGB)",2D)="white"{}
_Color("Color",color)=(1,1,1,0)
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD300
CGPROGRAM
#pragmasurfacesurfLambertvertex:dispNonetessellate:tessEdgetessphong:_Phongnolightmap
#include"Tessellation.cginc"
structappdata{
float4vertex:POSITION;
float3normal:NORMAL;
float2texcoord:TEXCOORD0;
};
voiddispNone(inoutappdatav){}
float_Phong;
float_EdgeLength;
float4tessEdge(appdatav0,appdatav1,appdatav2)
{
returnUnityEdgeLengthBasedTess(v0.vertex,v1.vertex,v2.vertex,_EdgeLength);
}
structInput{
float2uv_MainTex;
};
fixed4_Color;
sampler2D_MainTex;
voidsurf(InputIN,inoutSurfaceOutputo){
half4c=tex2D(_MainTex,IN.uv_MainTex)*_Color;
o.Albedo=c.rgb;
o.Alpha=c.a;
}
ENDCG
}
FallBack"Diffuse"
}