// Blending with reconstructed terrain fragments
#include "UnityCG.cginc"
float BlendStart;
float BlendEnd;
sampler2D_float TerrainHeightmapTexture;
sampler2D_float TerrainNormalTexture;
sampler2D TerrainAlphaMap;
float4 HeightmapScale;
float4 TerrainSize;
float4 TerrainPos;
Float4 TerrainLightmap_ST;
UNITY_DECLARE_TEX2D(TerrainSplatMap0);
UNITY_DECLARE_TEX2D_NOSAMPLER(TerrainNormalMap0);
half4 TerrainSplatMap0_ST;
UNITY_DECLARE_TEX2D(TerrainSplatMap1);
UNITY_DECLARE_TEX2D_NOSAMPLER(TerrainNormalMap1);
half4 TerrainSplatMap1_ST;
UNITY_DECLARE_TEX2D(TerrainSplatMap2);
UNITY_DECLARE_TEX2D_NOSAMPLER(TerrainNormalMap2);
half4 TerrainSplatMap2_ST;
UNITY_DECLARE_TEX2D(TerrainSplatMap3);
UNITY_DECLARE_TEX2D_NOSAMPLER(TerrainNormalMap3);
half4 TerrainSplatMap3_ST;
struct v2f
{
// ...
float3 worldPos : TEXCOORD0;
float2 heightMapUV : TEXCOORD1;
#if defined(LIGHTMAP_ON)
float2 modelLightMapUV : TEXCOORD2;
float2 terrainLightMapUV : TEXCOORD3;
#endif
// ...
};
v2f vert(appdata v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f,o);
// ...
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.heightMapUV = TerrainUV(o.worldPos);
#if defined(LIGHTMAP_ON)
o.modelLightMapUV = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
o.terrainLightMapUV = o.heightMapUV * TerrainLightmap_ST.xy + TerrainLightmap_ST.zw;
#endif
// ...
return o;
}
half3 TerrainNormal(float2 terrainUV)
{
return tex2Dlod( TerrainNormalTexture, float4(terrainUV,0,0) ).xyz * 2.0 - 1.0;
}
half4 TerrainSplatMap(float2 uv0, float2 uv1, float2 uv2, float2 uv3, half4 control)
{
half4 splat0 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainSplatMap0, TerrainSplatMap0, uv0);
half4 splat1 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainSplatMap1, TerrainSplatMap1, uv1);
half4 splat2 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainSplatMap2, TerrainSplatMap2, uv2);
half4 splat3 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainSplatMap3, TerrainSplatMap3, uv3);
half4 result = splat0 * control.r +
splat1 * control.g +
splat2 * control.b +
splat3 * control.a;
return result;
}
half3 TerrainNormalMap(float2 uv0, float2 uv1, float2 uv2, float2 uv3, half4 control)
{
half4 n0 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainNormalMap0, TerrainSplatMap0, uv0);
half4 n1 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainNormalMap1, TerrainSplatMap1, uv1);
half4 n2 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainNormalMap2, TerrainSplatMap2, uv2);
half4 n3 = UNITY_SAMPLE_TEX2D_SAMPLER(TerrainNormalMap3, TerrainSplatMap3, uv3);
half3 result = UnpackNormalWithScale(n0, 1.0) * control.r +
UnpackNormalWithScale(n1, 1.0) * control.g +
UnpackNormalWithScale(n2, 1.0) * control.b +
UnpackNormalWithScale(n3, 1.0) * control.a;
result.z += 1e-5;
return result;
}
half3 TerrainLightmap(float2 uv, half3 normal)
{
#if defined(LIGHTMAP_ON)
#if defined(DIRLIGHTMAP_COMBINED)
half4 lm = UNITY_SAMPLE_TEX2D(unity_Lightmap, uv);
half4 lmd = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, uv);
half3 result = DecodeLightmapRGBM(lm, unity_Lightmap_HDR);
result = DecodeDirectionalLightmap(result, lmd, normal);
#else
half4 lm = UNITY_SAMPLE_TEX2D(unity_Lightmap, uv);
half3 result = DecodeLightmapRGBM(lm, unity_Lightmap_HDR);
#endif
#else
half3 result = UNITY_LIGHTMODEL_AMBIENT.rgb;
#endif
return result;
}
fixed4 frag(v2f i) : COLOR
{
fixed4 result = 0;
// ...
// compute model color and put it to the result
// ...
// reconstruction of terrain fragment
float2 splatUV0 = TRANSFORM_TEX(i.heightMapUV, TerrainSplatMap0);
float2 splatUV1 = TRANSFORM_TEX(i.heightMapUV, TerrainSplatMap1);
float2 splatUV2 = TRANSFORM_TEX(i.heightMapUV, TerrainSplatMap2);
float2 splatUV3 = TRANSFORM_TEX(i.heightMapUV, TerrainSplatMap3);
half4 control = tex2D(_TerrainAlphaMap, i.heightMapUV);
half4 terrainColor = TerrainSplatMap(splatUV0, splatUV1, splatUV2, splatUV3, control);
half3 terrainSurfaceNormal = TerrainNormal(i.heightMapUV);
half3 terrainSurfaceTangent = cross(terrainSurfaceNormal, float3(0,0,1));
half3 terrainSurfaceBitangent = cross(terrainSurfaceTangent, terrainSurfaceNormal);
half3 terrainNormal = TerrainNormalMap(splatUV0, splatUV1, splatUV2, splatUV3, control);
terrainNormal = terrainNormal.x * terrainSurfaceTangent +
terrainNormal.y * terrainSurfaceBitangent +
terrainNormal.z * terrainSurfaceNormal;
half3 terrainLightmapColor = TerrainLightmap(i.heightMapUV, terrainNormal);
terrainColor *= terrainLightmapColor;
// blend model color & terrain color
half height = TerrainHeight(i.heightMapUV);
half deltaHeight = i.worldPos.y - height;
half blendingWeight = smoothstep(BlendStart, BlendEnd, deltaHeight);
result.rgb = lerp(result.rgb, terrainColor, blendingFactor);
return result;
}