Unity RenderTexture转Texture2D传原生DLL失效问题求助
场景与开发现状
- 开发身份为Unity初学者,正在推进大学研究项目开发,核心开发需求为:完成指定场景渲染后,将渲染得到的图像全量像素数据传入外部DLL工具,由外部工具基于原始像素数据生成独立的输出图像
- 开发进展:已参考Unity官方开源原生渲染插件示例,实现普通纹理传入DLL的功能且运行正常;但在将相机渲染产生的RenderTexture数据传入DLL时,无任何预期效果,问题长期未解决
可正常运行的功能代码
该段代码实现了普通Texture2D传入DLL的逻辑,运行状态正常:
tex.filterMode = FilterMode.Point; tex.Apply(); // Set texture onto our material GetComponent<Renderer>().material.mainTexture = tex; SetTextureFromUnity(tex.GetNativeTexturePtr(), tex.width, tex.height);
运行无效果的问题代码
该段代码尝试将相机渲染结果传入DLL,运行后无预期输出:
Camera camera = Camera.main; var rt = RenderTexture.GetTemporary(Screen.width, Screen.height); camera.targetTexture = rt; camera.Render(); var currentRT = RenderTexture.active; RenderTexture.active = camera.targetTexture; camera.Render(); Texture2D image = new Texture2D(camera.targetTexture.width, camera.targetTexture.height); image.ReadPixels(new Rect(0, 0, camera.targetTexture.width, camera.targetTexture.height), 0, 0); image.Apply(); RenderTexture.active = currentRT; camera.targetTexture = null; SetTextureFromUnity(image.GetNativeTexturePtr(), image.width, image.height);
问题根因与修正方案
核心问题点
- 渲染时机错位:代码中连续两次调用
camera.Render(),第一次渲染执行时还未将RenderTexture设为全局激活渲染目标,渲染输出未写入目标RT内存;第二次渲染属于冗余调用,会造成渲染管线状态污染 - 纹理格式不匹配:新建Texture2D时未显式指定像素格式,默认生成的纹理内存布局与RenderTexture的实际像素格式不一致,DLL侧按照固定格式解析指针时会读到无效数据
- 内存状态不对齐:调用
image.Apply()时未指定内存同步参数,直接通过GetNativeTexturePtr()拿到的指针可能指向GPU侧的纹理句柄,而非CPU侧可直接读取的像素内存,导致DLL无法获取全量像素数据 - 资源泄漏:临时申请的RenderTexture未在使用完成后执行回收操作,长期运行会造成显存占用异常
修正后的可参考代码
Camera camera = Camera.main; // 申请临时RT时显式指定位深度和像素格式,与后续读取的Texture2D格式完全对齐 var rt = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); // 保存当前全局激活的RT状态,避免渲染操作影响场景正常显示 var currentActiveRT = RenderTexture.active; // 先将目标RT设为全局激活的渲染目标,再触发渲染 RenderTexture.active = rt; camera.targetTexture = rt; camera.Render(); // 新建无mipmap的、格式与RT完全一致的Texture2D,减少不必要的内存开销 Texture2D image = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false); // 从当前激活的RT上读取全量像素 image.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); // 强制将像素数据同步到CPU可访问的内存空间 image.Apply(false, false); // 恢复全局渲染状态 RenderTexture.active = currentActiveRT; camera.targetTexture = null; // 回收临时申请的RT资源 RenderTexture.ReleaseTemporary(rt); // 传递给DLL的纹理指针、宽高参数与实际像素内存布局完全匹配 SetTextureFromUnity(image.GetNativeTexturePtr(), image.width, image.height);
注意:如果DLL侧是按照CPU内存逐字节读取像素,也可以直接通过
image.GetRawTextureData()拿到结构化的像素内存块指针传入,比直接传原生纹理指针的兼容性更好,不会受不同平台GPU纹理句柄差异的影响。
内容的提问来源于stack exchange,提问作者Thiwanka Chathuranga
相关产品推荐
相关产品推荐

