Unity Shader 梯度噪声 vs 值噪声
▦值噪声Value Noise插值随机标量值生成速度快但有明显块状感和人工痕迹适合低端设备或不需要高视觉质量的大面积纹理。◈梯度噪声Perlin Noise基于随机梯度方向插值各向同性更均匀平滑自然无方向性伪像是程序化纹理的首选基础函数。◇Simplex 噪声Simplex Noise利用单形网格减少顶点数量3D 下性能优于 Perlin 50%无任何方向性伪像适合高质量实时渲染。核心原理对比值噪声 (Value Noise)值噪声是最基础的程序化噪声实现。在整数网格顶点上生成随机标量值然后通过双线性 Hermite 插值在顶点之间平滑过渡。这种方法计算极快但相邻采样点之间的过渡往往显得生硬产生明显的块状视觉感受。// 值噪声实现 // 步骤1: 定义 hash 函数 (sin-free) float hash12(vec2 p) { vec3 p3 fract(vec3(p.xyx) * 0.1031); p3 dot(p3, p3.yzx 33.33); return fract((p3.x p3.y) * p3.z); } // 步骤2: 双线性 Hermite 插值 float valueNoise(vec2 p) { // 取整与小数分离 vec2 i floor(p); vec2 f fract(p); // Hermite 平滑: f*f*(3-2f) f f * f * (3.0 - 2.0 * f); // 步骤3: 获取4个顶点随机值 float a hash12(i vec2(0.0, 0.0)); float b hash12(i vec2(1.0, 0.0)); float c hash12(i vec2(0.0, 1.0)); float d hash12(i vec2(1.0, 1.0)); // 步骤4: 双线性插值混合 return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); }梯度噪声 (Perlin Noise)Perlin 噪声在每个网格顶点定义一个随机梯度方向然后在晶格点之间使用梯度与位置向量的点积进行插值。这种方法确保了噪声在各方向上具有相同的统计特性各向同性避免了值噪声的块状感和方向性伪影。// Perlin 梯度噪声实现 // 梯度向量 hash vec2 hash22(vec2 p) { vec3 p3 fract(vec3(p.xyx) * vec3(.1031, .1030, .0973)); p3 dot(p3, p3.yzx 33.33); return -1.0 2.0 * fract((p3.xx p3.yz) * p3.zy); } float perlinNoise(vec2 p) { vec2 i floor(p); vec2 f fract(p); f f * f * (3.0 - 2.0 * f); // Hermite // 每个顶点存储随机梯度方向 vec2 g00 hash22(i vec2(0.0, 0.0)); vec2 g10 hash22(i vec2(1.0, 0.0)); vec2 g01 hash22(i vec2(0.0, 1.0)); vec2 g11 hash22(i vec2(1.0, 1.0)); // 计算到各顶点的梯度点积 float n00 dot(g00, f - vec2(0.0, 0.0)); float n10 dot(g10, f - vec2(1.0, 0.0)); float n01 dot(g01, f - vec2(0.0, 1.0)); float n11 dot(g11, f - vec2(1.0, 1.0)); // 插值 (输出范围 [-1, 1]) return 0.5 0.5 * mix( mix(n00, n10, f.x), mix(n01, n11, f.x), f.y); }Simplex 噪声Simplex 噪声是对 Perlin 噪声的改进使用单形simplex网格而非方形网格。在 2D 中使用三角形网格3D 中使用四面体网格。这使得每个采样点只需要 3-4 个周围顶点参与计算相比 Perlin 的 4-8 个顶点减少了计算量且完全消除了轴对齐的视觉伪像。// Simplex 噪声实现 // 2D: 使用三角形网格 (非方形) float simplexNoise(vec2 p) { const float K1 0.366025404; // (sqrt(3)-1)/2 const float K2 0.211324865; // (3-sqrt(3))/6 // 偏斜变换到单形网格 vec2 i floor(p (p.x p.y) * K1); vec2 a p - i (i.x i.y) * K2; // 确定下半三角形 vec2 o (a.x a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec2 b a - o K2; // 第二近顶点 vec2 c a - 1.0 2.0 * K2; // 对角顶点 // h^4 核函数权重 vec3 h max(0.5 - vec3( dot(a, a), dot(b, b), dot(c, c)), 0.0); h h * h * h * h; // 梯度点积加权求和 (仅3个顶点) vec3 n h * vec3( dot(a, hash22(i 0.0)), dot(b, hash22(i o)), dot(c, hash22(i 1.0)) ); return dot(n, vec3(70.0)) * 0.5 0.5; }性能与特性对比特性值噪声Perlin 噪声Simplex 噪声插值方式双线性 Hermite梯度点积 平滑插值单形网格 h4 核函数网格类型方形晶格方形晶格三角形/四面体晶格采样点数4 个顶点4 个顶点3 个顶点 (2D) / 4 个 (3D)2D 性能5/54/54/53D 性能5/53/55/5各向同性明显块状良好优秀方向伪影严重轻微轴对齐无Unity URP 适用地形大型基底程序化纹理高质量体积渲染Unity URP 应用场景选择指南根据需求匹配最佳噪声类型地形系统大型地形基底使用值噪声节省性能FBM 叠加 Perlin 增加细节层次☁体积云/雾3D Simplex 噪声提供最佳性能与视觉平衡避免体积渲染中的方向伪影火焰/熔岩Ridged FBM 结合 Perlin 梯度噪声生成锐利脊线模拟自然裂痕纹理URP 实践建议在 URP Shader 中使用噪声时优先考虑 Simplex 噪声处理 3D 数据体积、粒子2D 程序化纹理可使用 Perlin 噪声。对于超大规模地形等性能敏感场景值噪声FBM 组合仍是务实选择。URP Shader 示例URP ShaderLibrary 使用在 URP 的 ShaderLibrary 中已内置常用噪声函数可以直接引用// URP ShaderLibrary 使用 #include Packages/com.unity.render-pipelines.core/ ShaderLibrary/Common.hlsl // 内置噪声函数 float noise SAMPLE_TEXTURE2D( _NoiseTex, // 噪声纹理 sampler_NoiseTex, uv ).r; // 自定义实现 (推荐用于程序化需求) float3 PerlinNoise(float2 p, float2 offset) { return PBR.ProceduralCommons.PerlinNoise2D(p offset); } // Shader Graph 自定义节点 // 在 Shader Graph 中添加 Custom Function Node // 输出类型: Fragment // 函数名: PerlinFBM // 输入: UV (float2) // 输出: Out (float3) // Body: // float3 n PerlinNoise(uv * 4.0, float2(0.0)); // n 0.5 * PerlinNoise(uv * 8.0, float2(3.2)); // n 0.25 * PerlinNoise(uv * 16.0, float2(7.1)); // Out n * 0.5 0.5;常见误区很多开发者忽略了噪声的视觉差异直接导致最终质感下降。例如在角色皮肤纹理上使用值噪声会产生明显的塑料感而在地形远景使用 Simplex 则浪费了不必要的性能。根据不同距离和材质特性选择合适的噪声类型是提升视觉质量同时控制成本的关键。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2542976.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!