第16章 深度与颜色纹理处理

第16章 深度与颜色纹理处理

理论讲解

16.1 DepthOnlyPass实现原理

DepthOnlyPass是URP中用于生成深度纹理的渲染通道,它只渲染场景中物体的深度信息而不输出颜色,为后续的光照、阴影、后处理等效果提供深度数据支持。

DepthOnlyPass的主要功能:

  1. 深度纹理生成:渲染场景中所有物体的深度信息到纹理
  2. 性能优化:通过只输出深度值减少渲染开销
  3. 数据准备:为阴影计算、后期处理等提供深度数据
  4. 剔除处理:处理透明物体和不透明物体的深度

DepthOnlyPass的工作流程:

  1. 渲染设置:配置渲染状态,只输出深度值
  2. 物体筛选:选择需要渲染深度的物体
  3. 深度渲染:执行深度渲染,输出到深度纹理
  4. 资源管理:管理深度纹理的创建和释放

深度纹理的用途:

  • 阴影计算:用于阴影贴图的生成
  • 后期处理:用于景深、屏幕空间反射等效果
  • 遮挡剔除:用于优化渲染性能
  • 光照计算:用于屏幕空间光照效果

16.2 CopyDepthPass与DepthTexture

CopyDepthPass负责将深度缓冲区的内容复制到可访问的纹理中,使得着色器可以在后续渲染中采样深度信息。

CopyDepthPass的作用:

  1. 深度缓冲区复制:将GPU深度缓冲区复制到纹理
  2. 格式转换:确保深度数据格式正确
  3. 多相机支持:支持多个相机的深度纹理复制
  4. 性能优化:使用高效的复制操作

深度纹理的特性:

  • 精度要求:需要足够的精度存储深度值
  • 格式选择:通常使用RFloat或RHalf格式
  • 采样方式:支持硬件插值采样
  • 内存管理:需要有效的内存分配和释放

16.3 OpaqueTexture生成流程

OpaqueTexture是URP中用于存储不透明物体颜色信息的纹理,通常在透明物体渲染前生成,用于实现透明度混合效果。

OpaqueTexture的生成时机:

  1. 渲染顺序:在透明物体渲染之前生成
  2. 相机设置:根据相机配置决定是否生成
  3. 效果需求:当需要透明度混合效果时生成
  4. 性能考虑:平衡效果和性能需求

OpaqueTexture的使用场景:

  • 透明度混合:实现正确的透明度混合
  • 反射效果:用于屏幕空间反射
  • 折射效果:用于屏幕空间折射
  • 后处理效果:用于某些后处理算法

16.4 深度纹理的采样与使用

在URP的着色器中,深度纹理通过特定的函数和变量进行访问和采样。

深度采样函数:

SampleSceneDepth:采样场景深度纹理
LinearEyeDepth:将深度值转换为线性眼部深度
ComputeScreenPos:计算屏幕空间位置

深度纹理格式:

  • RFloat:32位浮点格式,精度最高
  • RHalf:16位浮点格式,平衡精度和性能
  • RInt:整数格式,用于特定用途

16.5 场景颜色的复制时机

场景颜色的复制是渲染管线中的重要步骤,决定了何时将当前渲染结果保存为纹理供后续使用。

复制时机的考虑因素:

  1. 渲染顺序:在透明物体渲染前复制
  2. 后处理需求:为后处理效果准备输入
  3. 性能影响:平衡复制频率和性能
  4. 内存使用:管理纹理资源的使用

复制操作的优化:

  • 条件复制:只在需要时复制
  • 异步复制:使用异步操作提高性能
  • 压缩格式:使用压缩格式减少内存占用
  • 共享纹理:在多个效果间共享纹理

16.6 性能影响分析

深度与颜色纹理的处理对渲染性能有显著影响,需要在视觉效果和性能之间找到平衡。

性能影响因素:

  1. 纹理分辨率:分辨率越高性能开销越大
  2. 复制频率:频繁复制影响渲染性能
  3. 内存占用:纹理占用显存资源
  4. 带宽消耗:纹理读写消耗带宽

优化策略:

  • 分辨率缩放:降低纹理分辨率
  • 条件生成:只在需要时生成纹理
  • 格式优化:选择合适的纹理格式
  • 资源复用:复用纹理资源

代码示例

16.7 深度纹理处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class DepthTextureProcessor : MonoBehaviour
{
[Header("Depth Texture Settings")]
public bool enableDepthProcessing = true;
public bool visualizeDepth = true;
public bool logDepthData = true;

[Header("Depth Texture Configuration")]
public RenderTextureFormat depthFormat = RenderTextureFormat.Depth;
public FilterMode depthFilterMode = FilterMode.Point;
public TextureWrapMode depthWrapMode = TextureWrapMode.Clamp;
public CompareFunction depthCompareFunction = CompareFunction.Less;

[Header("Performance Settings")]
public int maxDepthTextureResolution = 2048;
public float depthTextureScale = 1.0f;
public bool useMipmaps = false;
public bool enableAntiAliasing = false;

private RenderTexture m_DepthTexture;
private CommandBuffer m_DepthCommandBuffer;
private Material m_DepthVisualizationMaterial;
private Camera m_Camera;

[System.Serializable]
public class DepthAnalysisData
{
public RenderTexture depthTexture;
public int resolutionWidth;
public int resolutionHeight;
public RenderTextureFormat format;
public FilterMode filterMode;
public float averageDepth;
public float minDepth;
public float maxDepth;
public bool isValid;
public System.DateTime lastUpdate;
}

[System.Serializable]
public class DepthPerformanceData
{
public int depthTextureMemoryKB;
public float depthRenderTimeMS;
public int depthDrawCalls;
public float memoryUsageMB;
public bool isOptimal;
}

public DepthAnalysisData analysisData = new DepthAnalysisData();
public DepthPerformanceData performanceData = new DepthPerformanceData();

void Start()
{
m_Camera = GetComponent<Camera>();
if (m_Camera == null)
{
m_Camera = Camera.main;
}

if (enableDepthProcessing)
{
InitializeDepthProcessing();
}
}

void OnEnable()
{
if (enableDepthProcessing)
{
RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
}
}

void OnDisable()
{
if (enableDepthProcessing)
{
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
}

Cleanup();
}

private void InitializeDepthProcessing()
{
CreateDepthTexture();
CreateDepthCommandBuffer();
CreateDepthVisualizationMaterial();
}

private void CreateDepthTexture()
{
if (m_Camera == null) return;

int width = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelWidth * depthTextureScale), maxDepthTextureResolution);
int height = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelHeight * depthTextureScale), maxDepthTextureResolution);

