# 前言
离正式辞职,已经过去半个多月了吧。这些天埋头苦干,自己的 “游戏” 基本功能算是完成得差不了,就目前而言,应该就还差场景、AI 以及剧情了。随着日子不断过去,心里似乎也变的有些焦虑了起来 —— 本来我以为自己是不会出现这样的心理的,不过一直待着吃老本,果然是越待越不淡定了。真想马上还是去把工作找了...... 不过想想,之前自己可貌似定下了 “雄心壮志” 一般的想法计划,怎么着,也得弄出个可玩的吧?
今天下午准备先画一下场景了,把该用的地形贴图都 assign 上去,然后画了几笔.... 我去,除了前四张贴图,该花的花,该黑的黑,Shader 上的 Texture Scale 也没用了... 虽然之前 “偷懒” 的时候就早已有了心理准备(Unity 的地形 Shader 具有 -base、-FirstPass、AddPass 三个组成的,之前我的那个地形 Shader,只有一份代码,就相当于只写了一个 FirstPass),虽然做其它功能的时候,就已经发现远处的贴图变成红色的了,不过那会儿也没在意。
但如今可不行了,若是只有前四张地形贴图可以用 Tripanar,又有何意义?于是没办法,怕麻烦也得继续该改了。
# 简介
关于介绍的 Triplanar 相关的就不多说了,上次的文章应该写了不少。
这次只是在前文的基础上,添加 AddPass Shader 用于处理超出 4 张地形贴图的情况,以及添加 base Shader 处理超出 Terrain base map dist 的情况。
关于 Base shader 好说,因为不必做出什么处理,用正常模型的算法都行 —— 因为太远了,能把贴图显示一下也就差不多了。或者直接使用 Unity 的 Base Shader 都可以,这儿我就直接使用 Unity 的了。
然后是 AddPass Shader.
地形的 AddPadd Shader 跟普通 Shader 的 AddPass 貌似功能上差不多,都是为了负责渲染前一个 Pass 没法渲染的东西 —— 比如普通 Shader 中额外处理点光源之类的。
所以,这个 Pass 的算法,基本上与前一个 Pass 保持一致,只是因为处理对象不同,会有那么一丢丢的改动。
# 效果
为了表示比较,再上一张使用内置的 Standard Terrain Shader 的效果吧:
# 代码
完整代码已上传至 Github,地址:https://github.com/CWHISME/Unity3D-Tripanar-Terrain-Shader
# Base
So,先看看最简单的 Base Shader 吧:
Shader "Hidden/TerrainEngine/Splatmap/TriplanarTerrain-Base" { | |
Properties { | |
_MainTex ("Base (RGB) Smoothness (A)", 2D) = "white" {} | |
_MetallicTex ("Metallic (R)", 2D) = "white" {} | |
// used in fallback on old cards | |
_Color ("Main Color", Color) = (1,1,1,1) | |
} | |
SubShader { | |
Tags { | |
"RenderType" = "Opaque" | |
"Queue" = "Geometry-100" | |
} | |
LOD 200 | |
CGPROGRAM | |
#pragma surface surf Standard fullforwardshadows | |
#pragma target 3.0 | |
// needs more than 8 texcoords | |
#pragma exclude_renderers gles | |
#include "UnityPBSLighting.cginc" | |
sampler2D _MainTex; | |
sampler2D _MetallicTex; | |
struct Input { | |
float2 uv_MainTex; | |
}; | |
void surf (Input IN, inout SurfaceOutputStandard o) { | |
half4 c = tex2D (_MainTex, IN.uv_MainTex); | |
o.Albedo = c.rgb; | |
o.Alpha = 1; | |
o.Smoothness = c.a; | |
o.Metallic = tex2D (_MetallicTex, IN.uv_MainTex).r; | |
} | |
ENDCG | |
} | |
FallBack "Diffuse" | |
} |
嘛.... 就是 Unity 的,而且很简单,跟普通 Shader 都差不多,没什么可解释的。
# FirstPass
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' | |
//2016.11.18 by cwhisme | |
//Note: 在基于 Unity Buildin Terrain Shader 的基础上修改 | |
//Unity 内置的地形 shader 可以在官方网站上进行下载 | |
// 加入了 Triplanar 计算,避免贴图拉伸问题 | |
//Updarte 2016.12.15 | |
// 替换部分内置代码,并添加对 AddPass 与 Base Shader 的引用 | |
// 以提供四张贴图以上的支持,及超出 Base Map Dis 之后贴图变红问题 | |
Shader "CWHISME/TriplannarTerrain" | |
{ | |
Properties{ | |
// set by terrain engine | |
[HideInInspector] _Control("Control (RGBA)", 2D) = "red" {} | |
[HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {} | |
[HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {} | |
[HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {} | |
[HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {} | |
[HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {} | |
[HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {} | |
[HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {} | |
[HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {} | |
[HideInInspector][Gamma] _Metallic0("Metallic 0", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic1("Metallic 1", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic2("Metallic 2", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic3("Metallic 3", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector] _Smoothness0("Smoothness 0", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness1("Smoothness 1", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness2("Smoothness 2", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness3("Smoothness 3", Range(0.0, 1.0)) = 1.0 | |
// used in fallback on old cards & base map | |
[HideInInspector] _MainTex("BaseMap (RGB)", 2D) = "white" {} | |
[HideInInspector] _Color("Main Color", Color) = (1,1,1,1) | |
_TextureScale("Texture Scale",float) = 100 | |
_TriplanarBlendSharpness("Triplanar Blend Sharpness",float) = 1 | |
} | |
SubShader{ | |
Tags{ | |
"SplatCount" = "10" | |
"Queue" = "Geometry-100" | |
"RenderType" = "Opaque" | |
} | |
CGPROGRAM | |
#pragma surface surf Standard vertex:vert finalcolor:SplatmapFinalColor finalprepass:SplatmapFinalPrepass finalgbuffer:SplatmapFinalGBuffer fullforwardshadows | |
#pragma multi_compile_fog | |
#pragma target 3.0 | |
// needs more than 8 texcoords | |
#pragma exclude_renderers gles | |
#include "UnityPBSLighting.cginc" | |
#pragma multi_compile __ _TERRAIN_NORMAL_MAP | |
#define TERRAIN_SURFACE_OUTPUT SurfaceOutputStandard | |
sampler2D _Control; | |
float4 _Control_ST; | |
sampler2D _Splat0, _Splat1, _Splat2, _Splat3; | |
half4 _Splat0_ST, _Splat1_ST, _Splat2_ST, _Splat3_ST; | |
#ifdef _TERRAIN_NORMAL_MAP | |
sampler2D _Normal0, _Normal1, _Normal2, _Normal3; | |
#endif | |
half _Metallic0; | |
half _Metallic1; | |
half _Metallic2; | |
half _Metallic3; | |
half _Smoothness0; | |
half _Smoothness1; | |
half _Smoothness2; | |
half _Smoothness3; | |
float _TriplanarBlendSharpness; | |
float _TextureScale; | |
struct Input | |
{ | |
float2 tc_Control : TEXCOORD4; | |
float3 wNormal; | |
float3 worldPos; | |
UNITY_FOG_COORDS(5) | |
}; | |
void vert(inout appdata_full v, out Input o) | |
{ | |
UNITY_INITIALIZE_OUTPUT(Input, o); | |
o.tc_Control = TRANSFORM_TEX(v.texcoord, _Control); | |
float4 pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
UNITY_TRANSFER_FOG(o, pos); | |
o.wNormal =normalize(mul(unity_ObjectToWorld, fixed4(v.normal, 0)).xyz); | |
#ifdef _TERRAIN_NORMAL_MAP | |
v.tangent.xyz = cross(v.normal, float3(0, 0, 1)); | |
v.tangent.w = -1; | |
#endif | |
} | |
void surf(Input IN, inout SurfaceOutputStandard o) { | |
half4 splat_control; | |
half weight; | |
fixed4 mixedDiffuse=0; | |
half4 defaultSmoothness = half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3); | |
//Custom begin=================================================<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
splat_control = tex2D(_Control, IN.tc_Control); | |
weight = dot(splat_control, half4(1, 1, 1, 1)); | |
splat_control /= (weight + 1e-3f); | |
//triplanar---------------<<<<<<<<<<<< | |
// 计算权重 | |
float3 N =normalize( IN.wNormal); | |
//N -= 0.4f; | |
half3 blendWeights = pow(abs(IN.wNormal), _TriplanarBlendSharpness); | |
blendWeights /= dot(blendWeights, 1.0); | |
half2 xUV = IN.worldPos.zy;// / _TextureScale; | |
half2 yUV = IN.worldPos.xz;// / _TextureScale; | |
half2 zUV = IN.worldPos.xy;// / _TextureScale; | |
// 通常 Triplanar 实现,只是多了三张贴图处理 | |
fixed4 tex0X = tex2D(_Splat0, (xUV*_Splat0_ST.xy + _Splat0_ST.zw)/ _TextureScale); | |
fixed4 tex0Y = tex2D(_Splat0, (yUV*_Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 tex0Z = tex2D(_Splat0, (zUV*_Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 tex1X = tex2D(_Splat1, (xUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex1Y = tex2D(_Splat1, (yUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex1Z = tex2D(_Splat1, (zUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex2X = tex2D(_Splat2, (xUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex2Y = tex2D(_Splat2, (yUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex2Z = tex2D(_Splat2, (zUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex3X = tex2D(_Splat3, (xUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex3Y = tex2D(_Splat3, (yUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex3Z = tex2D(_Splat3, (zUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex0 = tex0X*blendWeights.x + tex0Y * blendWeights.y + tex0Z * blendWeights.z; | |
fixed4 tex1 = tex1X*blendWeights.x + tex1Y * blendWeights.y + tex1Z * blendWeights.z; | |
fixed4 tex2 = tex2X*blendWeights.x + tex2Y * blendWeights.y + tex2Z * blendWeights.z; | |
fixed4 tex3 = tex3X*blendWeights.x + tex3Y * blendWeights.y + tex3Z * blendWeights.z; | |
// 融合权重,添加高光 | |
tex0 *= splat_control.r *half4(1.0, 1.0, 1.0, defaultSmoothness.r); | |
tex1 *= splat_control.g *half4(1.0, 1.0, 1.0, defaultSmoothness.g); | |
tex2 *= splat_control.b *half4(1.0, 1.0, 1.0, defaultSmoothness.b); | |
tex3 *= splat_control.a *half4(1.0, 1.0, 1.0, defaultSmoothness.a); | |
mixedDiffuse = tex0 + tex1 + tex2 + tex3; | |
//--------- 法线 ---------<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
#ifdef _TERRAIN_NORMAL_MAP | |
fixed4 nrm = 0.0f; | |
fixed4 nm0X = tex2D(_Normal0, (xUV* _Splat0_ST.xy + _Splat0_ST.zw)/ _TextureScale); | |
fixed4 nm0Y = tex2D(_Normal0, (yUV* _Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 nm0Z = tex2D(_Normal0, (zUV* _Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 nm1X = tex2D(_Normal1, (xUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm1Y = tex2D(_Normal1, (yUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm1Z = tex2D(_Normal1, (zUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm2X = tex2D(_Normal2, (xUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm2Y = tex2D(_Normal2, (yUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm2Z = tex2D(_Normal2, (zUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm3X = tex2D(_Normal3, (xUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm3Y = tex2D(_Normal3, (yUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm3Z = tex2D(_Normal3, (zUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm0 = nm0X*blendWeights.x +nm0Y * blendWeights.y + nm0Z * blendWeights.z; | |
fixed4 nm1 = nm1X*blendWeights.x + nm1Y * blendWeights.y + nm1Z * blendWeights.z; | |
fixed4 nm2 = nm2X*blendWeights.x + nm2Y * blendWeights.y + nm2Z * blendWeights.z; | |
fixed4 nm3 = nm3X*blendWeights.x + nm3Y * blendWeights.y + nm3Z * blendWeights.z; | |
nm0 *= splat_control.r; | |
nm1 *= splat_control.g; | |
nm2 *= splat_control.b; | |
nm3 *= splat_control.a; | |
nrm = nm0 + nm1 + nm2 + nm3; | |
o.Normal = UnpackNormal(nrm); | |
#endif | |
//End Custom=================================================<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
o.Albedo = mixedDiffuse.rgb;//max(fixed3(0.001, 0.001, 0.001), mixedDiffuse.rgb); | |
o.Alpha = weight; | |
o.Smoothness = mixedDiffuse.a; | |
o.Metallic = dot(splat_control, half4(_Metallic0, _Metallic1, _Metallic2, _Metallic3)); | |
} | |
void SplatmapFinalColor(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 color) | |
{ | |
color *= o.Alpha; | |
#ifdef TERRAIN_SPLAT_ADDPASS | |
UNITY_APPLY_FOG_COLOR(IN.fogCoord, color, fixed4(0, 0, 0, 0)); | |
#else | |
UNITY_APPLY_FOG(IN.fogCoord, color); | |
#endif | |
} | |
void SplatmapFinalPrepass(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 normalSpec) | |
{ | |
normalSpec *= o.Alpha; | |
} | |
void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission) | |
{ | |
UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha); | |
emission *= o.Alpha; | |
} | |
ENDCG | |
} | |
dependency "AddPassShader" = "Hidden/TerrainEngine/Splatmap/TriplanarTerrain-AddPass" | |
dependency "BaseMapShader" = "Hidden/TerrainEngine/Splatmap/TriplanarTerrain-Base" | |
Fallback "Nature/Terrain/Diffuse" | |
} |
解释都在代码最开头,就这样。
# AddPass
//2016.12.15 by cwhisme | |
// 在 FirstPass,即前一份代码基础上,处理超出四张地形贴图 | |
Shader "Hidden/TerrainEngine/Splatmap/TriplanarTerrain-AddPass" | |
{ | |
Properties{ | |
// set by terrain engine | |
[HideInInspector] _Control("Control (RGBA)", 2D) = "red" {} | |
[HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {} | |
[HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {} | |
[HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {} | |
[HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {} | |
[HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {} | |
[HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {} | |
[HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {} | |
[HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {} | |
[HideInInspector][Gamma] _Metallic0("Metallic 0", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic1("Metallic 1", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic2("Metallic 2", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector][Gamma] _Metallic3("Metallic 3", Range(0.0, 1.0)) = 0.0 | |
[HideInInspector] _Smoothness0("Smoothness 0", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness1("Smoothness 1", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness2("Smoothness 2", Range(0.0, 1.0)) = 1.0 | |
[HideInInspector] _Smoothness3("Smoothness 3", Range(0.0, 1.0)) = 1.0 | |
} | |
SubShader{ | |
Tags{ | |
"Queue" = "Geometry-99" | |
"IgnoreProjector" = "True" | |
"RenderType" = "Opaque" | |
} | |
CGPROGRAM | |
#pragma surface surf Standard decal:add vertex:vert finalcolor:SplatmapFinalColor finalgbuffer:SplatmapFinalGBuffer fullforwardshadows | |
#pragma multi_compile_fog | |
#pragma target 3.0 | |
// needs more than 8 texcoords | |
#pragma exclude_renderers gles | |
#include "UnityPBSLighting.cginc" | |
#pragma multi_compile __ _TERRAIN_NORMAL_MAP | |
#define TERRAIN_SPLAT_ADDPASS | |
#define TERRAIN_SURFACE_OUTPUT SurfaceOutputStandard | |
sampler2D _Control; | |
float4 _Control_ST; | |
sampler2D _Splat0, _Splat1, _Splat2, _Splat3; | |
half4 _Splat0_ST, _Splat1_ST, _Splat2_ST, _Splat3_ST; | |
#ifdef _TERRAIN_NORMAL_MAP | |
sampler2D _Normal0, _Normal1, _Normal2, _Normal3; | |
#endif | |
half _Metallic0; | |
half _Metallic1; | |
half _Metallic2; | |
half _Metallic3; | |
half _Smoothness0; | |
half _Smoothness1; | |
half _Smoothness2; | |
half _Smoothness3; | |
float _TriplanarBlendSharpness; | |
float _TextureScale; | |
struct Input | |
{ | |
float2 tc_Control : TEXCOORD4; | |
float3 wNormal; | |
float3 worldPos; | |
UNITY_FOG_COORDS(5) | |
}; | |
void vert(inout appdata_full v, out Input o) | |
{ | |
UNITY_INITIALIZE_OUTPUT(Input, o); | |
o.tc_Control = TRANSFORM_TEX(v.texcoord, _Control); | |
float4 pos = mul(UNITY_MATRIX_MVP, v.vertex); | |
UNITY_TRANSFER_FOG(o, pos); | |
o.wNormal =normalize(mul(unity_ObjectToWorld, fixed4(v.normal, 0)).xyz); | |
#ifdef _TERRAIN_NORMAL_MAP | |
v.tangent.xyz = cross(v.normal, float3(0, 0, 1)); | |
v.tangent.w = -1; | |
#endif | |
} | |
void surf(Input IN, inout SurfaceOutputStandard o) { | |
half4 splat_control; | |
half weight; | |
fixed4 mixedDiffuse=0; | |
half4 defaultSmoothness = half4(_Smoothness0, _Smoothness1, _Smoothness2, _Smoothness3); | |
//Custom begin=================================================<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
splat_control = tex2D(_Control, IN.tc_Control); | |
weight = dot(splat_control, half4(1, 1, 1, 1)); | |
#if !defined(SHADER_API_MOBILE) && defined(TERRAIN_SPLAT_ADDPASS) | |
clip(weight == 0.0f ? -1 : 1); | |
#endif | |
splat_control /= (weight + 1e-3f); | |
//triplanar---------------<<<<<<<<<<<< | |
// 计算权重 | |
float3 N =normalize( IN.wNormal); | |
//N -= 0.4f; | |
half3 blendWeights = pow(abs(IN.wNormal), _TriplanarBlendSharpness); | |
blendWeights /= dot(blendWeights, 1.0); | |
half2 xUV = IN.worldPos.zy;// / _TextureScale; | |
half2 yUV = IN.worldPos.xz;// / _TextureScale; | |
half2 zUV = IN.worldPos.xy;// / _TextureScale; | |
// 通常 Triplanar 实现,只是多了三张贴图处理 | |
fixed4 tex0X = tex2D(_Splat0, (xUV*_Splat0_ST.xy + _Splat0_ST.zw)/ _TextureScale); | |
fixed4 tex0Y = tex2D(_Splat0, (yUV*_Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 tex0Z = tex2D(_Splat0, (zUV*_Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 tex1X = tex2D(_Splat1, (xUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex1Y = tex2D(_Splat1, (yUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex1Z = tex2D(_Splat1, (zUV*_Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 tex2X = tex2D(_Splat2, (xUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex2Y = tex2D(_Splat2, (yUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex2Z = tex2D(_Splat2, (zUV*_Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 tex3X = tex2D(_Splat3, (xUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex3Y = tex2D(_Splat3, (yUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex3Z = tex2D(_Splat3, (zUV*_Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 tex0 = tex0X*blendWeights.x + tex0Y * blendWeights.y + tex0Z * blendWeights.z; | |
fixed4 tex1 = tex1X*blendWeights.x + tex1Y * blendWeights.y + tex1Z * blendWeights.z; | |
fixed4 tex2 = tex2X*blendWeights.x + tex2Y * blendWeights.y + tex2Z * blendWeights.z; | |
fixed4 tex3 = tex3X*blendWeights.x + tex3Y * blendWeights.y + tex3Z * blendWeights.z; | |
// 融合权重,添加高光 | |
tex0 *= splat_control.r *half4(1.0, 1.0, 1.0, defaultSmoothness.r); | |
tex1 *= splat_control.g *half4(1.0, 1.0, 1.0, defaultSmoothness.g); | |
tex2 *= splat_control.b *half4(1.0, 1.0, 1.0, defaultSmoothness.b); | |
tex3 *= splat_control.a *half4(1.0, 1.0, 1.0, defaultSmoothness.a); | |
mixedDiffuse = tex0 + tex1 + tex2 + tex3; | |
//--------- 法线 ---------<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
#ifdef _TERRAIN_NORMAL_MAP | |
fixed4 nrm = 0.0f; | |
fixed4 nm0X = tex2D(_Normal0, (xUV* _Splat0_ST.xy + _Splat0_ST.zw)/ _TextureScale); | |
fixed4 nm0Y = tex2D(_Normal0, (yUV* _Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 nm0Z = tex2D(_Normal0, (zUV* _Splat0_ST.xy + _Splat0_ST.zw) / _TextureScale); | |
fixed4 nm1X = tex2D(_Normal1, (xUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm1Y = tex2D(_Normal1, (yUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm1Z = tex2D(_Normal1, (zUV* _Splat1_ST.xy + _Splat1_ST.zw) / _TextureScale); | |
fixed4 nm2X = tex2D(_Normal2, (xUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm2Y = tex2D(_Normal2, (yUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm2Z = tex2D(_Normal2, (zUV* _Splat2_ST.xy + _Splat2_ST.zw)/ _TextureScale); | |
fixed4 nm3X = tex2D(_Normal3, (xUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm3Y = tex2D(_Normal3, (yUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm3Z = tex2D(_Normal3, (zUV* _Splat3_ST.xy + _Splat3_ST.zw)/ _TextureScale); | |
fixed4 nm0 = nm0X*blendWeights.x +nm0Y * blendWeights.y + nm0Z * blendWeights.z; | |
fixed4 nm1 = nm1X*blendWeights.x + nm1Y * blendWeights.y + nm1Z * blendWeights.z; | |
fixed4 nm2 = nm2X*blendWeights.x + nm2Y * blendWeights.y + nm2Z * blendWeights.z; | |
fixed4 nm3 = nm3X*blendWeights.x + nm3Y * blendWeights.y + nm3Z * blendWeights.z; | |
nm0 *= splat_control.r; | |
nm1 *= splat_control.g; | |
nm2 *= splat_control.b; | |
nm3 *= splat_control.a; | |
nrm = nm0 + nm1 + nm2 + nm3; | |
o.Normal = UnpackNormal(nrm); | |
#endif | |
//End Custom=================================================<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
o.Albedo = mixedDiffuse.rgb;//max(fixed3(0.001, 0.001, 0.001), mixedDiffuse.rgb); | |
o.Alpha = weight; | |
o.Smoothness = mixedDiffuse.a; | |
o.Metallic = dot(splat_control, half4(_Metallic0, _Metallic1, _Metallic2, _Metallic3)); | |
} | |
void SplatmapFinalColor(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 color) | |
{ | |
color *= o.Alpha; | |
#ifdef TERRAIN_SPLAT_ADDPASS | |
UNITY_APPLY_FOG_COLOR(IN.fogCoord, color, fixed4(0, 0, 0, 0)); | |
#else | |
UNITY_APPLY_FOG(IN.fogCoord, color); | |
#endif | |
} | |
void SplatmapFinalPrepass(Input IN, TERRAIN_SURFACE_OUTPUT o, inout fixed4 normalSpec) | |
{ | |
normalSpec *= o.Alpha; | |
} | |
void SplatmapFinalGBuffer(Input IN, TERRAIN_SURFACE_OUTPUT o, inout half4 outGBuffer0, inout half4 outGBuffer1, inout half4 outGBuffer2, inout half4 emission) | |
{ | |
UnityStandardDataApplyWeightToGbuffer(outGBuffer0, outGBuffer1, outGBuffer2, o.Alpha); | |
emission *= o.Alpha; | |
} | |
ENDCG | |
} | |
Fallback "Hidden/TerrainEngine/Splatmap/Diffuse-AddPass" | |
} |