news 2026/4/18 13:26:40

【URP】Unity中Mipmap是如何实现的?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【URP】Unity中Mipmap是如何实现的?

原理详解

‌纹理金字塔构建‌:

原始纹理经过滤波处理生成多级缩略图,例如256×256的纹理会生成128×128、64×64等层级,每级分辨率递减50%。

‌动态层级选择‌:

GPU根据像素在屏幕空间中的覆盖面积自动计算合适的Mip层级(公式为level = log2(max(ddx,ddy)),其中ddx/ddy为纹理坐标导数)。

‌过滤技术配合‌:

‌双线性过滤‌:在单一Mip层级内插值。

‌三线性过滤‌:在相邻两个Mip层级间插值,消除层级切换的突兀感。

构建 纹理金字塔

在Unity URP中,Mipmap纹理金字塔的构建是通过GPU逐级下采样实现的,其核心流程分为硬件自动生成和计算着色器手动生成两种方式。

硬件自动生成原理

‌基础纹理处理‌:原始纹理(如2048×2048)经过双线性/三线性滤波处理,生成分辨率逐级减半的子纹理(1024×1024、512×512等),直至1×1像素。

‌层级关系计算‌:GPU根据屏幕像素覆盖率自动选择Mip层级,公式为:$lod=log2(max(\frac{\partial u}{\partial x},\frac{\partial v}{\partial y}))$其中偏导数通过纹理坐标微分计算。

计算着色器手动生成示例(Hi-Z技术)

通过Compute Shader构建深度纹理的金字塔:

HiZFeature.cs

using UnityEngine;

using UnityEngine.Rendering;

using UnityEngine.Rendering.Universal;

public class HiZFeature : ScriptableRendererFeature {

class HiZPass : ScriptableRenderPass {

ComputeShader _hizShader;

RenderTexture _hizPyramid;

public override void Execute(ScriptableRenderContext context, ref RenderingData data) {

CommandBuffer cmd = CommandBufferPool.Get();

// 从深度纹理生成Mipmap金字塔

int width = _hizPyramid.width;

int height = _hizPyramid.height;

for (int mip = 0; width >= 8 || height >= 8; mip++) {

cmd.SetComputeTextureParam(_hizShader, 0, "_HiZTexture", _hizPyramid, mip);

cmd.DispatchCompute(_hizShader, 0, width/8, height/8, 1);

width >>= 1; height >>= 1;

}

context.ExecuteCommandBuffer(cmd);

CommandBufferPool.Release(cmd);

}

}

}

HiZ.compute

#pragma kernel CSMain_HiZ

Texture2D<float> _DepthTexture;

RWTexture2D<float> _HiZTexture;

[numthreads(8, 8, 1)]

void CSMain_HiZ(uint3 id : SV_DispatchThreadID) {

// 8x8区域取最大深度值作为下采样结果

float maxDepth = 0;

for (int x = 0; x < 8; x++) {

for (int y = 0; y < 8; y++) {

maxDepth = max(maxDepth, _DepthTexture[id.xy * 8 + uint2(x,y)]);

}

}

_HiZTexture[id.xy] = maxDepth;

}

关键步骤解析

‌层级生成逻辑‌:每级Mipmap通过对上一级4个像素取平均值(颜色纹理)或最大值(深度纹理)生成,例如256×256纹理生成128×128层级时,每个新像素由原纹理2×2区域计算得出。

‌过滤模式影响‌:

‌双线性过滤‌:在单层Mip内插值4个相邻纹素。

‌三线性过滤‌:在相邻两层Mip间进行二次插值,消除层级切换突变。

应用场景对比

生成方式 适用场景 性能开销

硬件自动生成 常规颜色纹理 低

计算着色器生成 深度纹理/特殊效果(如Hi-Z) 中高

通过调整RenderTexture.useMipMap属性和GenerateMipMaps标志位可控制生成行为。手动生成更适合需要自定义下采样规则的场景,如遮挡剔除优化.

实现动态层级选择

在Unity URP中,Mipmap的动态层级选择是通过GPU硬件自动计算纹理坐标的导数(ddx/ddy)实现的.

动态选择原理

‌导数计算‌$lod=log2(max(∥\frac{\partial u}{\partial x}∥,∥\frac{\partial v}{\partial y}∥))$

GPU通过片元着色器中的纹理坐标偏导数(ddx(uv)和ddy(uv))确定屏幕像素覆盖的纹理区域大小。当物体距离摄像机越远,UV坐标变化率越大,导数值越高。

示例:若屏幕像素覆盖4×4纹素区域,则Mip层级计算公式为:

此时计算结果为2(因4=2²),选择Mip Level 2的纹理。

‌层级插值‌

启用三线性过滤时,GPU会在计算出的层级(如2.3级)相邻两层(Level 2和Level 3)之间进行插值,消除突变感。

‌LOD偏移控制‌

URP通过Texture2D.mipMapBias参数手动调整层级偏移,正值使纹理更模糊(强制使用更高层级),负值保留细节(偏向低级)。

实现示例

以下Shader代码演示手动控制Mip层级的两种方式:

hlsl

// 方式1:通过tex2Dlod硬编码层级

fixed4 frag(v2f i) : SV_Target {

float4 uv = float4(i.uv, 0, _ManualLod); // _ManualLod为自定义层级

return tex2Dlod(_MainTex, uv);

}