if (m_DepthTexture != null)
{
m_DepthTexture.Release();
}

m_DepthTexture = new RenderTexture(width, height, 24, depthFormat);
m_DepthTexture.filterMode = depthFilterMode;
m_DepthTexture.wrapMode = depthWrapMode;
m_DepthTexture.useMipmaps = useMipmaps;
m_DepthTexture.antiAliasing = enableAntiAliasing ? 4 : 1;
m_DepthTexture.Create();

// 更新分析数据
analysisData.depthTexture = m_DepthTexture;
analysisData.resolutionWidth = width;
analysisData.resolutionHeight = height;
analysisData.format = depthFormat;
analysisData.filterMode = depthFilterMode;
analysisData.lastUpdate = System.DateTime.Now;
analysisData.isValid = m_DepthTexture.IsCreated();

if (logDepthData)
{
Debug.Log($"[DepthTexture] Created depth texture: {width}x{height}, Format: {depthFormat}");
}
}

private void CreateDepthCommandBuffer()
{
if (m_DepthCommandBuffer != null)
{
m_DepthCommandBuffer.Clear();
}
else
{
m_DepthCommandBuffer = new CommandBuffer();
m_DepthCommandBuffer.name = "Depth Texture Copy";
}
}

private void CreateDepthVisualizationMaterial()
{
// 创建深度可视化材质
string shaderSource = @"
Shader ""Hidden/DepthVisualization""
{
Properties
{
_MainTex (""Texture"", 2D) = ""white"" {}
_DepthTex (""Depth Texture"", 2D) = ""white"" {}
_DepthScale (""Depth Scale"", Range(0.1, 10.0)) = 1.0
}
SubShader
{
Tags { ""RenderType""=""Opaque"" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include ""UnityCG.cginc""

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

sampler2D _DepthTex;
float4 _DepthTex_TexelSize;
float _DepthScale;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_DepthTex, i.uv);
depth = Linear01Depth(depth, _ZBufferParams);
float3 color = depth * _DepthScale;
return fixed4(color, 1.0);
}
ENDCG
}
}
}";

// 注意:在实际项目中,您需要创建一个真正的Shader资源
// 这里仅作示例,实际使用时请创建Shader文件
}

private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
if (camera != m_Camera || !enableDepthProcessing) return;

// 在相机渲染开始时执行深度处理
ExecuteDepthProcessing(context, camera);
}

private void OnEndCameraRendering(ScriptableRenderContext context, Camera camera)
{
if (camera != m_Camera || !enableDepthProcessing) return;

// 在相机渲染结束时执行清理
ExecuteDepthCleanup(context, camera);
}

private void ExecuteDepthProcessing(ScriptableRenderContext context, Camera camera)
{
if (m_DepthCommandBuffer == null) return;

m_DepthCommandBuffer.Clear();

// 添加深度纹理复制命令
m_DepthCommandBuffer.BeginSample("DepthTextureCopy");
m_DepthCommandBuffer.CopyDepth(m_DepthTexture);
m_DepthCommandBuffer.EndSample("DepthTextureCopy");

context.ExecuteCommandBuffer(m_DepthCommandBuffer);
m_DepthCommandBuffer.Clear();
}

private void ExecuteDepthCleanup(ScriptableRenderContext context, Camera camera)
{
// 分析深度纹理数据
AnalyzeDepthTexture();
}

private void AnalyzeDepthTexture()
{
if (m_DepthTexture == null || !m_DepthTexture.IsCreated()) return;

// 读取深度纹理数据进行分析(简化处理)
RenderTexture.active = m_DepthTexture;

// 创建临时纹理用于读取数据
Texture2D tempTexture = new Texture2D(m_DepthTexture.width, m_DepthTexture.height, TextureFormat.RGB24, false);
tempTexture.ReadPixels(new Rect(0, 0, m_DepthTexture.width, m_DepthTexture.height), 0, 0);
tempTexture.Apply();

// 分析像素数据
Color[] pixels = tempTexture.GetPixels();
float sum = 0f;
float minDepth = float.MaxValue;
float maxDepth = float.MinValue;

foreach (Color pixel in pixels)
{
float depthValue = pixel.r; // 简化:使用红色通道表示深度
sum += depthValue;
minDepth = Mathf.Min(minDepth, depthValue);
maxDepth = Mathf.Max(maxDepth, depthValue);
}

analysisData.averageDepth = sum / pixels.Length;
analysisData.minDepth = minDepth;
analysisData.maxDepth = maxDepth;

// 计算性能数据
performanceData.depthTextureMemoryKB = (m_DepthTexture.width * m_DepthTexture.height * 4) / 1024; // 简化计算
performanceData.memoryUsageMB = performanceData.depthTextureMemoryKB / 1024.0f;
performanceData.isOptimal = performanceData.memoryUsageMB < 100.0f; // 假设100MB是阈值

// 清理临时纹理
DestroyImmediate(tempTexture);

if (logDepthData)
{
Debug.Log($"[Depth Analysis] Avg: {analysisData.averageDepth:F3}, Min: {analysisData.minDepth:F3}, Max: {analysisData.maxDepth:F3}");
}
}

// 获取深度纹理
public RenderTexture GetDepthTexture()
{
return m_DepthTexture;
}

// 获取深度分析数据
public DepthAnalysisData GetDepthAnalysisData()
{
return analysisData;
}

// 获取深度性能数据
public DepthPerformanceData GetDepthPerformanceData()
{
return performanceData;
}

// 更新深度纹理配置
public void UpdateDepthConfiguration(int resolutionScale, RenderTextureFormat format, FilterMode filterMode)
{
depthTextureScale = Mathf.Clamp01(resolutionScale / 100.0f);
depthFormat = format;
depthFilterMode = filterMode;

CreateDepthTexture();
}

// 检查深度纹理是否有效
public bool IsDepthTextureValid()
{
return m_DepthTexture != null && m_DepthTexture.IsCreated();
}

// 获取深度纹理统计信息
public string GetDepthTextureStats()
{
var stats = new System.Text.StringBuilder();
stats.AppendLine("=== Depth Texture Statistics ===");
stats.AppendLine($"Resolution: {analysisData.resolutionWidth}x{analysisData.resolutionHeight}");
stats.AppendLine($"Format: {analysisData.format}");
stats.AppendLine($"Filter Mode: {analysisData.filterMode}");
stats.AppendLine($"Average Depth: {analysisData.averageDepth:F3}");
stats.AppendLine($"Min Depth: {analysisData.minDepth:F3}");
stats.AppendLine($"Max Depth: {analysisData.maxDepth:F3}");
stats.AppendLine($"Memory Usage: {performanceData.memoryUsageMB:F2} MB");
stats.AppendLine($"Is Valid: {analysisData.isValid}");
stats.AppendLine($"Is Optimal: {performanceData.isOptimal}");

return stats.ToString();
}

// 绘制深度纹理可视化(用于调试)
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (!visualizeDepth || !IsDepthTextureValid())
{
Graphics.Blit(source, destination);
return;
}

// 这里可以实现深度纹理的可视化
// 由于Unity的限制,实际的深度纹理可视化需要特殊处理
Graphics.Blit(source, destination);
}

private void Cleanup()
{
if (m_DepthTexture != null)
{
m_DepthTexture.Release();
m_DepthTexture = null;
}

if (m_DepthCommandBuffer != null)
{
m_DepthCommandBuffer.Dispose();
m_DepthCommandBuffer = null;
}
}

void OnDestroy()
{
Cleanup();
}
}

16.8 颜色纹理处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class ColorTextureProcessor : MonoBehaviour
{
[Header("Color Texture Settings")]
public bool enableColorProcessing = true;
public bool visualizeColor = true;
public bool logColorData = true;

[Header("Color Texture Configuration")]
public RenderTextureFormat colorFormat = RenderTextureFormat.ARGB32;
public FilterMode colorFilterMode = FilterMode.Bilinear;
public TextureWrapMode colorWrapMode = TextureWrapMode.Clamp;
public int antiAliasing = 1;
public bool useMipmaps = false;

[Header("Performance Settings")]
public int maxColorTextureResolution = 2048;
public float colorTextureScale = 1.0f;
public bool enableDynamicResolution = false;
public float resolutionReductionThreshold = 0.8f;

private RenderTexture m_ColorTexture;
private RenderTexture m_PreviousColorTexture;
private CommandBuffer m_ColorCommandBuffer;
private Material m_ColorVisualizationMaterial;
private Camera m_Camera;

[System.Serializable]
public class ColorAnalysisData
{
public RenderTexture colorTexture;
public RenderTexture previousColorTexture;
public int resolutionWidth;
public int resolutionHeight;
public RenderTextureFormat format;
public FilterMode filterMode;
public Color averageColor;
public float brightness;
public float saturation;
public float contrast;
public bool isValid;
public System.DateTime lastUpdate;
}

[System.Serializable]
public class ColorPerformanceData
{
public int colorTextureMemoryKB;
public float colorRenderTimeMS;
public int colorDrawCalls;
public float memoryUsageMB;
public bool isOptimal;
public float textureBandwidthMBPS;
}

public ColorAnalysisData analysisData = new ColorAnalysisData();
public ColorPerformanceData performanceData = new ColorPerformanceData();

void Start()
{
m_Camera = GetComponent<Camera>();
if (m_Camera == null)
{
m_Camera = Camera.main;
}

if (enableColorProcessing)
{
InitializeColorProcessing();
}
}

void OnEnable()
{
if (enableColorProcessing)
{
RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering += OnEndCameraRendering;
}
}

void OnDisable()
{
if (enableColorProcessing)
{
RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
RenderPipelineManager.endCameraRendering -= OnEndCameraRendering;
}

Cleanup();
}

private void InitializeColorProcessing()
{
CreateColorTexture();
CreateColorCommandBuffer();
CreateColorVisualizationMaterial();
}

private void CreateColorTexture()
{
if (m_Camera == null) return;

int width, height;

if (enableDynamicResolution)
{
// 根据性能动态调整分辨率
float performanceFactor = GetPerformanceFactor();
width = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelWidth * colorTextureScale * performanceFactor), maxColorTextureResolution);
height = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelHeight * colorTextureScale * performanceFactor), maxColorTextureResolution);
}
else
{
width = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelWidth * colorTextureScale), maxColorTextureResolution);
height = Mathf.Min(Mathf.RoundToInt(m_Camera.pixelHeight * colorTextureScale), maxColorTextureResolution);
}

// 保存之前的纹理用于比较
m_PreviousColorTexture = m_ColorTexture;

if (m_ColorTexture != null)
{
m_ColorTexture.Release();
}

m_ColorTexture = new RenderTexture(width, height, 24, colorFormat);
m_ColorTexture.filterMode = colorFilterMode;
m_ColorTexture.wrapMode = colorWrapMode;
m_ColorTexture.useMipmaps = useMipmaps;
m_ColorTexture.antiAliasing = Mathf.Max(1, Mathf.Min(8, antiAliasing));
m_ColorTexture.Create();

// 更新分析数据
analysisData.colorTexture = m_ColorTexture;
analysisData.resolutionWidth = width;
analysisData.resolutionHeight = height;
analysisData.format = colorFormat;
analysisData.filterMode = colorFilterMode;
analysisData.lastUpdate = System.DateTime.Now;
analysisData.isValid = m_ColorTexture.IsCreated();

if (logColorData)
{
Debug.Log($"[ColorTexture] Created color texture: {width}x{height}, Format: {colorFormat}");
}
}

private float GetPerformanceFactor()
{
// 简化的性能因子计算
float frameTime = Time.unscaledDeltaTime;
float targetFrameTime = 1.0f / 60.0f; // 60 FPS

if (frameTime > targetFrameTime * 1.2f) // 性能下降
{
return Mathf.Max(0.5f, resolutionReductionThreshold);
}

return 1.0f; // 正常性能
}

private void CreateColorCommandBuffer()
{
if (m_ColorCommandBuffer != null)
{
m_ColorCommandBuffer.Clear();
}
else
{
m_ColorCommandBuffer = new CommandBuffer();
m_ColorCommandBuffer.name = "Color Texture Copy";
}
}

private void CreateColorVisualizationMaterial()
{
// 创建颜色可视化材质
string shaderSource = @"
Shader ""Hidden/ColorVisualization""
{
Properties
{
_MainTex (""Texture"", 2D) = ""white"" {}
_ColorTex (""Color Texture"", 2D) = ""white"" {}
_Intensity (""Intensity"", Range(0.1, 5.0)) = 1.0
}
SubShader
{
Tags { ""RenderType""=""Opaque"" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include ""UnityCG.cginc""

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};

sampler2D _ColorTex;
float4 _ColorTex_TexelSize;
float _Intensity;

v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}

fixed4 frag (v2f i) : SV_Target
{
fixed4 color = tex2D(_ColorTex, i.uv);
return color * _Intensity;
}
ENDCG
}
}
}";

// 注意:在实际项目中,您需要创建一个真正的Shader资源
// 这里仅作示例,实际使用时请创建Shader文件
}

private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
if (camera != m_Camera || !enableColorProcessing) return;

// 在相机渲染开始时执行颜色处理
ExecuteColorProcessing(context, camera);
}

private void OnEndCameraRendering(ScriptableRenderContext context, Camera camera)
{
if (camera != m_Camera || !enableColorProcessing) return;

// 在相机渲染结束时执行清理和分析
ExecuteColorCleanup(context, camera);
}

private void ExecuteColorProcessing(ScriptableRenderContext context, Camera camera)
{
if (m_ColorCommandBuffer == null) return;

m_ColorCommandBuffer.Clear();

// 添加颜色纹理复制命令
m_ColorCommandBuffer.BeginSample("ColorTextureCopy");
m_ColorCommandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, m_ColorTexture);
m_ColorCommandBuffer.EndSample("ColorTextureCopy");

context.ExecuteCommandBuffer(m_ColorCommandBuffer);
m_ColorCommandBuffer.Clear();
}

private void ExecuteColorCleanup(ScriptableRenderContext context, Camera camera)
{
// 分析颜色纹理数据
AnalyzeColorTexture();
}

private void AnalyzeColorTexture()
{
if (m_ColorTexture == null || !m_ColorTexture.IsCreated()) return;

// 读取颜色纹理数据进行分析
RenderTexture activeRT = RenderTexture.active;
RenderTexture.active = m_ColorTexture;

// 创建临时纹理用于读取数据
Texture2D tempTexture = new Texture2D(m_ColorTexture.width, m_ColorTexture.height, TextureFormat.RGB24, false);
tempTexture.ReadPixels(new Rect(0, 0, m_ColorTexture.width, m_ColorTexture.height), 0, 0);
tempTexture.Apply();

// 分析像素数据
Color[] pixels = tempTexture.GetPixels();
Color sum = Color.black;
float brightnessSum = 0f;
float saturationSum = 0f;

foreach (Color pixel in pixels)
{
sum += pixel;

// 计算亮度
float brightness = pixel.grayscale;
brightnessSum += brightness;

// 计算饱和度
float maxVal = Mathf.Max(Mathf.Max(pixel.r, pixel.g), pixel.b);
float minVal = Mathf.Min(Mathf.Min(pixel.r, pixel.g), pixel.b);
float saturation = maxVal == 0 ? 0 : (maxVal - minVal) / maxVal;
saturationSum += saturation;
}

analysisData.averageColor = sum / pixels.Length;
analysisData.brightness = brightnessSum / pixels.Length;
analysisData.saturation = saturationSum / pixels.Length;

// 计算对比度(简化算法)
analysisData.contrast = Mathf.Abs(analysisData.brightness - 0.5f) * 2f;

// 计算性能数据
performanceData.colorTextureMemoryKB = (m_ColorTexture.width * m_ColorTexture.height * GetFormatBytes(colorFormat)) / 1024;
performanceData.memoryUsageMB = performanceData.colorTextureMemoryKB / 1024.0f;
performanceData.isOptimal = performanceData.memoryUsageMB < 200.0f; // 假设200MB是阈值
performanceData.textureBandwidthMBPS = performanceData.memoryUsageMB / Time.deltaTime; // 简化计算

// 恢复原始渲染纹理
RenderTexture.active = activeRT;

// 清理临时纹理
DestroyImmediate(tempTexture);

if (logColorData)
{
Debug.Log($"[Color Analysis] Avg: {analysisData.averageColor}, Brightness: {analysisData.brightness:F3}, Saturation: {analysisData.saturation:F3}");
}
}

private int GetFormatBytes(RenderTextureFormat format)
{
switch (format)
{
case RenderTextureFormat.ARGB32:
case RenderTextureFormat.RGB111110Float:
return 4;
case RenderTextureFormat.ARGBHalf:
case RenderTextureFormat.Depth:
return 2;
case RenderTextureFormat.ARGBFloat:
return 16;
default:
return 4; // 默认值
}
}

// 获取颜色纹理
public RenderTexture GetColorTexture()
{
return m_ColorTexture;
}

// 获取颜色分析数据
public ColorAnalysisData GetColorAnalysisData()
{
return analysisData;
}

// 获取颜色性能数据
public ColorPerformanceData GetColorPerformanceData()
{
return performanceData;
}

// 更新颜色纹理配置
public void UpdateColorConfiguration(int resolutionScale, RenderTextureFormat format, FilterMode filterMode, int aa)
{
colorTextureScale = Mathf.Clamp01(resolutionScale / 100.0f);
colorFormat = format;
colorFilterMode = filterMode;
antiAliasing = aa;

CreateColorTexture();
}

// 检查颜色纹理是否有效
public bool IsColorTextureValid()
{
return m_ColorTexture != null && m_ColorTexture.IsCreated();
}

// 获取颜色纹理统计信息
public string GetColorTextureStats()
{
var stats = new System.Text.StringBuilder();
stats.AppendLine("=== Color Texture Statistics ===");
stats.AppendLine($"Resolution: {analysisData.resolutionWidth}x{analysisData.resolutionHeight}");
stats.AppendLine($"Format: {analysisData.format}");
stats.AppendLine($"Filter Mode: {analysisData.filterMode}");
stats.AppendLine($"Average Color: {analysisData.averageColor}");
stats.AppendLine($"Brightness: {analysisData.brightness:F3}");
stats.AppendLine($"Saturation: {analysisData.saturation:F3}");
stats.AppendLine($"Contrast: {analysisData.contrast:F3}");
stats.AppendLine($"Memory Usage: {performanceData.memoryUsageMB:F2} MB");
stats.AppendLine($"Bandwidth: {performanceData.textureBandwidthMBPS:F2} MB/s");
stats.AppendLine($"Is Valid: {analysisData.isValid}");
stats.AppendLine($"Is Optimal: {performanceData.isOptimal}");

return stats.ToString();
}

