diff --git a/1Project/GPU地形/地形优化.md b/1Project/GPU地形/地形优化.md new file mode 100644 index 0000000..49dd2aa --- /dev/null +++ b/1Project/GPU地形/地形优化.md @@ -0,0 +1,26 @@ +### 优化带宽(减少储存数据量 +- 一块地形为128个三角形,每个三角形包含三个位置 + - 每个位置包含位置Vec3,法线Vec3,UV Vec2 + - 计算得出每个网格是12kb,整个场景为192M +- 优化uv储存 + - uv可以直接去掉,使用网格模型空间下的坐标 / 8来代替 + - ![[Pasted image 20251111231745.png]] +- 位置信息,可以优化掉position.xz只保留高度(没懂 + - 使用gl_VertexID(顶点索引)来生成位置 + - 使用floor和mod来确定x,z + - position.x = flooar(gl_VertexID / 2.0); + - position.z = mod(gl_VertexID, 2.0); +- 去掉法线,改为两个16整数,使用俯仰角和偏航角来确定法线方向。虽然精度只有原来的一半,但是对于法线来说足够了 +- 这些做完之后,由12.9kb=>3kb +- 使用三角形条带,除了第一个三角形之外,之后的每个三角形都可以较少两个顶点信息 + - 但只适合规整的网格 + +--- +着色器执行很快,但是一直等待从内存读取更多的数据,所以造成瓶颈 + + +### 使用批处理 + +### LOD + +### 使用foliage来掩盖每个细节层次的起始位置 \ No newline at end of file diff --git a/1Project/图文合批/图文使用不同的Tex2DArr.md b/1Project/图文合批/图文使用不同的Tex2DArr.md index 8dacc01..507341e 100644 --- a/1Project/图文合批/图文使用不同的Tex2DArr.md +++ b/1Project/图文合批/图文使用不同的Tex2DArr.md @@ -1 +1 @@ -- 降低内存 \ No newline at end of file +- 图片需要的format为RGBA格式,但是文字只需要灰度图,所以需要两种不同的处理方式,但需要在一个shader中处理 \ No newline at end of file diff --git a/1Project/图文合批/图文合批原理.md b/1Project/图文合批/图文合批原理.md deleted file mode 100644 index 5da1aeb..0000000 --- a/1Project/图文合批/图文合批原理.md +++ /dev/null @@ -1,3 +0,0 @@ -申请字体图原理 - -shader uv原理 \ No newline at end of file diff --git a/1Project/图文合批/字体字形图片申请.md b/1Project/图文合批/字体字形图片申请.md index d761264..1aa3646 100644 --- a/1Project/图文合批/字体字形图片申请.md +++ b/1Project/图文合批/字体字形图片申请.md @@ -2,3 +2,5 @@ - 通过`TMP_FontAsset.characterLookupTable.TryGetValue(char, out charInfo);`获得字符串信息 - 通过charInfo.glyph.glyphRect获得TMP_FontAsset.atlasTextures中的uv +### 传统字体 +- TODO \ No newline at end of file diff --git a/1Project/海量渲染战斗/GPU动画.md b/1Project/海量渲染战斗/GPU动画.md new file mode 100644 index 0000000..4b10aaf --- /dev/null +++ b/1Project/海量渲染战斗/GPU动画.md @@ -0,0 +1,2 @@ +- 拿到原mesh中的顶点uv,normals和bones以及bonesWeight,实例一张新的网格。通过RootTransform的算出来的每个顶点的Martix4x4与骨骼权重算出来的混合。 +- 通过Graphsic.DrawMesh()来绘制这张网格,至此实现gpu蒙皮动画 \ No newline at end of file diff --git a/1Project/海量渲染战斗/基于GPU蒙皮动画的Spine实现.md b/1Project/海量渲染战斗/基于GPU蒙皮动画的Spine实现.md new file mode 100644 index 0000000..cb5530f --- /dev/null +++ b/1Project/海量渲染战斗/基于GPU蒙皮动画的Spine实现.md @@ -0,0 +1 @@ +[[基于GPU动画和ComputeShader的大批量动画渲染Demo(一)之GPU顶点动画]] \ No newline at end of file diff --git a/1Project/海量渲染战斗/批量渲染gpu动画.md b/1Project/海量渲染战斗/批量渲染gpu动画.md new file mode 100644 index 0000000..5283ade --- /dev/null +++ b/1Project/海量渲染战斗/批量渲染gpu动画.md @@ -0,0 +1,7 @@ +- 通过[[GPU动画]],将Clip(每个顶点每帧的位置)烘焙到一张图片上去。 +- 用shader做顶点偏移,片元着色还是原来物体上的 + +### QA +- Q:如何保留原来shader的片元着色? +- Q:需要烘焙些什么信息,它们分别用在什么地方? +- Q:如果本身一个clip由多个不同的蒙皮动画来实现,每个蒙皮又对应不同的骨骼,该怎么处理? \ No newline at end of file diff --git a/2Areas/游戏开发/Texture、Texture2D与RenderTexture.md b/2Areas/游戏开发/Texture、Texture2D与RenderTexture.md index 44e3813..68034f4 100644 --- a/2Areas/游戏开发/Texture、Texture2D与RenderTexture.md +++ b/2Areas/游戏开发/Texture、Texture2D与RenderTexture.md @@ -8,4 +8,5 @@ tags: 简言: `Texture` 是抽象基类; `Texture2D` 是可读写的普通贴图; -`RenderTexture` 是可被渲染的动态纹理。 \ No newline at end of file +`RenderTexture` 是可被渲染的动态纹理。 + diff --git a/3Resources/游戏开发/性能优化/卡片/通过Unity申请的RenderTexture的内存在显存中还是在内存中.md b/3Resources/游戏开发/性能优化/卡片/通过Unity申请的RenderTexture的内存在显存中还是在内存中.md new file mode 100644 index 0000000..97b3617 --- /dev/null +++ b/3Resources/游戏开发/性能优化/卡片/通过Unity申请的RenderTexture的内存在显存中还是在内存中.md @@ -0,0 +1,89 @@ +--- +tags: + - Texture + - Texture2D + - RenderTexture +--- +# 总结 +- **RenderTexture 的像素数据 100% 在显存(GPU Memory)中**,不是在 CPU 内存中。 +- 除非**触发回读CPU**,也就是ReadPixel,才会在内存中有数据 +- 内存中有RT对象、Unity C++中的handle + + +下面分层说明其放在哪里、为什么、以及哪些部分可能在 CPU。 + +--- + +# 1. **RenderTexture 的核心像素存储位置:显存 (VRAM)** + +Unity 调用底层 API(DX11/12、Metal、Vulkan、GLES)时,创建 RenderTarget Texture 一定会将纹理 Allocation 放在: + +- **VRAM(GPU local memory)** + +- 或在某些平台(集显)上在**统一显存 UMA**区域(但本质也属于 GPU 可直接访问的物理内存) + + +因为: + +### RenderTexture 必须支持: + +- GPU 作为 RenderTarget 写入 + +- GPU 作为 Shader 资源读 + +- ComputeShader random write(开启 enableRandomWrite 时) + + +这些都要求纹理在 GPU 可直接寻址的专用显存中。 + +**所以 RenderTexture 不会放在 CPU 内存(System RAM)。** + +--- + +# 2. 那系统内存会占用吗? + +会,但只是**少量管理结构**: + +|类型|是否在 CPU RAM|说明| +|---|---|---| +|RenderTexture 对象(C# wrapper)|✔|占用极小(几十字节)| +|Unity 内部 RenderTexture handle|✔|也非常小| +|像素数据|✖|全在显存| + +**像素数据绝不会放在 System RAM。** +除非你用 `ReadPixels` 强制拷贝。 + +--- + +# 3. 特殊情况(集显、移动设备) + +即便 CPU 和 GPU 共用物理内存(如 Intel 集显、移动 SOC),Unity 仍然会: + +- 将 RenderTexture 创建成 **GPU 访问区域的纹理资源** + +- 不会放到 CPU 那边的缓冲区 + + +因此逻辑上它依然属于“显存”。 + +--- + +# 4. 如果你读取 RenderTexture,会发生什么? + +例如: + +`RenderTexture.active = rt; tex.ReadPixels(...);` + +**这会把 RenderTexture 从 GPU → CPU 进行一次拷贝** +代价巨大,会 stall GPU → CPU pipeline。 + +但这只是“做了 CPU 副本”,RenderTexture 仍然在显存中。 + +--- + +# 5. Unity Profiler 中的 Attrib + +Profiler 中 GPU Memory 的 **RenderTexture** 项目,就是 VRAM 占用。 +CPU Memory 中不会出现它。 + +如果你看到 CPU Memory 涨,是你创建了大量 Texture2D Readback 副本。 \ No newline at end of file diff --git a/4Archives/动态图集/动态图集.md b/4Archives/动态图集/动态图集.md new file mode 100644 index 0000000..8120943 --- /dev/null +++ b/4Archives/动态图集/动态图集.md @@ -0,0 +1,37 @@ +--- +tags: + - 性能优化 + - 动态图集 +--- +--- +### 目的 +- 减少*零散图标*导致使用不同材质球的批次 +- 需要注意*内存(在显存中)*的开销,如果释放策略不对,有可能导致内存泄露 +- [[2Areas/游戏开发/Texture、Texture2D与RenderTexture|Texture、Texture2D与RenderTexture]] +- [[通过Unity申请的RenderTexture的内存在显存中还是在内存中]] + +### 过程注意 +- 算法 + - 通过 +- 页 + - 负责记录有哪些图片,以及所在的位置,和对应的PageId +- 插入策略 + - 在页满的时候,先找外部传进来的策略先释放掉RefCount\==0的位置 + - 再根据权重重新排列 + - 计算重新排列后的空间是否足够插入 +- 回调 + - 当页因为释放/重排等原因变换位置的时候需要触发区域变换的回调通知到每个涉及到的图片Handle +- 释放 + - 定时器+脏标 + - 每次释放重置定时器的倒计时,在倒计时结束的时候如果为脏标,则触发重排重新计算权重 + - 脏标干净的时候,不触发定时器的tick +- Debug + - 需要告知页的数量 + - 每个handle的refCount,出生时间,最后调用时间,所在页Id,所在区域 +- Blit + - 需要注意,不要使用SetPixel,因为这种方法是CPU的耗时 + - 使用Graphics.Blit,这种方法是告知GPU往RT上Blit + +### 结果 +- 一张2048 * 2048的图片,对于主场景能减少20个批次左右 +- 方便为未来的HUD功能做铺垫 diff --git a/渲染/软渲染/图片/Pasted image 20251111231745.png b/渲染/软渲染/图片/Pasted image 20251111231745.png new file mode 100644 index 0000000..12db9b8 Binary files /dev/null and b/渲染/软渲染/图片/Pasted image 20251111231745.png differ