# Conflicts:
#	1Project/图文合批/图文合批原理.md
This commit is contained in:
Zane
2025-11-28 10:20:12 +08:00
11 changed files with 167 additions and 5 deletions

View File

@@ -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来掩盖每个细节层次的起始位置

View File

@@ -1 +1 @@
- 降低内存
- 图片需要的format为RGBA格式但是文字只需要灰度图所以需要两种不同的处理方式但需要在一个shader中处理

View File

@@ -1,3 +0,0 @@
申请字体图原理
shader uv原理

View File

@@ -2,3 +2,5 @@
- 通过`TMP_FontAsset.characterLookupTable.TryGetValue(char, out charInfo);`获得字符串信息
- 通过charInfo.glyph.glyphRect获得TMP_FontAsset.atlasTextures中的uv
### 传统字体
- TODO

View File

@@ -0,0 +1,2 @@
- 拿到原mesh中的顶点uvnormals和bones以及bonesWeight实例一张新的网格。通过RootTransform的算出来的每个顶点的Martix4x4与骨骼权重算出来的混合。
- 通过Graphsic.DrawMesh()来绘制这张网格至此实现gpu蒙皮动画

View File

@@ -0,0 +1 @@
[[基于GPU动画和ComputeShader的大批量动画渲染Demo之GPU顶点动画]]

View File

@@ -0,0 +1,7 @@
- 通过[[GPU动画]]将Clip每个顶点每帧的位置烘焙到一张图片上去。
- 用shader做顶点偏移片元着色还是原来物体上的
### QA
- Q如何保留原来shader的片元着色
- Q需要烘焙些什么信息它们分别用在什么地方
- Q如果本身一个clip由多个不同的蒙皮动画来实现每个蒙皮又对应不同的骨骼该怎么处理

View File

@@ -8,4 +8,5 @@ tags:
简言:
`Texture` 是抽象基类;
`Texture2D` 是可读写的普通贴图;
`RenderTexture` 是可被渲染的动态纹理。
`RenderTexture` 是可被渲染的动态纹理。

View File

@@ -0,0 +1,89 @@
---
tags:
- Texture
- Texture2D
- RenderTexture
---
# 总结
- **RenderTexture 的像素数据 100% 在显存GPU Memory中**,不是在 CPU 内存中。
- 除非**触发回读CPU**也就是ReadPixel才会在内存中有数据
- 内存中有RT对象、Unity C++中的handle
下面分层说明其放在哪里、为什么、以及哪些部分可能在 CPU。
---
# 1. **RenderTexture 的核心像素存储位置:显存 (VRAM)**
Unity 调用底层 APIDX11/12、Metal、Vulkan、GLES创建 RenderTarget Texture 一定会将纹理 Allocation 放在:
- **VRAMGPU 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 集显、移动 SOCUnity 仍然会:
- 将 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 副本。

View File

@@ -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功能做铺垫

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB