Shader第二十六讲 Tessellation

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

Shader第二十六讲 Tessellation_第1张图片

简而言之,Instancing/Compute Shader/Tessellation Shader/GeometryShader

在电脑/家用机/移动端都可以运行(只要显卡支持)

下面用一张图说明这些Shader的关系。

Shader第二十六讲 Tessellation_第2张图片

本讲就来介绍Tessellation细分曲面。

当我们显示普通的模型时,效果一般,于是有了法线贴图。但是法线贴图有局限性,例如入视角。而DX11的

Tessellation是真正的生成更细致的mesh。一句话就是把模型的三角面细分成一组更小的面,再配合Displace贴图等信息进行处理。

Unity的Surface Shader支持Tessellation,例子如下

Shader第二十六讲 Tessellation_第3张图片

[例一:基本细分曲面]

Shader第二十六讲 Tessellation_第4张图片

步骤

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"

}

Shader第二十六讲 Tessellation_第5张图片
Shader第二十六讲 Tessellation_第6张图片
Shader第二十六讲 Tessellation_第7张图片

[例二:基于距离细分曲面]

Shader第二十六讲 Tessellation_第8张图片

基于相机距离进行细分,离相机越近细分面数越多。

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"

}

Shader第二十六讲 Tessellation_第9张图片

[例三:边缘长度曲面]

Shader第二十六讲 Tessellation_第10张图片

根据三角面的边缘长度进行细分,也就是越大的三角细分越多

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细分曲面]

Shader第二十六讲 Tessellation_第11张图片

如果是low poly的模型的话,沿着法线方向去细分效果并不好。

Shader第二十六讲 Tessellation_第12张图片
Shader第二十六讲 Tessellation_第13张图片

而我们可以用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"

}

Shader第二十六讲 Tessellation_第14张图片

你可能感兴趣的:(Shader第二十六讲 Tessellation)