// 动态调整纹理分辨率以优化性能
public void AdjustResolutionForPerformance()
{
if (!enableDynamicResolution) return;

float performanceFactor = GetPerformanceFactor();

if (performanceFactor < resolutionReductionThreshold)
{
// 性能不足,降低分辨率
colorTextureScale = Mathf.Max(0.25f, colorTextureScale * 0.8f);
CreateColorTexture();

if (logColorData)
{
Debug.LogWarning($"[ColorTexture] Resolution reduced to maintain performance: Scale={colorTextureScale:F2}");
}
}
else if (performanceFactor > 0.95f && colorTextureScale < 1.0f)
{
// 性能良好,提高分辨率
colorTextureScale = Mathf.Min(1.0f, colorTextureScale * 1.1f);
CreateColorTexture();

if (logColorData)
{
Debug.Log($"[ColorTexture] Resolution increased for better quality: Scale={colorTextureScale:F2}");
}
}
}

// 绘制颜色纹理可视化(用于调试)
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (!visualizeColor || !IsColorTextureValid())
{
Graphics.Blit(source, destination);
return;
}

// 这里可以实现颜色纹理的可视化
Graphics.Blit(source, destination);
}

private void Cleanup()
{
if (m_ColorTexture != null)
{
m_ColorTexture.Release();
m_ColorTexture = null;
}

if (m_PreviousColorTexture != null)
{
m_PreviousColorTexture.Release();
m_PreviousColorTexture = null;
}

if (m_ColorCommandBuffer != null)
{
m_ColorCommandBuffer.Dispose();
m_ColorCommandBuffer = null;
}
}

void OnDestroy()
{
Cleanup();
}
}

