news 2026/2/27 15:01:49

【URP】Unity[视差贴图]模拟[风格化地形]实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【URP】Unity[视差贴图]模拟[风格化地形]实践

陡峭视差贴图(Steep Parallax Mapping)实现原理

陡峭视差贴图通过‌分层深度比较‌和‌动态UV偏移‌技术增强岩石表面立体感.

‌视角自适应分层采样‌

根据视线与表面法线的夹角动态分配采样层数(平视视角增加至12层,俯视视角减少至5层),解决标准视差贴图在平视角度下的失真问题

‌深度图梯度修正‌

引入_LayerBias参数(推荐值0.2-0.4)调整UV偏移量计算公式,避免陡峭区域出现采样断裂:

$\Delta UV=\frac{ParallaxScale \cdot ViewDir_{xy}}{(ViewDir_z+LayerBias) \cdot LayerCount}$

‌风格化深度增强‌

在最终插值阶段使用pow(weight,2)强化轮廓对比度,配合ramp贴图实现卡通化光影过渡效果

URP HLSL完整实现代码

关键特性说明

‌动态层数优化‌:通过lerp(_MaxLayers, _MinLayers, saturate(dot(float3(0,0,1), viewDirTS)))实现平视视角自动增加采样精度

‌抗失真处理‌:_LayerBias参数修正陡峭表面的UV偏移计算,避免采样断裂

‌风格化增强‌:ramp贴图控制光影过渡,边缘光强化轮廓立体感

StylizedRockParallax.shader

Shader "Universal Render Pipeline/StylizedRockParallax"

{

Properties

{

[Header(Base Textures)]

_MainTex("Albedo (RGB)", 2D) = "white" {}

_NormalMap("Normal Map", 2D) = "bump" {}

_HeightMap("Height Map", 2D) = "white" {}

_RampTex("Stylized Ramp", 2D) = "white" {}

[Header(Parallax Settings)]

_ParallaxScale("Depth Scale", Range(0, 0.15)) = 0.08

_LayerBias("Layer Bias", Range(0.1, 0.5)) = 0.3

_MinLayers("Min Layers", Int) = 5

_MaxLayers("Max Layers", Int) = 12

[Header(Stylized Lighting)]

_RimPower("Rim Power", Range(1, 10)) = 3

_ShadowTint("Shadow Tint", Color) = (0.3,0.3,0.4,1)

}

SubShader

{

Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }

HLSLINCLUDE

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);

TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap);

TEXTURE2D(_HeightMap); SAMPLER(sampler_HeightMap);

TEXTURE2D(_RampTex); SAMPLER(sampler_RampTex);

float _ParallaxScale;

float _LayerBias;

int _MinLayers, _MaxLayers;

float _RimPower;

float4 _ShadowTint;

// 陡峭视差映射核心算法

float2 SteepParallaxMapping(float3 viewDirTS, float2 uv)

{

// 动态层数计算(平视视角增加层数)

int numLayers = (int)lerp(_MaxLayers, _MinLayers, saturate(dot(float3(0,0,1), viewDirTS)));

float layerHeight = 1.0 / numLayers;

float2 deltaUV = _ParallaxScale * viewDirTS.xy / (viewDirTS.z + _LayerBias) / numLayers;

// 光线步进初始化

float currentLayerHeight = 0;

float2 currentUV = uv;

float currentDepth = 1 - SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, currentUV).r;

// 分层深度检测

[loop]

for (int i = 0; i < _MaxLayers; ++i) {

if (currentLayerHeight >= currentDepth) break;

currentUV -= deltaUV;

currentDepth = 1 - SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, currentUV).r;

currentLayerHeight += layerHeight;

}

// 风格化插值修正

float2 prevUV = currentUV + deltaUV;

float prevDepth = currentDepth - layerHeight;

float weight = pow((currentLayerHeight - currentDepth) / (prevDepth - currentDepth + 0.001), 2);

return lerp(currentUV, prevUV, saturate(weight * 1.5));

}

// 风格化光照计算

half3 StylizedShading(float3 normalWS, float3 viewDirWS, float NdotL)

{

float rim = pow(1 - saturate(dot(normalWS, viewDirWS)), _RimPower);

float2 rampUV = float2(NdotL * 0.5 + 0.5, 0.5);

half3 rampColor = SAMPLE_TEXTURE2D(_RampTex, sampler_RampTex, rampUV).rgb;

return lerp(rampColor * _ShadowTint.rgb, rampColor, saturate(NdotL + rim));

}

ENDHLSL

Pass

