Unity Shader:三向贴图(Tri-planar mapping)---解决地形拉伸贴图变形以及贴图边缘的缝隙问题
来源:互联网 发布:mac设置自动关机 编辑:程序博客网 时间:2024/05/22 14:05
效果图:
效果图1,地形:左边为三向贴图效果,右边为一般贴图效果。
效果图2,树干:右边为三向贴图效果,左边为一般贴图效果。
效果图3,球体:左边为三向贴图效果,右边为一般贴图效果。
1,世界坐标贴图 World Space UV-mapping
在一般的贴图方法中,在片段着色器内使用tex2D(texture,uv);对2D材质进行采样时,片段着色器将会根据顶点着色器将会传入的顶点UV值插值出当前像素点的uv值。在World Space UV-mapping中,uv值使用当前像素的世界坐标,tex2D(texture,worldPos_xy);。由于uv值只可以取0-1,因此一般面积大于1的2D平面会出现一种repeat的效果,可以将uv值除以一个变量进行缩放,tex2D(texture,worldPos_xy/textureScale);。这种贴图方法的优势是物体向xy平面方向放大时贴图不会出现拉伸,缺点时当物体移动或旋转时,贴图不会随着物体移动,而是根据新的坐标重新进行材质采样。
效果图4:平面以worldPos_xz进行tex2D()
2,三向贴图 Triplanar Mapping
以世界坐标贴图方法为基础,将像素的世界坐标(x,y,z)取值为三组UV,xy,xz,yz;根据三组UV值分别对材质进行采样, 然后根据法线方形对采样的颜色进行混合。这样当像素的法线面向y轴时,它会显示由xz采样的颜色,当面向x轴时,将会显示yz采样的颜色,在面向xy轴45度夹角时将会显示由xz,yz采样出的颜色的混合颜色。以此种方式对物体所有非平滑处进行混合过渡。对不规则复杂形状物体,如地形,树木用此方式贴图视觉效果更好。缺点是计算量相对普通贴图要更大。
3,代码
surface shader:
Shader "TriplanarTutorial/Triplanar_Final" { Properties { _DiffuseMap ("Diffuse Map ", 2D) = "white" {} _TextureScale ("Texture Scale",float) = 1 _TriplanarBlendSharpness ("Blend Sharpness",float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma target 3.0 #pragma surface surf Lambert sampler2D _DiffuseMap; float _TextureScale; float _TriplanarBlendSharpness; struct Input { float3 worldPos; float3 worldNormal; }; void surf (Input IN, inout SurfaceOutput o) { // Find our UVs for each axis based on world position of the fragment. half2 yUV = IN.worldPos.xz / _TextureScale; half2 xUV = IN.worldPos.zy / _TextureScale; half2 zUV = IN.worldPos.xy / _TextureScale; // Now do texture samples from our diffuse map with each of the 3 UV set's we've just made. half3 yDiff = tex2D (_DiffuseMap, yUV); half3 xDiff = tex2D (_DiffuseMap, xUV); half3 zDiff = tex2D (_DiffuseMap, zUV); // Get the absolute value of the world normal. // Put the blend weights to the power of BlendSharpness, the higher the value, // the sharper the transition between the planar maps will be. half3 blendWeights = pow (abs(IN.worldNormal), _TriplanarBlendSharpness); // Divide our blend mask by the sum of it's components, this will make x+y+z=1 blendWeights = blendWeights / (blendWeights.x + blendWeights.y + blendWeights.z); // Finally, blend together all three samples based on the blend mask. o.Albedo = xDiff * blendWeights.x + yDiff * blendWeights.y + zDiff * blendWeights.z; } ENDCG }}
vertex shader:
Shader "Unlit/Tri-Planar"{ Properties { _DiffuseMap ("Diffuse Map ", 2D) = "white" {} _TextureScale ("Texture Scale",float) = 1 _TriplanarBlendSharpness ("Blend Sharpness",float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal:NORMAL; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; float3 normal:NORMAL; float4 w_Vertex : FLOAT; }; float _TextureScale; sampler2D _DiffuseMap; float4 _MainTex_ST; float _TriplanarBlendSharpness; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); o.normal=mul(unity_ObjectToWorld,v.normal); o.w_Vertex=mul(unity_ObjectToWorld,v.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture float3 blending=abs(i.normal); blending=normalize(pow(blending,_TriplanarBlendSharpness)); float b=(blending.x+blending.y+blending.z); blending/=float3(b,b,b); float4 xaxis=tex2D(_DiffuseMap,i.w_Vertex.yz/_TextureScale); float4 yaxis=tex2D(_DiffuseMap,i.w_Vertex.xz/_TextureScale); float4 zaxis=tex2D(_DiffuseMap,i.w_Vertex.xy/_TextureScale); fixed4 tex=xaxis*blending.x+yaxis*blending.y+zaxis*blending.z; // fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, tex); return tex; } ENDCG } }}
参考:
Use Tri-Planar Texture Mapping for Better Terrain –Brent Owens
https://gamedevelopment.tutsplus.com/articles/use-tri-planar-texture-mapping-for-better-terrain–gamedev-13821
Triplanar Mapping –MARTIN PALKO
http://www.martinpalko.com/triplanar-mapping/
———————————————————————————
维护日志:
2017-9-20:将“三平面式”改为“三向式”
- Unity Shader:三向贴图(Tri-planar mapping)---解决地形拉伸贴图变形以及贴图边缘的缝隙问题
- unity shader 贴图流动
- shaderforge 贴图重定位 贴图clamp边缘的问题。
- Unity Shader 什么是法线贴图
- Duilib库中的点九图使用(解决控件贴图拉伸圆角变形问题等)
- vision引擎中环境地形 - 三向贴图介绍
- surface Shader——主贴图、法线贴图、边缘颜色
- Unity 解决 动态设置Lightmap 贴图会歪的问题
- 贴图
- 贴图
- 贴图
- 贴图
- 贴图
- 贴图
- 贴图
- 在unity内置的地形中使用凹凸贴图
- Unity 法线贴图、高光贴图、Cube Map shader
- 解决unity5 地形 从assetbundle载入后,贴图分辨率不正常的问题
- 文字如何与单选框垂直对齐
- 关于plist文件存储方式(swift)
- V4L2 获取和配置摄像头程序示例(使用v4l2_queryctrl )
- 探索skynet(二):skynet如何启动一个服务
- Spring Security(07)——缓存UserDetails
- Unity Shader:三向贴图(Tri-planar mapping)---解决地形拉伸贴图变形以及贴图边缘的缝隙问题
- git删除远程分支文件
- 在ARM实验板LCD上显示汉字
- 安卓自定义饼状图
- [LeetCode] 104. Maximum Depth of Binary Tree
- Spring Security(08)——intercept-url配置
- Python并发速查表
- 初入Python
- 关于linux文件权限的介绍