16.9 深度与颜色纹理管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class DepthColorTextureManager : MonoBehaviour
{
[Header("Texture Management Settings")]
public bool enableTextureManagement = true;
public bool enableAutoOptimization = true;
public bool logManagementData = true;

[Header("Management Configuration")]
public float textureUpdateInterval = 1.0f;
public int maxManagedTextures = 16;
public float memoryBudgetMB = 512.0f;
public float performanceThreshold = 0.8f;

[Header("Optimization Settings")]
public bool enableResolutionScaling = true;
public bool enableFormatOptimization = true;
public bool enableMipmapOptimization = true;
public bool enableAsyncRelease = true;

private List<RenderTexture> m_ManagedTextures = new List<RenderTexture>();
private Dictionary<RenderTexture, TextureManagementData> m_TextureManagementData = new Dictionary<RenderTexture, TextureManagementData>();
private DepthTextureProcessor m_DepthProcessor;
private ColorTextureProcessor m_ColorProcessor;
private float m_LastUpdate = 0f;

[System.Serializable]
public class TextureManagementData
{
public RenderTexture texture;
public TextureType type;
public int width;
public int height;
public RenderTextureFormat format;
public int usageCount;
public float lastAccessTime;
public float creationTime;
public bool isOptimal;
public float memoryUsageMB;
public TextureOptimizationState optimizationState;
public System.DateTime lastOptimization;
}

public enum TextureType
{
Depth,
Color,
Opaque,
Custom
}

public enum TextureOptimizationState
{
Optimal,
OverSized,
UnderSized,
FormatSuboptimal,
NeedsCompression
}

[System.Serializable]
public class TextureManagementSummary
{
public int totalManagedTextures;
public int depthTextures;
public int colorTextures;
public int opaqueTextures;
public float totalMemoryUsageMB;
public float memoryBudgetMB;
public float memoryUsagePercentage;
public int optimalTextures;
public int suboptimalTextures;
public float averageOptimizationScore;
public bool memoryBudgetExceeded;
public int texturesNeedingOptimization;
}

public TextureManagementSummary summary = new TextureManagementSummary();

void Start()
{
if (enableTextureManagement)
{
InitializeTextureManagement();
}
}

void Update()
{
if (enableTextureManagement && Time.time - m_LastUpdate >= textureUpdateInterval)
{
UpdateTextureManagement();
m_LastUpdate = Time.time;
}
}

private void InitializeTextureManagement()
{
m_DepthProcessor = GetComponent<DepthTextureProcessor>();
if (m_DepthProcessor == null)
{
m_DepthProcessor = gameObject.AddComponent<DepthTextureProcessor>();
}

m_ColorProcessor = GetComponent<ColorTextureProcessor>();
if (m_ColorProcessor == null)
{
m_ColorProcessor = gameObject.AddComponent<ColorTextureProcessor>();
}

// 注册渲染管线事件
RenderPipelineManager.beginFrameRendering += OnBeginFrameRendering;
RenderPipelineManager.endFrameRendering += OnEndFrameRendering;
}

private void OnBeginFrameRendering(ScriptableRenderContext context, Camera[] cameras)
{
// 在帧渲染开始时执行纹理管理
foreach (var camera in cameras)
{
ManageCameraTextures(context, camera);
}
}

private void OnEndFrameRendering(ScriptableRenderContext context, Camera[] cameras)
{
// 在帧渲染结束时执行纹理清理
foreach (var camera in cameras)
{
CleanupCameraTextures(context, camera);
}
}

private void ManageCameraTextures(ScriptableRenderContext context, Camera camera)
{
// 管理相机相关的纹理
var cameraTextures = GetCameraTextures(camera);

foreach (var texture in cameraTextures)
{
if (!m_TextureManagementData.ContainsKey(texture))
{
RegisterTexture(texture);
}

UpdateTextureUsage(texture);
}
}

private void CleanupCameraTextures(ScriptableRenderContext context, Camera camera)
{
// 清理不再使用的纹理
CleanupUnusedTextures();
}

private List<RenderTexture> GetCameraTextures(Camera camera)
{
var textures = new List<RenderTexture>();

// 获取相机相关的深度纹理
if (m_DepthProcessor != null && m_DepthProcessor.IsDepthTextureValid())
{
var depthTex = m_DepthProcessor.GetDepthTexture();
if (depthTex != null)
{
textures.Add(depthTex);
}
}

// 获取相机相关的颜色纹理
if (m_ColorProcessor != null && m_ColorProcessor.IsColorTextureValid())
{
var colorTex = m_ColorProcessor.GetColorTexture();
if (colorTex != null)
{
textures.Add(colorTex);
}
}

return textures;
}

private void RegisterTexture(RenderTexture texture)
{
if (m_ManagedTextures.Count >= maxManagedTextures)
{
// 如果达到最大纹理数,移除最不常用的纹理
RemoveLeastUsedTexture();
}

var managementData = new TextureManagementData
{
texture = texture,
type = DetermineTextureType(texture),
width = texture.width,
height = texture.height,
format = texture.format,
usageCount = 1,
lastAccessTime = Time.time,
creationTime = Time.time,
memoryUsageMB = CalculateTextureMemoryUsage(texture),
optimizationState = TextureOptimizationState.Optimal,
lastOptimization = System.DateTime.Now
};

m_ManagedTextures.Add(texture);
m_TextureManagementData[texture] = managementData;

if (logManagementData)
{
Debug.Log($"[TextureManager] Registered texture: {texture.width}x{texture.height}, Format: {texture.format}");
}
}

private TextureType DetermineTextureType(RenderTexture texture)
{
// 简化的纹理类型判断
if (texture.depth > 0)
{
return TextureType.Depth;
}
else if (texture.format == RenderTextureFormat.ARGB32 ||
texture.format == RenderTextureFormat.ARGBHalf ||
texture.format == RenderTextureFormat.ARGBFloat)
{
return TextureType.Color;
}
else
{
return TextureType.Custom;
}
}

private float CalculateTextureMemoryUsage(RenderTexture texture)
{
int bytesPerPixel = GetFormatBytes(texture.format);
int totalBytes = texture.width * texture.height * bytesPerPixel;
return totalBytes / (1024.0f * 1024.0f); // 转换为MB
}

private int GetFormatBytes(RenderTextureFormat format)
{
switch (format)
{
case RenderTextureFormat.ARGB32:
case RenderTextureFormat.RGB111110Float:
return 4;
case RenderTextureFormat.ARGBHalf:
case RenderTextureFormat.Depth:
return 2;
case RenderTextureFormat.ARGBFloat:
return 16;
case RenderTextureFormat.R8:
return 1;
case RenderTextureFormat.R16:
return 2;
case RenderTextureFormat.RFloat:
return 4;
default:
return 4; // 默认值
}
}

private void UpdateTextureUsage(RenderTexture texture)
{
if (m_TextureManagementData.ContainsKey(texture))
{
var data = m_TextureManagementData[texture];
data.usageCount++;
data.lastAccessTime = Time.time;

// 检查是否需要优化
if (enableAutoOptimization)
{
AnalyzeAndOptimizeTexture(texture);
}
}
}

private void AnalyzeAndOptimizeTexture(RenderTexture texture)
{
if (!m_TextureManagementData.ContainsKey(texture)) return;

var data = m_TextureManagementData[texture];

// 分析纹理是否需要优化
data.optimizationState = AnalyzeTextureOptimization(texture, data);

// 如果需要优化,执行优化
if (data.optimizationState != TextureOptimizationState.Optimal && enableAutoOptimization)
{
OptimizeTexture(texture, data);
}
}

private TextureOptimizationState AnalyzeTextureOptimization(RenderTexture texture, TextureManagementData data)
{
// 检查分辨率是否过大
if (texture.width > 2048 || texture.height > 2048)
{
return TextureOptimizationState.OverSized;
}

// 检查内存使用是否过多
if (data.memoryUsageMB > 32.0f) // 假设32MB是单个纹理的阈值
{
return TextureOptimizationState.OverSized;
}

// 检查格式是否合适
if (texture.format == RenderTextureFormat.ARGBFloat && data.type == TextureType.Depth)
{
return TextureOptimizationState.FormatSuboptimal;
}

// 检查是否需要mipmap
if (texture.useMipmaps && data.type == TextureType.Depth && !IsDepthTextureUsingMipmapsOptimal(texture))
{
return TextureOptimizationState.FormatSuboptimal;
}

return TextureOptimizationState.Optimal;
}

private bool IsDepthTextureUsingMipmapsOptimal(RenderTexture texture)
{
// 对于深度纹理,通常不需要mipmap
return false;
}

private void OptimizeTexture(RenderTexture texture, TextureManagementData data)
{
switch (data.optimizationState)
{
case TextureOptimizationState.OverSized:
OptimizeTextureResolution(texture);
break;
case TextureOptimizationState.FormatSuboptimal:
OptimizeTextureFormat(texture);
break;
}

data.lastOptimization = System.DateTime.Now;
data.memoryUsageMB = CalculateTextureMemoryUsage(texture);
}

private void OptimizeTextureResolution(RenderTexture texture)
{
if (!enableResolutionScaling) return;

// 降低纹理分辨率
int newWidth = Mathf.Max(256, texture.width / 2);
int newHeight = Mathf.Max(256, texture.height / 2);

if (newWidth != texture.width || newHeight != texture.height)
{
// 创建新的优化后纹理
var optimizedTexture = new RenderTexture(newWidth, newHeight, texture.depth, texture.format);
optimizedTexture.filterMode = texture.filterMode;
optimizedTexture.wrapMode = texture.wrapMode;
optimizedTexture.useMipmaps = texture.useMipmaps;
optimizedTexture.antiAliasing = texture.antiAliasing;
optimizedTexture.Create();

// 复制内容(简化处理)
Graphics.Blit(texture, optimizedTexture);

// 替换纹理引用
ReplaceTexture(texture, optimizedTexture);

if (logManagementData)
{
Debug.Log($"[TextureManager] Optimized texture resolution: {texture.width}x{texture.height} -> {newWidth}x{newHeight}");
}
}
}

private void OptimizeTextureFormat(RenderTexture texture)
{
if (!enableFormatOptimization) return;

RenderTextureFormat newFormat = texture.format;

// 根据纹理类型选择合适的格式
if (texture.depth > 0) // 深度纹理
{
if (texture.format == RenderTextureFormat.ARGBFloat)
{
newFormat = RenderTextureFormat.Depth;
}
}
else // 颜色纹理
{
if (texture.format == RenderTextureFormat.ARGBFloat && !RequiresHighPrecision(texture))
{
newFormat = RenderTextureFormat.ARGB32;
}
}

if (newFormat != texture.format)
{
// 创建新的优化后纹理
var optimizedTexture = new RenderTexture(texture.width, texture.height, texture.depth, newFormat);
optimizedTexture.filterMode = texture.filterMode;
optimizedTexture.wrapMode = texture.wrapMode;
optimizedTexture.useMipmaps = texture.useMipmaps;
optimizedTexture.antiAliasing = texture.antiAliasing;
optimizedTexture.Create();

// 复制内容
Graphics.Blit(texture, optimizedTexture);

// 替换纹理引用
ReplaceTexture(texture, optimizedTexture);

if (logManagementData)
{
Debug.Log($"[TextureManager] Optimized texture format: {texture.format} -> {newFormat}");
}
}
}

private bool RequiresHighPrecision(RenderTexture texture)
{
// 简化的高精度需求判断
// 在实际应用中,这可能需要更复杂的逻辑
return texture.width > 1024 || texture.height > 1024;
}

private void ReplaceTexture(RenderTexture oldTexture, RenderTexture newTexture)
{
// 更新管理数据
if (m_TextureManagementData.ContainsKey(oldTexture))
{
var data = m_TextureManagementData[oldTexture];
m_TextureManagementData.Remove(oldTexture);
m_TextureManagementData[newTexture] = data;
data.texture = newTexture;
}

// 从列表中替换
int index = m_ManagedTextures.IndexOf(oldTexture);
if (index >= 0)
{
m_ManagedTextures[index] = newTexture;
}

// 释放旧纹理
if (enableAsyncRelease)
{
StartCoroutine(AsyncReleaseTexture(oldTexture));
}
else
{
oldTexture.Release();
}
}

private System.Collections.IEnumerator AsyncReleaseTexture(RenderTexture texture)
{
yield return new WaitForEndOfFrame();
if (texture != null && texture.IsCreated())
{
texture.Release();
}
}

private void RemoveLeastUsedTexture()
{
if (m_ManagedTextures.Count == 0) return;

// 找到使用次数最少且最久未访问的纹理
RenderTexture leastUsedTexture = null;
float oldestAccessTime = float.MaxValue;
int minUsageCount = int.MaxValue;

foreach (var texture in m_ManagedTextures)
{
if (m_TextureManagementData.ContainsKey(texture))
{
var data = m_TextureManagementData[texture];
if (data.usageCount < minUsageCount ||
(data.usageCount == minUsageCount && data.lastAccessTime < oldestAccessTime))
{
minUsageCount = data.usageCount;
oldestAccessTime = data.lastAccessTime;
leastUsedTexture = texture;
}
}
}

if (leastUsedTexture != null)
{
UnregisterTexture(leastUsedTexture);
}
}

private void UnregisterTexture(RenderTexture texture)
{
if (m_TextureManagementData.ContainsKey(texture))
{
m_TextureManagementData.Remove(texture);
}

m_ManagedTextures.Remove(texture);

if (enableAsyncRelease)
{
StartCoroutine(AsyncReleaseTexture(texture));
}
else
{
texture.Release();
}

if (logManagementData)
{
Debug.Log($"[TextureManager] Unregistered texture due to memory management");
}
}

private void CleanupUnusedTextures()
{
var texturesToRemove = new List<RenderTexture>();

foreach (var kvp in m_TextureManagementData)
{
var texture = kvp.Key;
var data = kvp.Value;

// 如果纹理已被外部释放或长时间未使用
if (!texture.IsCreated() || (Time.time - data.lastAccessTime) > 10f)
{
texturesToRemove.Add(texture);
}
}

foreach (var texture in texturesToRemove)
{
UnregisterTexture(texture);
}
}

private void UpdateTextureManagement()
{
GenerateSummary();

if (logManagementData)
{
LogManagementSummary();
}

// 检查内存预算
if (summary.totalMemoryUsageMB > memoryBudgetMB)
{
Debug.LogWarning($"[TextureManager] Memory budget exceeded: {summary.totalMemoryUsageMB:F2}MB / {memoryBudgetMB:F2}MB");
PerformMemoryCleanup();
}
}

private void GenerateSummary()
{
summary.totalManagedTextures = m_ManagedTextures.Count;
summary.depthTextures = 0;
summary.colorTextures = 0;
summary.opaqueTextures = 0;
summary.totalMemoryUsageMB = 0f;
summary.memoryBudgetMB = memoryBudgetMB;
summary.optimalTextures = 0;
summary.suboptimalTextures = 0;
summary.averageOptimizationScore = 0f;
summary.texturesNeedingOptimization = 0;

foreach (var texture in m_ManagedTextures)
{
if (m_TextureManagementData.ContainsKey(texture))
{
var data = m_TextureManagementData[texture];
summary.totalMemoryUsageMB += data.memoryUsageMB;

switch (data.type)
{
case TextureType.Depth:
summary.depthTextures++;
break;
case TextureType.Color:
summary.colorTextures++;
break;
case TextureType.Opaque:
summary.opaqueTextures++;
break;
}

if (data.optimizationState == TextureOptimizationState.Optimal)
{
summary.optimalTextures++;
}
else
{
summary.suboptimalTextures++;
summary.texturesNeedingOptimization++;
}
}
}

summary.memoryUsagePercentage = (summary.totalMemoryUsageMB / summary.memoryBudgetMB) * 100f;
summary.memoryBudgetExceeded = summary.totalMemoryUsageMB > memoryBudgetMB;

if (summary.totalManagedTextures > 0)
{
summary.averageOptimizationScore = (float)summary.optimalTextures / summary.totalManagedTextures;
}
}

private void LogManagementSummary()
{
var log = new System.Text.StringBuilder();
log.AppendLine("=== Texture Management Summary ===");
log.AppendLine($"Total Managed Textures: {summary.totalManagedTextures}");
log.AppendLine($"Depth Textures: {summary.depthTextures}");
log.AppendLine($"Color Textures: {summary.colorTextures}");
log.AppendLine($"Opaque Textures: {summary.opaqueTextures}");
log.AppendLine($"Total Memory Usage: {summary.totalMemoryUsageMB:F2} MB");
log.AppendLine($"Memory Budget: {summary.memoryBudgetMB:F2} MB");
log.AppendLine($"Memory Usage: {summary.memoryUsagePercentage:F1}%");
log.AppendLine($"Optimal Textures: {summary.optimalTextures}");
log.AppendLine($"Suboptimal Textures: {summary.suboptimalTextures}");
log.AppendLine($"Average Optimization Score: {summary.averageOptimizationScore:F2}");
log.AppendLine($"Memory Budget Exceeded: {summary.memoryBudgetExceeded}");
log.AppendLine($"Textures Needing Optimization: {summary.texturesNeedingOptimization}");

Debug.Log(log.ToString());
}

private void PerformMemoryCleanup()
{
// 执行内存清理
CleanupUnusedTextures();

// 如果仍然超出预算,进一步优化
if (summary.totalMemoryUsageMB > memoryBudgetMB)
{
OptimizeAllTextures();
}
}

private void OptimizeAllTextures()
{
// 对所有纹理进行优化
foreach (var texture in m_ManagedTextures)
{
if (m_TextureManagementData.ContainsKey(texture))
{
var data = m_TextureManagementData[texture];
if (data.optimizationState != TextureOptimizationState.Optimal)
{
OptimizeTexture(texture, data);
}
}
}
}

// 获取管理的纹理列表
public List<RenderTexture> GetManagedTextures()
{
return new List<RenderTexture>(m_ManagedTextures);
}

// 获取纹理管理数据
public TextureManagementData GetTextureManagementData(RenderTexture texture)
{
if (m_TextureManagementData.ContainsKey(texture))
{
return m_TextureManagementData[texture];
}
return null;
}

// 获取管理摘要
public TextureManagementSummary GetManagementSummary()
{
return summary;
}

// 手动添加纹理到管理
public bool AddTextureToManagement(RenderTexture texture)
{
if (m_ManagedTextures.Count >= maxManagedTextures)
{
return false;
}

if (!m_TextureManagementData.ContainsKey(texture))
{
RegisterTexture(texture);
return true;
}

return false;
}

// 手动移除纹理管理
public bool RemoveTextureFromManagement(RenderTexture texture)
{
if (m_TextureManagementData.ContainsKey(texture))
{
UnregisterTexture(texture);
return true;
}

return false;
}

// 获取纹理统计信息
public string GetTextureStats()
{
var stats = new System.Text.StringBuilder();
stats.AppendLine("=== Texture Statistics ===");

foreach (var texture in m_ManagedTextures)
{
if (m_TextureManagementData.ContainsKey(texture))
{
var data = m_TextureManagementData[texture];
stats.AppendLine($"Texture: {data.width}x{data.height}, Format: {data.format}, " +
$"Type: {data.type}, Memory: {data.memoryUsageMB:F2}MB, " +
$"Usage: {data.usageCount}, State: {data.optimizationState}");
}
}

return stats.ToString();
}

void OnDestroy()
{
// 清理所有管理的纹理
foreach (var texture in m_ManagedTextures)
{
if (texture != null && texture.IsCreated())
{
texture.Release();
}
}

m_ManagedTextures.Clear();
m_TextureManagementData.Clear();

// 注销渲染管线事件
RenderPipelineManager.beginFrameRendering -= OnBeginFrameRendering;
RenderPipelineManager.endFrameRendering -= OnEndFrameRendering;
}
}

