KopMap/Assets/MindPowerSdk/Shaders/TerrainFunctions.hlsl
2025-04-03 02:30:16 +08:00

197 lines
7.8 KiB
HLSL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef TERRAIN_FUNCTIONS_INCLUDED
#define TERRAIN_FUNCTIONS_INCLUDED
#include "UnityCG.cginc"
// 如果需要使用 Texture2DArray 类型,请确保 Shader 目标版本支持(例如 5.0 以上)
// #pragma target 5.0
// 全局变量声明(在 Amplify Shader Editor 中可作为属性绑定使用)
// 主贴图图集2DArray
UNITY_DECLARE_TEX2DARRAY(_MainTex);
// 贴图编号贴图2D
sampler2D _TexNo;
// 遮罩编号贴图2D
sampler2D _MaskNo;
// 遮罩图集2DArray
UNITY_DECLARE_TEX2DARRAY(_MaskTex);
// 地形参数x 表示宽度z 表示高度y/w 可忽略)
float4 _TerrainSize;
// 纹理重复系数
float _Repeat;
// UV 偏移(防止采样边界问题)
float _UVOffsetX;
float _UVOffsetY;
// 采样时的 texel 尺寸(由 Unity 自动传入)
float4 _TexNo_TexelSize;
float4 _MaskNo_TexelSize;
////////////////////////////////////////////////////////////////////////////////
// 计算全局 UV根据世界坐标和地形尺寸
// worldPos.x 对应宽度方向worldPos.z 对应高度方向
float2 ComputeGlobalUV(float3 worldPos)
{
return float2(worldPos.x / (_TerrainSize.x + 1.0), worldPos.z / (_TerrainSize.z + 1.0));
}
////////////////////////////////////////////////////////////////////////////////
// 将从 _TexNo 中采样到的数值转换为图集层号064 内的整数)
int GetTexNo(float f)
{
return (int)round(f * 64.0);
}
////////////////////////////////////////////////////////////////////////////////
// 混合函数:从主图集中采样指定图层,并根据遮罩图集的采样结果进行混合
// (使用全局变量版本)
// @param color 当前颜色
// @param maskTexuv 用于遮罩图集采样的 UV
// @param mainTexuv 用于主图集采样的局部 UV
// @param mask 遮罩值(对应 _MaskNo 中的通道)
// @param layer 主图集的图层号
float4 Blend(float4 color, float2 maskTexuv, float2 mainTexuv, float mask, int layer)
{
float4 col2 = UNITY_SAMPLE_TEX2DARRAY(_MainTex, float3(mainTexuv, layer));
int idx = (int)round(mask * 16.0);
maskTexuv += float2(_UVOffsetX, _UVOffsetY);
float4 maskTexCol = UNITY_SAMPLE_TEX2DARRAY(_MaskTex, float3(maskTexuv, idx));
return lerp(color, col2, maskTexCol);
}
////////////////////////////////////////////////////////////////////////////////
// 调试用混合测试函数(返回遮罩图集采样结果)
// @param color 当前颜色(仅用于占位)
// @param uv 用于遮罩采样的 UV
// @param mask 遮罩值
// @param layer 贴图层号
float4 BlendTest(float4 color, float2 uv, float mask, int layer)
{
int idx = (int)round(mask * 16.0);
uv += float2(_UVOffsetX, _UVOffsetY);
return UNITY_SAMPLE_TEX2DARRAY(_MaskTex, float3(uv, idx));
}
////////////////////////////////////////////////////////////////////////////////
// 主混合函数(使用全局变量):根据 _TexNo 与 _MaskNo 中采样的编号和遮罩值混合出最终颜色
// @param globalUV 全局 UV例如由 ComputeGlobalUV 得来,用于 _TexNo 与 _MaskNo 采样)
// @param localUV 局部 UV例如每个 tile 内的局部坐标,用于主图集采样)
// @return 混合后的最终颜色
float4 TerrainBlend(float2 globalUV, float2 localUV)
{
// 调整 UV增加偏移以保证采样精度
float2 uvAdjusted = globalUV + float2(0, _TexNo_TexelSize.y);
float4 texNo = tex2D(_TexNo, uvAdjusted);
int layer1 = GetTexNo(texNo.r);
int layer2 = GetTexNo(texNo.g);
int layer3 = GetTexNo(texNo.b);
int layer4 = GetTexNo(texNo.a);
float4 maskNo = tex2D(_MaskNo, uvAdjusted);
// 局部 UVuv2 用于遮罩采样mainTextureUV2 用于主图集采样
float2 uv2 = frac(localUV * _Repeat);
float2 mainTextureUV2 = frac(localUV * (_Repeat / 4.0));
// 先采样第一层
float4 col = UNITY_SAMPLE_TEX2DARRAY(_MainTex, float3(mainTextureUV2, layer1));
if (layer2 > 0)
{
col = Blend(col, uv2, mainTextureUV2, maskNo.g, layer2);
}
if (layer3 > 0)
{
col = Blend(col, uv2, mainTextureUV2, maskNo.b, layer3);
}
if (layer4 > 0)
{
col = Blend(col, uv2, mainTextureUV2, maskNo.a, layer4);
}
return col;
}
////////////////////////////////////////////////////////////////////////////////
// 新的函数入口:提供所有参数(不依赖全局变量)
// 2DArray 类型参数采用 HLSL 原生类型 Texture2DArray + SamplerState需要 Shader Model 5.0 支持)
// @param globalUV 全局 UV 坐标(例如由世界坐标计算得到)
// @param localUV 局部 UV 坐标(例如 tile 内坐标)
// @param _MainTexParam 主贴图图集2DArray 贴图对象)
// @param _MainTexSamplerParam 主贴图采样状态
// @param _TexNoParam 贴图编号贴图2D 采样器)
// @param _MaskNoParam 遮罩编号贴图2D 采样器)
// @param _MaskTexParam 遮罩图集2DArray 贴图对象)
// @param _MaskTexSamplerParam 遮罩图集采样状态
// @param TerrainSizeParam 地形尺寸float4x为宽度z为高度
// @param RepeatParam 纹理重复系数
// @param UVOffsetXParam UV X轴偏移
// @param UVOffsetYParam UV Y轴偏移
// @param TexNo_TexelSizeParam _TexNo 贴图的 texel 尺寸float4
// @param MaskNo_TexelSizeParam _MaskNo 贴图的 texel 尺寸float4
// @return 最终混合后的颜色
float4 TerrainBlendFull(
float2 globalUV,
float2 localUV,
uniform Texture2DArray _MainTexParam,
uniform SamplerState _MainTexSamplerParam,
sampler2D _TexNoParam,
sampler2D _MaskNoParam,
uniform Texture2DArray _MaskTexParam,
uniform SamplerState _MaskTexSamplerParam,
float4 TerrainSizeParam,
float RepeatParam,
float UVOffsetXParam,
float UVOffsetYParam,
float4 TexNo_TexelSizeParam,
float4 MaskNo_TexelSizeParam
)
{
// 调整 UV 用于 _TexNo 与 _MaskNo 的采样
float2 uvAdjusted = globalUV + float2(0, TexNo_TexelSizeParam.y);
float4 texNo = tex2D(_TexNoParam, uvAdjusted);
int layer1 = (int)round(texNo.r * 64.0);
int layer2 = (int)round(texNo.g * 64.0);
int layer3 = (int)round(texNo.b * 64.0);
int layer4 = (int)round(texNo.a * 64.0);
float4 maskNo = tex2D(_MaskNoParam, uvAdjusted);
// 计算局部 UV用于主贴图与遮罩采样
float2 uv2 = frac(localUV * RepeatParam);
float2 mainTextureUV2 = frac(localUV * (RepeatParam / 4.0));
// 从主贴图图集中采样第一层
float4 col = _MainTexParam.Sample(_MainTexSamplerParam, float3(mainTextureUV2, layer1));
// 内联 Blend 逻辑(采用 .Sample() 方法)
if (layer2 > 0)
{
int idx = (int)round(maskNo.g * 16.0);
float2 maskUV = uv2 + float2(UVOffsetXParam, UVOffsetYParam);
float4 col2 = _MainTexParam.Sample(_MainTexSamplerParam, float3(mainTextureUV2, layer2));
float4 maskTexCol = _MaskTexParam.Sample(_MaskTexSamplerParam, float3(maskUV, idx));
col = lerp(col, col2, maskTexCol);
}
if (layer3 > 0)
{
int idx = (int)round(maskNo.b * 16.0);
float2 maskUV = uv2 + float2(UVOffsetXParam, UVOffsetYParam);
float4 col2 = _MainTexParam.Sample(_MainTexSamplerParam, float3(mainTextureUV2, layer3));
float4 maskTexCol = _MaskTexParam.Sample(_MaskTexSamplerParam, float3(maskUV, idx));
col = lerp(col, col2, maskTexCol);
}
if (layer4 > 0)
{
int idx = (int)round(maskNo.a * 16.0);
float2 maskUV = uv2 + float2(UVOffsetXParam, UVOffsetYParam);
float4 col2 = _MainTexParam.Sample(_MainTexSamplerParam, float3(mainTextureUV2, layer4));
float4 maskTexCol = _MaskTexParam.Sample(_MaskTexSamplerParam, float3(maskUV, idx));
col = lerp(col, col2, maskTexCol);
}
return col;
}
#endif // TERRAIN_FUNCTIONS_INCLUDED