You need to enable JavaScript to run this app. Unity RenderTexture转Texture2D传原生DLL失效问题求助
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 21:36:08