实践练习

16.10 练习1:深度纹理分析

目标:创建一个深度纹理分析工具

步骤

  1. 创建DepthTextureProcessor类
  2. 实现深度纹理的创建和管理
  3. 分析深度纹理数据
  4. 生成深度纹理统计报告
  5. 测试深度纹理的性能影响

实现要点

  • 深度纹理的正确创建
  • 深度值的准确分析
  • 性能数据的收集

16.11 练习2:颜色纹理处理

目标:实现颜色纹理的全面管理

步骤

  1. 创建ColorTextureProcessor类
  2. 实现颜色纹理的生成和复制
  3. 分析颜色纹理属性
  4. 优化颜色纹理性能
  5. 验证颜色纹理质量

分析维度

  • 颜色平均值
  • 亮度和饱和度
  • 内存使用情况

16.12 练习3:纹理内存管理

目标:创建纹理内存管理器

步骤

  1. 实现纹理注册和跟踪
  2. 监控纹理内存使用
  3. 自动优化纹理配置
  4. 处理纹理生命周期
  5. 验证内存管理效果

管理策略

  • 内存预算控制
  • 纹理使用统计
  • 自动优化机制

16.13 练习4:深度纹理优化

目标:实现深度纹理的性能优化

步骤

  1. 分析深度纹理需求
  2. 优化深度纹理格式
  3. 调整深度纹理分辨率
  4. 实现深度纹理复用
  5. 测试优化效果

