关于texture2D复用的问题

  • 问题背景:
    项目中,需要频繁创建以及销毁texture2D,所以想模仿节点池的思路,做复用,但发现texture2D二次赋值后,在屏幕上无法显示出来

  • 示例代码
    新建空场景,在场景中增加node,加载Sprite组件和UITransform组件
    export class test extends Component {

    _sp : Sprite = null; // 在场景中创建一个空的Sprite与其绑定

    _tag: number = 0;

    _texture:Texture2D = null;

    start () {

      this.node.on(Node.EventType.TOUCH_END, this.loadPic, this)
    

    }

    loadPic () {

      if (this._tag == 0){
    
           assetManager.loadRemote("http://xxxx.jpg", (err, asset) => {
    
                  if (!err) this.setImage(asset)
    
           })
    
      }
    
      else{
    
           this.clearImage()
    
      }
    

    }

    setImage(asset){

      if(this._texture == null){
    
          this._texture = new Texture2D()
    
          this._texture.image = asset
    
      } else {
    
          this._texture.image = asset
    
      }
    
      let spf: SpriteFrame = new SpriteFrame()
    
      spf.texture = this._texture
    
      spf.packable = false // 这行代码很重要,没有这行代码,引擎会自动合图,自动合图的时候会new Texture2D()
    
      this._sp.spriteFrame = spf
    
      this._sp.node.parent = this.node
    

    }

    clearImage(){

      this._texture.mipmaps = []
    
      this._sp.spriteFrame.destroy()
    
      this._sp.spriteFrame = null
    
      this._sp.node.removeFromParent() // 这里不用destroy是为了复用Sprite
    

    }
    }

现象就是,第一次点击场景,有图片,第二次点击图片消失,第三次点击应该有图片,但是没有。
在浏览器调试了引擎代码,发现texture.image赋值的时候,reset调用了,_assignImage也调用了,渲染的时候,该组装的数据也组装了,底层gl.texSubImage2D也调用了,现在求问引擎组大佬,这是为啥?

  • Creator 版本: 3.4.2
  • 目标平台: 谷歌浏览器
  • 首个报错: 没有报错
  • 编辑器操作系统: windows 10 64位
  • 重现概率: 必现

image
这里有问题。去底层看下源码。


这样是可行的。但是如果texture已经被第一个节点用了,

此时第二个节点用当前这个texture,
理论上会影响第一个节点。

1赞

参考官方代码:你若研究通了,分享一下

谢谢,我去瞅瞅

多次实验后发现,真正起作用的是
director.root.batcher2D._releaseDescriptorSetCache
texture.reset和uploadData在赋值image时有调用的

在_releaseDescriptorSetCache函数里,最终干了这些事儿


然后在getDescriptor的时候,再去重新创建

如果不调用_releaseDescriptorSetCache函数,在获取Descriptor的时候,得到的还是之前的descriptors[i].gpuTexture,而之前的gpuTexture在texture.reset()的时候被清理了,这应该就是引擎提示的,重置后,贴图的像素数据将变为未定义。

1赞

那你看,你要的texture缓存池这方案可行性如何?

可以了,按照你提供的API,texture2D的缓存池已经实现了,texture2D也可以复用了。

1赞

可不可以私发我研究研究哈哈哈

公司的项目是在内网开发的,拷不出来,如果你说的是demo的话,我发问的帖子里那段代码就是了。
而且后来我实验了一下,感觉复用texture2D没啥意义,还不如复用整个Sprite。

顺便提一下,这是做地图用的,游戏里地图是一块一块拼接起来的,人物移动的时候,需要把出视野的那些Sprite执行removefromparent,然后通过assetManager.loadRemote下载到新坐标的地图资源,重新组装成spriteframe赋值给Sprite,再调整Sprite的坐标位置。

刚开始全是new和destroy操作,所以在性能不好的手机上移动的时候,会有轻微卡顿的感觉,现在正在寻找不卡的方法。

了解了。