C3D关于用RenderTexture截屏

为了截图改个fov总觉得有点脏

改完再改回去就好了。或者改相机的z坐标

可以分享下你的toB64吗?
我的好像有问题,转出来的特别大而且没法还原成图片

好像跟你上边的一样。

这个解决了吗

用楼上大哥的方法可以

不用canvas 可以截屏吗 document.createElement(‘canvas’); 不用这个

大佬有demo吗?

原生版怎么截屏呢

请问,renderTex在哪里赋值的哈?有点懵

就new一下就行,随便哪里赋值。
new RenderTexture()

你好 大佬解决了有demo吗

/**截屏base64格式 */

public static capture(): string {

    if (xdSys.platform == xdPlatform.WEB ||

        xdSys.platform == xdPlatform.XQWEB ||

        xdSys.platform == xdPlatform.JSB) {

        let node = xdUIUtil.getUICanvas();

        let renderTex: RenderTexture = new RenderTexture();

        let winSize = xdUIUtil.getViewSize();

        renderTex.initialize({

            width: Math.floor(winSize.width),

            height: Math.floor(winSize.height),

        })

        let camera = node.getComponent(Canvas);

        camera.targetTexture = renderTex;

        director.root.pipeline.render([camera.camera.view]);

        let data = this.copyRenderTex(renderTex);

        camera.targetTexture = null;

        return data;

    }

    return null;

}

private static copyRenderTex(renderTex: RenderTexture): string {

    let arrayBuffer = new ArrayBuffer(renderTex.width * renderTex.height * 4);

    let region = new GFXBufferTextureCopy();

    region.texOffset.x = 0;

    region.texOffset.y = 0;

    region.texExtent.width = renderTex.width;

    region.texExtent.height = renderTex.height;

    director.root.device.copyFramebufferToBuffer(renderTex.window.framebuffer, arrayBuffer, [region]);

    if (xdSys.platform == xdPlatform.JSB) {

        let path = xdfile.getWritablePath() + 'capture.jpg';

        this.saveImageData(arrayBuffer, renderTex.width, renderTex.height, path);

        return path;

    } else {

        return this.toB64(arrayBuffer);

    }

}

private static saveImageData(arrayBuffer: ArrayBuffer, w: number, h: number, path: string) {

    let imageU8Data = new Uint8Array(arrayBuffer);

    //翻转图片

    let picData = new Uint8Array(w * h * 4);

    let rowBytes = w * 4;

    for (let row = 0; row < h; row++) {

        let srow = h - 1 - row;

        let start = srow * w * 4;

        let reStart = row * w * 4;

        // save the piexls data

        for (let i = 0; i < rowBytes; i++) {

            picData[reStart + i] = imageU8Data[start + i];

        }

    }

    jsb.saveImageData(picData, w, h, path);

}

private static toB64(arrayBuffer: ArrayBuffer): string {

    let canvas = document.createElement('canvas');

    let winSize = xdUIUtil.getViewSize();

    let width = canvas.width = Math.floor(winSize.width);

    let height = canvas.height = Math.floor(winSize.height);

    let ctx = canvas.getContext('2d');

    let imageU8Data = new Uint8Array(arrayBuffer);

    let rowBytes = width * 4;

    let rowBytesh = height * 4;

    for (let row = 0; row < rowBytesh; row++) {

        let sRow = height - 1 - row;

        let imageData = ctx.createImageData(width, 1);

        let start = sRow * rowBytes;

        for (let i = 0; i < rowBytes; i++) {

            imageData.data[i] = imageU8Data[start + i];

        }

        ctx.putImageData(imageData, 0, row);

    }

    var base64 = canvas.toDataURL("image/jpeg", 0.7); //压缩语句

    return base64;

}
2赞

请问这个 API 是你们自定义的 jsb 吗?

this.saveImageData(arrayBuffer, renderTex.width, renderTex.height, path);

另外在 3.x 版本构建的,放在原生上运行报错如下

arrayBuffer CCMTLDevice {__object_id__: 363, __native_class_name__: "CCMTLDevice", cachedUboOffsetAlignment: 256}
jsb-adapter/jsb-engine.js:2092 (see stack) Uncaught TypeError: i.device.copyFramebufferToBuffer is not a function  - [0]copyRenderTex@assets/main/index.js:3

同问,这个原生截屏的功能解决了吗

是的。我们目前通过定制引擎解决了,官方 3.4 版本会支持

spriteframe.texture=rendertexture,这样的话当屏幕变化时,sprite也会跟着变化吧

能否分享一下在3.3.2上如何实现原生截屏的吗?

具体定制需要做什么操作呢?

引擎部分改动还好,新增 API,调用原生能力即可。大概是以下几步

  1. 通过 RT 获取到对应原生的实例
  2. 原生 iOS 对应 Metal、Android 对应 GLES3 或者其他
  3. 双端基于此使用原生代码做转图片的操作就好

注意点

  1. Android 在 GLES3 上的多线程问题,可考虑关闭多线程。否则获取到的图片不符合预期 参考:再不解决就要被炒鱿鱼:3.3.1 GLES3Texture getPixelBytes 获取到的结果是花屏
  2. 安卓端通过 GLES3 获取图片耗时卡顿的问题,需要在子线程完成处理,主线程回调
  3. iOS 15 上 Metal 获取到的图片,透明背景会存在异常颜色,可通过代码处理成透明色

其他目前倒没有太大的问题