news 2026/4/22 12:05:57

Unity URP 顶点偏移实现伪体积 Billboard

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Unity URP 顶点偏移实现伪体积 Billboard

让 Quad 始终面朝摄像机 — 球形与柱状 Billboard 详解

一、什么是 Billboard?

Billboard(公告板)是一种在游戏开发中广泛使用的技术——用一块始终朝向观察者的平面(通常为 Quad)来模拟体积效果。经典应用包括粒子、烟雾、远景树木、光晕等。

核心原理

Billboard 的本质是在顶点着色器中,丢弃模型的本地轴向(local axes),改用摄像机空间中的方向向量来计算顶点位置。

原始顶点→计算相机右向量→计算相机上向量→偏移顶点→朝向相机

二、球形 Billboard(Spherical Billboard)

球形 Billboard 平面始终正对摄像机位置,无论摄像机如何移动或旋转,Quad 都会完美地"面对"它。这是粒子系统中最常用的 Billboard 类型。

Shader 实现

完整的天空球形 Billboard Shader,包含两种矩阵变换方式的对比:

Shader "Custom/SphericalBillboard" { Properties { _MainTex ("Main Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) _Softness ("Softness", Range(0,1)) = 0.1 } SubShader { Tags { "RenderPipeline"="UniversalPipeline" "Queue"="Transparent" "RenderType"="Transparent" } Pass { Name Blend SrcAlpha OneMinusSrcAlpha ZWrite Off HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // ---------- 声明变量 TEXTURE2D(<_MainTex>); SAMPLER(sampler_MainTex); float4 _MainTex_ST; half4 _Color; float _Softness; struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; }; Varyings vert(Attributes input) { Varyings output = (Varyings)0; // 获取世界空间位置 float3 worldPos = TransformObjectToWorld(input.positionOS.xyz); // --- 关键:提取 CameraRight 和 CameraUp --- float camRight = -UNITY_MATRIX_V[0].x; // 矩阵第1列.x → Camera Right float camUp = -UNITY_MATRIX_V[1].x; // 矩阵第2列.x → Camera Up float3 camRightVec = float3(camRight, 0, 0); float3 camUpVec = float3(0, camUp, 0); // 计算 Billboard 尺寸 float2 size = float2(1.0, 1.0); float2 offset = input.positionOS.xy * size; // --- 顶点偏移:用相机向量替换模型轴向 --- worldPos += camRightVec * offset.x; // X轴替换为相机右向量 worldPos += camUpVec * offset.y; // Y轴替换为相机上向量 output.positionCS = TransformWorldToHClip(worldPos); output.uv = TRANSFORM_TEX(input.uv, _MainTex); return output; } half4 frag(Varyings input) : SV_Target { half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); col *= _Color; // 软边缘 alpha col.a *= 1.0 - saturate(length(input.uv - 2.0); return col; } ENDHLSL } } }

关键解析:第 55-58 行是 Billboard 的核心。通过读取 View Matrix(UNITY_MATRIX_V)的第 0 列和第 1 列,分别提取相机右向量(Camera Right)和相机上向量(Camera Up)。然后用这两个向量替换 Quad 原本的本地 X 和 Y 轴方向,使平面始终朝向摄像机。

三、柱状 Billboard(Cylindrical Billboard)

柱状 Billboard 与球形 Billboard 的核心区别在于:它只绕世界 Y 轴旋转,始终保持"站立"姿态,水平方向始终朝向摄像机。这种变体常用于远景树木、公告牌、圆柱形烟囱等场景。

Shader 实现

柱状 Billboard 的关键区别:Y 轴保持世界 Up 向量,只有水平方向绕 Y 轴旋转。

Shader "Custom/CylindricalBillboard" { Properties { _MainTex ("Main Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) } SubShader { Tags { "RenderPipeline"="UniversalPipeline" "Queue"="Transparent" } Pass { Name Blend SrcAlpha OneMinusSrcAlpha ZWrite Off HLSLPROGRAM #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" TEXTURE2D(<_MainTex>); SAMPLER(sampler_MainTex); float4 _MainTex_ST; CBUFFER_START(UnityPerMaterial) half4 _Color; CBUFFER_END struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float2 uv : TEXCOORD0; }; Varyings vert(Attributes input) { Varyings output = (Varyings)0; // 世界空间位置 float3 worldPos = TransformObjectToWorld(input.positionOS.xyz); // --- 水平朝向:计算指向相机的水平方向 --- float3 cameraPos = GetCameraPositionWS(); float3 dirToCam = normalize(cameraPos - worldPos); // 投影到 XZ 平面(水平面),去掉 Y 分量 float3 horizontalDir = normalize(float3(dirToCam.x, 0.0, dirToCam.z)); // Billboard 水平右向量(绕 Y 轴旋转) float3 billboardRight = horizontalDir; float3 billboardUp = float3(0, 1, 0); // 世界 Up,固定不变 // 顶点偏移 float2 offset = input.positionOS.xy * float2(1.0, 1.0); worldPos += billboardRight * offset.x; worldPos += billboardUp * offset.y; output.positionCS = TransformWorldToHClip(worldPos); output.uv = TRANSFORM_TEX(input.uv, _MainTex); return output; } half4 frag(Varyings input) : SV_Target { half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv); return col * _Color; } ENDHLSL } } }

核心区别:第 56 行 `float3(..., 0.0, ...)` 将朝向向量投影到水平面(XZ),只保留水平分量。这样 Billboard 始终保持站立(Y 轴固定为世界 Up),只在水平面内旋转朝向摄像机。适合树木、公告牌、圆柱形物体。

四、两种 Billboard 对比

特性球形 Billboard柱状 Billboard
旋转轴完全自由,始终朝向相机仅绕世界 Y 轴旋转
典型用途粒子、烟雾、光晕、特效远景树木、公告牌、路灯
向量来源Camera Right + Camera Up水平朝向 + 世界 Up
俯视效果会看到 Billboard 侧面(穿帮)俯视仍保持正确朝向
计算量从 View Matrix 提取(略低)需要计算水平朝向向量(略高)
适合场景空中粒子、3D 视角变化多的特效地形树木、户外建筑立面

五、实际应用:带噪声的烟雾 Billboard

配合半透明纹理和噪声动画,可以做出自然的烟雾效果。关键思路是在片段着色器中叠加 UV 偏移,实现软边衰减和动态扰动。

烟雾片段着色器片段
// 软边缘衰减 float2 center = float2(0.5, 0.5); float dist = length(input.uv - center) * 2.0; float softEdge = 1.0 - smoothstep(0.3, 1.0, dist); // UV 噪声扰动(时间动画) float noise = SAMPLE_TEXTURE2D(_NoiseTex, sampler_NoiseTex, input.uv * 2.0 + float2(0, -_Time.y * 0.3)).r; float alpha = softEdge * noise; col.a *= saturate(alpha);

六、性能优化建议

  • 批次合并(Batching)
    Billboard 对象通常数量极多(数千粒子),务必开启 GPU Instancing 或 SRP Batcher,减少 Draw Call。
  • 深度排序
    半透明物体无法写入深度缓冲,常见排序问题是闪烁(Z-fighting)。可设置合适的 Render Queue 或使用深度预通道。
  • 纹理尺寸
    Billboard 依赖 alpha 通道做软边缘,远景 Billboard 建议 256×256 即可,近景可适当增大,但超过 1024 通常收益不大。
  • 避免过度使用
    Billboard 的本质是"欺骗",适合中远景。近景、特写镜头建议用真实 3D 模型替代,以免穿帮。
  • GPU Instancing Shader
    如需同时控制数千个 Billboard,使用 `UNITY_VERTEX_INPUT_INSTANCE_ID` + `UNITY_VERTEX_OUTPUT_STEREO` 配合 Instancing Buffer 传入位置/缩放/颜色。

七、总结

Billboard 是一种简单却强大的伪体积技术。通过顶点着色器中的向量替换,Quad 可以模拟复杂的体积效果。两种变体的选择取决于场景需求:

球形 Billboard→ 粒子、烟雾、爆炸光效等全方位视角的场景
柱状 Billboard→ 树木、公告牌、灯柱等保持垂直的地物

在实际项目中,可以进一步扩展为 GPU Instancing 版本,配合噪声纹理和时间变量,实现更丰富的动态效果。核心原理始终不变——用相机向量替换模型轴向,让平面"面朝观众"。

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

NoFences:3步打造整洁高效的Windows桌面分区系统

NoFences&#xff1a;3步打造整洁高效的Windows桌面分区系统 【免费下载链接】NoFences &#x1f6a7; Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 想要彻底告别混乱的桌面图标吗&#xff1f;NoFences作为一款完全…

作者头像 李华
网站建设 2026/4/22 12:04:29

元宇宙质量保障:Roblox脚本安全测试框架

在元宇宙从概念蓝图演变为产业现实的进程中&#xff0c;以Roblox为代表的用户生成内容平台正扮演着核心枢纽的角色。其生命力源于强大的Luau脚本语言&#xff0c;它赋予创作者构建复杂交互与动态世界的无限可能。然而&#xff0c;这种开放性与灵活性也带来了前所未有的质量保障…

作者头像 李华
网站建设 2026/4/22 12:02:30

从需求到发布:手把手教你用CMMI配置管理搭建研发“数字档案馆”

构建研发数字资产中枢&#xff1a;CMMI配置管理实战指南 当电商平台的订单服务突然出现数据不一致时&#xff0c;开发团队耗费72小时才定位到问题根源——三个月前某次hotfix修改了数据库脚本但未更新部署文档。这种场景在缺乏配置管理的团队中屡见不鲜。现代软件研发早已不是代…

作者头像 李华
网站建设 2026/4/22 12:02:03

网络安全3个月速成学习顺序

网络安全3个月速成学习顺序 学习资源 如果你也是零基础想转行网络安全&#xff0c;却苦于没系统学习路径、不懂核心攻防技能&#xff1f;光靠盲目摸索不仅浪费时间&#xff0c;还消磨自己信心。这份 360 智榜样学习中心独家出版《网络攻防知识库》专为转行党量身打造&#xff0…

作者头像 李华
网站建设 2026/4/22 11:59:02

B站缓存视频转换终极指南:3分钟让m4s文件变成可播放MP4

B站缓存视频转换终极指南&#xff1a;3分钟让m4s文件变成可播放MP4 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾遇到这样的情况&…

作者头像 李华