{

HLSLPROGRAM

#pragma vertex vert

#pragma fragment frag

struct Attributes

{

float4 positionOS : POSITION;

float2 uv : TEXCOORD0;

float3 normalOS : NORMAL;

float4 tangentOS : TANGENT;

};

struct Varyings

{

float4 positionCS : SV_POSITION;

float2 uv : TEXCOORD0;

float3 viewDirTS : TEXCOORD1;

float3 normalWS : TEXCOORD2;

float3 viewDirWS : TEXCOORD3;

float4 shadowCoord : TEXCOORD4;

};

Varyings vert(Attributes IN)

{

Varyings OUT;

VertexPositionInputs posInput = GetVertexPositionInputs(IN.positionOS.xyz);

OUT.positionCS = posInput.positionCS;

VertexNormalInputs normInput = GetVertexNormalInputs(IN.normalOS, IN.tangentOS);

float3 viewDirWS = GetWorldSpaceViewDir(posInput.positionWS);

OUT.viewDirTS = TransformWorldToTangent(viewDirWS,

normInput.tangentWS, normInput.bitangentWS, normInput.normalWS);

OUT.normalWS = normInput.normalWS;

OUT.viewDirWS = viewDirWS;

OUT.shadowCoord = GetShadowCoord(posInput);

OUT.uv = IN.uv;

return OUT;

}

half4 frag(Varyings IN) : SV_Target

{

// 计算陡峭视差UV

float2 parallaxUV = SteepParallaxMapping(normalize(IN.viewDirTS), IN.uv);

// 采样纹理

half4 albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, parallaxUV);

half3 normalTS = UnpackNormal(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, parallaxUV));

// 转换法线到世界空间

float3x3 TBN = float3x3(

normalize(cross(IN.normalWS, IN.viewDirWS)),

normalize(IN.normalWS),

normalize(IN.viewDirWS)

);

float3 normalWS = mul(TBN, normalTS);

// 光照计算

Light mainLight = GetMainLight(IN.shadowCoord);

float NdotL = saturate(dot(normalWS, mainLight.direction));

half3 lighting = StylizedShading(normalWS, normalize(IN.viewDirWS), NdotL);

return half4(albedo.rgb * lighting * mainLight.color, 1);

}

ENDHLSL

}

}

}

材质配置

参数组合 风格化效果

_ParallaxScale=0.05 + _RimPower=5 轻度凹凸+柔和边缘光

_ParallaxScale=0.1 + _LayerBias=0.4 强烈凹凸+抗失真处理

_ShadowTint=(0.4,0.2,0.6) 紫色调阴影增强风格化表现

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/23 15:11:39

【python大数据毕设实战】哮喘患者症状数据可视化分析系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

作者头像 李华
网站建设 2026/2/24 22:54:11

9 个降AI率工具,MBA 必备避坑指南

9 个降AI率工具&#xff0c;MBA 必备避坑指南 AI降重工具&#xff1a;MBA论文的智能护航 MBA论文写作过程中&#xff0c;越来越多的学生开始依赖AI工具进行内容生成。然而&#xff0c;随着高校对AIGC率的严格管控&#xff0c;如何在保持论文原创性和学术规范的同时&#xff0c;…

作者头像 李华
网站建设 2026/2/25 23:59:01

Windows系统文件inetmib1.dll丢失损坏 下载修复方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/2/27 9:52:48

Boost电路的右半平面零点

3.1、为什么存在这个右零点&#xff1f;&#xff08;关键点&#xff1a;先储能再释放&#xff09;答&#xff1a;右零点不是数学上的巧合&#xff0c;而是由Boost电路独特的能量传输方式决定的。其物理过程可以这样理解&#xff1a;假设电路已经稳定工作&#xff0c;此时我们突…

作者头像 李华
网站建设 2026/2/25 21:40:24

【全球AI伦理治理】

AI伦理治理框架的全球协同案例 欧盟《人工智能法案》提出基于风险分级的四层治理体系&#xff0c;禁止社会评分等高风险应用。OECD的AI政策观察站已收录全球700余项政策倡议&#xff0c;形成跨国数据库共享机制。新加坡的Model AI Governance Framework为亚洲企业提供可认证的伦…

作者头像 李华
网站建设 2026/2/26 17:06:02

毕业季必看!7款免费AI写论文神器实测,一站式搞定选题、大纲到降重

如果你是正在熬夜赶Deadline的毕业生&#xff0c;或是面临着科研压力、被导师催稿的研究生&#xff0c;又或是没钱又要写高质量论文的大学生&#xff0c;那么这篇文章简直就是为你量身打造的&#xff01;在学术的道路上&#xff0c;我们都曾经历过论文选题的迷茫、写作过程的煎…

作者头像 李华