优化方面

  • 分辨率缩放
  • 格式选择
  • 内存复用

16.14 练习5:综合纹理管理系统

目标:创建综合的纹理管理系统

步骤

  1. 集成深度和颜色纹理管理
  2. 实现统一管理接口
  3. 提供性能监控
  4. 实现自动优化
  5. 生成综合报告

系统特性

  • 统一管理
  • 智能优化
  • 性能监控

总结

第16章详细探讨了URP中深度与颜色纹理的处理机制,包括DepthOnlyPass、CopyDepthPass、OpaqueTexture等关键组件的实现原理。深度和颜色纹理是渲染管线中的重要资源,为后续的光照、阴影、后处理等效果提供必要的数据支持。

关键要点总结:

  1. 深度纹理:通过DepthOnlyPass生成,用于阴影计算和后处理
  2. 颜色纹理:存储场景颜色信息,支持透明度混合等效果
  3. 纹理管理:有效的纹理管理对性能至关重要
  4. 性能优化:合理的纹理配置和使用策略影响整体性能
  5. 内存管理:纹理资源的内存使用需要严格控制

深度与颜色纹理的处理是渲染管线性能的关键因素,需要在视觉质量和性能之间找到平衡点。理解其内部实现有助于更好地配置和优化纹理资源的使用。

下一章将分析后处理系统的源码实现,深入了解URP中各种后处理效果的实现机制。