// 方式2:根据距离动态计算层级

float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

float dist = distance(_WorldSpaceCameraPos, worldPos);

float lod = log2(dist * _LodScale); // _LodScale控制距离敏感度

fixed4 col = tex2Dlod(_MainTex, float4(i.uv, 0, lod));

层级选择优化

‌Hi-Z技术‌

对深度纹理构建Mip金字塔时,每层级存储最大深度值(而非颜色平均值),加速遮挡剔除。

流程:

生成深度纹理Mipmap时,通过Compute Shader对4×4区域取最大值下采样。

渲染时根据层级深度快速判断可见性。

‌ShaderGraph节点‌

URP的Calculate Level Of Detail节点提供两种模式:

‌Clamped‌:限制在纹理最大层级内,避免越界。

‌Unclamped‌:允许超出现有层级,需配合边界处理。

性能与质量平衡

‌过模糊问题‌:通过QualitySettings.masterTextureLimit全局限制最高层级。

‌锐化需求‌:禁用Mipmap或使用Unlit Shader避免自动插值。

典型应用场景包括地形渲染(远山使用高Mip层级)和动态LOD系统(根据物体重要性调整mipMapBias)

解决的问题

‌性能优化‌:

减少显存带宽占用,远处物体使用低分辨率纹理降低GPU负载。

‌视觉质量‌:

消除远景的像素闪烁(Texture Aliasing)和锯齿,提升平滑度。

‌缓存命中率‌:

低分辨率纹理占用更少缓存空间,提高采样效率。

使用场景与限制

‌适用场景‌:

3D开放世界地形(如远山、建筑)。

动态缩放的物体(如角色模型在远距离时)。

‌不适用场景‌:

2D像素游戏(需保持锐利像素风格)。

UI元素(通常无需动态缩放)。

‌限制‌:

内存开销增加33%(存储多级纹理)。

可能引起远处纹理过度模糊(需调整Mip Bias参数)。

具体示例

‌Shader实现‌:

在URP Shader中,可通过tex2Dlod函数手动指定Mip层级(float4参数的w分量控制层级)。例如:

hlsl

fixed4 frag(v2f i) : SV_Target {

return tex2Dlod(_MainTex, float4(i.uv, 0, _MipLevel));

}

调整_MipLevel可观察不同层级的模糊效果.

‌Unity编辑器演示‌:

导入纹理后勾选Generate Mip Maps,观察Inspector面板中的Mipmap预览滑块(0-10级)。

对比开启/关闭Mipmap的相同纹理,远处物体在开启时会自然模糊,关闭则出现像素噪点。

通过权衡内存与性能,Mipmap在URP中成为优化大规模场景渲染的关键技术之一

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

变量名越怪,JVM 越快?

更短、更“随机”的名字在字符串常量池、哈希和反射路径上更省。在作者的压测里&#xff0c;吞吐提升最高接近 49%。这听起来反常识&#xff0c;但他用微基准、压测与分析器把它变成了一个严肃命题。这事是怎么被发现的故事开始于一次“事故”。作者重构时不小心把 customerEma…

作者头像 李华
网站建设 2026/4/18 2:06:29

终极指南:如何在Linux系统快速安装Maven 3.8.5

终极指南&#xff1a;如何在Linux系统快速安装Maven 3.8.5 【免费下载链接】Maven3.8.5Linux版本下载 本开源项目提供了专为Linux系统优化的Maven 3.8.5版本&#xff0c;采用一键解压设计&#xff0c;简化安装流程&#xff0c;极大提升部署效率。无论您是开发新手还是经验丰富的…

作者头像 李华
网站建设 2026/4/18 2:00:45

Android高斯模糊终极指南:Blurry库完整使用教程

Android高斯模糊终极指南&#xff1a;Blurry库完整使用教程 【免费下载链接】Blurry Blurry is an easy blur library for Android 项目地址: https://gitcode.com/gh_mirrors/bl/Blurry 还在为Android应用中的模糊效果实现而烦恼吗&#xff1f;面对复杂的RenderScript …

作者头像 李华
网站建设 2026/4/18 0:02:07

学习测评|基于springboot + vue学习测评系统(源码+数据库+文档)

学习测评 目录 基于springboot vue学习测评系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue学习测评系统 一、前言 博主介绍&#xff1a;✌️大…

作者头像 李华
网站建设 2026/4/17 10:08:11

14、深入了解Domino作为Web服务器的配置、安全与故障排除

深入了解Domino作为Web服务器的配置、安全与故障排除 1. Linux操作系统配置 在将Domino 6服务器配置为Web服务器时,由于HTTP协议下连接的临时性(每个请求打开一个连接,发送消息,返回响应,然后关闭连接),需要特别注意Linux操作系统的TCP/IP部分配置。 1.1 基本建议 系…

作者头像 李华
网站建设 2026/4/18 3:36:58

MapsModelsImporter终极指南:让Blender轻松导入Google地图3D模型

MapsModelsImporter终极指南&#xff1a;让Blender轻松导入Google地图3D模型 【免费下载链接】MapsModelsImporter A Blender add-on to import models from google maps 项目地址: https://gitcode.com/gh_mirrors/ma/MapsModelsImporter MapsModelsImporter是一款革命…

作者头像 李华