[LayaNative 2.0]CommandBuffer_Outline 每次 addCommandBuffer都会永久增加10Gpu,removed掉相机事件也不会减少

 
一下是代码
我的游戏需求是射线对准物体需要给物体描边,但添加描边这个操作会使Gpu永久增加10,调用了
removeCommandBuffer,这个gpu还是降低不下来,当描边过多次之后内存过满就会H5上就崩溃,请问怎么把之前的描边重新移
除呢?
 
 
 
import { PathData } from "../data/PathData";
import InsManager from "../manager/InsManager";
import { BlurEffect, BlurMaterial } from "../shader/BlurShader/BlurEffect"; 
export class CommandBuffer_Outline { 
    private commandBuffer: Laya.CommandBuffer;
    private cameraEventFlag: Laya.CameraEventFlags = Laya.CameraEventFlags.BeforeImageEffect;
    private camera: Laya.Camera; 
    private renders:Laya.BaseRender[]  = [];
    private materials:Laya.Material[] = []; 
    public static instance: CommandBuffer_Outline ; 
    private isUseOuline: boolean = true; // 控制是否使用描边
    
    public static GetInstance(): CommandBuffer_Outline{
        if(this.instance == null) this.instance = new CommandBuffer_Outline();
        return this.instance;
    } 
    public init(): void {
        //使用之前必须先初始化 
        if(this.camera == null){
            BlurEffect.init();
            this.camera = InsManager.GetInstance()._SceneManager.player.playerCamera;
            //Laya.Shader3D.debugMode = true;
        }
    } 
    public createDrawMeshCommandBuffer(camera:Laya.Camera, renders:Laya.BaseRender[] , materials:Laya.Material[]):Laya.CommandBuffer{ 
        if(this.renders.length == 0 || this.materials.length == 0 ) return;
        
        var buf:Laya.CommandBuffer = new Laya.CommandBuffer();
        //当需要在流程中拿摄像机渲染效果的时候 设置true
        camera.enableBuiltInRenderTexture = true;
        //创建和屏幕一样大的Rendertexture
        var viewPort: Laya.Viewport = camera.viewport;
        var renderTexture = Laya.RenderTexture.createFromPool(viewPort.width,viewPort.height,Laya.RenderTextureFormat.R8G8B8A8,Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
        //将RenderTexture设置为渲染目标
        buf.setRenderTarget(renderTexture);
        //清楚渲染目标的颜色为黑色,不清理深度
        buf.clearRenderTarget(true,false,new Laya.Vector4(0,0,0,0));
        
        //将传入的Render渲染到纹理上
        for(var i = 0,n = renders.length;i<n;i++){
            if(renders == null){
                this.RemoveCommandBuffer_Outline();
                return;
            }
            buf.drawRender(renders[i],materials[i],0);
        }
        //创建新的RenderTexture
         var subRendertexture = Laya.RenderTexture.createFromPool(viewPort.width,viewPort.height,Laya.RenderTextureFormat.R8G8B8A8,Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
        //将renderTexture的结果复制到subRenderTexture
         buf.blitScreenQuad(renderTexture,subRendertexture);
        //设置模糊的参数
         var downSampleFactor:number = 2;
         var downSampleWidth:number = viewPort.width/downSampleFactor;
         var downSampleheigh:number = viewPort.height/downSampleFactor;
        var texSize:Laya.Vector4 = new Laya.Vector4(1.0/viewPort.width,1.0/viewPort.height,viewPort.width,downSampleheigh);
        //创建模糊材质
        var blurMaterial: BlurMaterial = new BlurMaterial(texSize,1);
        
        //创建降采样RenderTexture1
         var downRenderTexture = Laya.RenderTexture.createFromPool(downSampleWidth,downSampleheigh,Laya.RenderTextureFormat.R8G8B8,Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
        //降采样  使用blurMaterial材质的0SubShader将Rendertexture渲染到DownRendertexture
         buf.blitScreenQuadByMaterial(renderTexture,downRenderTexture,null,blurMaterial,0); 
         //创建降采样RenderTexture2
        var blurTexture:Laya.RenderTexture =  Laya.RenderTexture.createFromPool(downSampleWidth,downSampleheigh,Laya.RenderTextureFormat.R8G8B8,Laya.RenderTextureDepthFormat.DEPTHSTENCIL_NONE);
        blurTexture.filterMode = Laya.FilterMode.Bilinear; 
        //Horizontal blur 使用blurMaterial材质的1SubShader
        buf.blitScreenQuadByMaterial(downRenderTexture,blurTexture,null,blurMaterial,1);
        //vertical blur 使用blurMaterial材质的2SubShader
        buf.blitScreenQuadByMaterial(blurTexture,downRenderTexture,null,blurMaterial,2);
        //Horizontal blur 使用blurMaterial材质的1SubShader
        buf.blitScreenQuadByMaterial(downRenderTexture,blurTexture,null,blurMaterial,1);
        //vertical blur   使用blurMaterial材质的2SubShader
        buf.blitScreenQuadByMaterial(blurTexture,downRenderTexture,null,blurMaterial,2);
        //在命令流里面插入设置图片命令流,在调用的时候会设置blurMaterial的图片数据
        buf.setShaderDataTexture(blurMaterial._shaderValues,BlurMaterial.SHADERVALUE_SOURCETEXTURE0,downRenderTexture);
        buf.setShaderDataTexture(blurMaterial._shaderValues,BlurMaterial.ShADERVALUE_SOURCETEXTURE1,subRendertexture);
        //caculate edge计算边缘图片
        buf.blitScreenQuadByMaterial(blurTexture,renderTexture,null,blurMaterial,3);
        //重新传入图片
        buf.setShaderDataTexture(blurMaterial._shaderValues,BlurMaterial.SHADERVALUE_SOURCETEXTURE0,renderTexture);
        //将camera渲染结果复制到subRendertexture,使用blurMaterial的4通道shader
        buf.blitScreenQuadByMaterial(null,subRendertexture,null,blurMaterial,4);
        //将subRenderTexture重新赋值到camera的渲染结果上面
        buf.blitScreenQuadByMaterial(subRendertexture,null);
        return buf;
    }

  /** 为目标物体添加上描边 */
    public AddCommandBuffet_Outline(sprite3D : Laya.Sprite3D): void{
        if((sprite3D as Laya.MeshSprite3D) == null || !this.isUseOuline){ 
          // console.log('spreite3D node meshSprite3D is null');
           return;
        }
        var unlitMaterial = new Laya.UnlitMaterial();
        unlitMaterial.albedoColor = new Laya.Vector4(255,0,0,255); 
        if((sprite3D as Laya.MeshSprite3D).meshRenderer == null){
           this.renders.push( (sprite3D as Laya.SkinnedMeshSprite3D).skinnedMeshRenderer);
          // console.log( (sprite3D as Laya.SkinnedMeshSprite3D).skinnedMeshRenderer);
        }else{
           this.renders.push( (sprite3D as Laya.MeshSprite3D).meshRenderer );
          // console.log( (sprite3D as Laya.MeshSprite3D).meshRenderer);
        }     
        this.materials.push(unlitMaterial);
    
        //创建commandBuffer
        this.commandBuffer = this.createDrawMeshCommandBuffer(this.camera , this.renders , this.materials);
        //将commandBuffer加入渲染流程
        this.camera.addCommandBuffer(this.cameraEventFlag,this.commandBuffer);
        console.log( '添加描边:' + sprite3D.name); 
        if(InsManager.GetInstance()._SceneManager.gamePanel != null) InsManager.GetInstance()._SceneManager.gamePanel.target_point.skin = PathData.game_path + 'zd2.png'
    } 
    /** 移除在物体上边的描边 */
    public RemoveCommandBuffer_Outline(): void{
        if(this.renders.length == 0 || !this.isUseOuline) return;
        this.renders = [];
        this.materials = [];
        this.camera.removeCommandBuffer(this.cameraEventFlag,this.commandBuffer);
        if(InsManager.GetInstance()._SceneManager.gamePanel != null) InsManager.GetInstance()._SceneManager.gamePanel.target_point.skin = PathData.game_path + 'zd.png' 
        console.log('清除描边');
    } 
}
 
已邀请:

小智队长

赞同来自: ParadiseKiss

已解决:要把每次创建出来的renderTexture  清理掉 , 不然会已存在在显存中,所以要把 贴图都保存起来RemoveCommandBuffer_Outline 方法改为:
  /** 移除在物体上边的描边 */
    public RemoveCommandBuffer_Outline(): void{
        //更改准心颜色
        if(InsManager.GetInstance()._SceneManager.gamePanel != null) InsManager.GetInstance()._SceneManager.gamePanel.target_point.skin = PathData.game_path + 'zd.png';
        
        if(this.renders.length == 0 || !this.isUseOuline) return;
        this.renders = [];
        this.materials = [];
        this.camera.removeCommandBuffer(this.cameraEventFlag,this.commandBuffer);
        this.buf = null;
        
        if(this.renderTexture != null) Laya.RenderTexture.recoverToPool(this.renderTexture);
        if(this.blurTexture != null) Laya.RenderTexture.recoverToPool(this.blurTexture);
        if(this.subRendertexture != null) Laya.RenderTexture.recoverToPool(this.subRendertexture);
        if(this.downRenderTexture != null) Laya.RenderTexture.recoverToPool(this.downRenderTexture); 
        console.log('清除描边');
    }

ParadiseKiss

赞同来自:

你可以尝试用描边的shader,用摄像机发射的射线获取到想要描边的对象,再将对象的材质替换为描边材质,我觉得这种效率会比较高

该问题目前已经被锁定, 无法添加新回复

商务合作
商务合作