我们目前使用的playcanvas引擎渲染3D场景,在AR开发时,我们已经定位到如果不使用VKFrame.getCameraTexture方法,模型可以正常渲染,使用该方法会导致部分模型材质无法正常渲染(全变成黑色)。
我们参考的是官方”小程序示例“里的代码。链接:https://github.com/wechat-miniprogram/miniprogram-demo/blob/master/miniprogram/packageAPI/pages/ar/plane-ar/yuvBehavior.js
在此,我想请问该方法是否针对WebGLContext有过操作?具体操作了哪些东西?我们需要再校正过来,万分谢谢。
你好,麻烦提供出现问题的具体机型、微信版本号、系统版本号,以及能复现问题的代码片段(https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html)
设备详情:
机型:华为mate30pro
微信版本号:8.0.25
系统版本号:HarmonyOS 2.0.0.273
(iPhone12 Pro是同样的问题)
复现步骤:
以下列举3种情况,只有yuvBehavior.js里的renderGL方法不同。
第一种情况参考第1,2图片,使用官方小程序示例的renderGL方法,相机渲染成功,但是模型材质全部为黑色。
第二种情况参考第3,4图片,renderGL方法只使用了getCameraTexture方法,没有渲染相机,模型材质为黑,所以全屏黑色。
第三种情况参考第5,6图片,renderGL方法为空,模型正常显示。
如上,第二种情况与第三种情况的不同之处只在于调用了VKFrame.getCameraTexture(gl)方法,就导致了模型材质无法正常渲染。
所以,我想了解一下该方法针对WebGLContext有什么操作?
const bindingTexture5 = gl.getParameter(gl.TEXTURE_BINDING_2D)
gl.bindTexture(gl.TEXTURE_2D, yTexture)
将模型的纹理 往后点的序号绑定一下
问题解决了,记录一下:
输出一下 `VKFrame.getCameraTexture` 的方法,内容如下:
function getCameraTexture(e, t = "yuv") { if (!this[jse].native || !this[jse].session) return null; "string" == typeof e && (t = e, e = null); var r = this[jse].session; if (!(e = e || r[Vse].options.gl)) return null; if ("yuv" === t) { var n = r[Vse].yTexture; n || (n = e.createTexture()); var i, a = r[Vse].uvTexture; a || (a = e.createTexture()); var o = !1; if (he && Use) { o = this[jse].native.updateCameraYUVTextureIOS(n, a, e) } else { i = this[jse].native.getCameraYUVBuffer() } e.bindTexture(e.TEXTURE_2D, n); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE); if (i) { e.texImage2D(e.TEXTURE_2D, 0, e.LUMINANCE, i.width, i.height, 0, e.LUMINANCE, e.UNSIGNED_BYTE, new Uint8Array(i.yAddress)) } r[Vse].yTexture = n; n._gl = e; e.bindTexture(e.TEXTURE_2D, null); e.bindTexture(e.TEXTURE_2D, a); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE); e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE); if (i) { e.texImage2D(e.TEXTURE_2D, 0, e.LUMINANCE_ALPHA, i.width / 2, i.height / 2, 0, e.LUMINANCE_ALPHA, e.UNSIGNED_BYTE, new Uint8Array(i.uvAddress)) } r[Vse].uvTexture = a; a._gl = e; e.bindTexture(e.TEXTURE_2D, null); return { yTexture: n, uvTexture: a } } return null }
可以看到,创建纹理后直接绑定了,并没有指定激活纹理序号,所以默认绑定到了 `gl.TEXTURE0`。
而这时候模型的贴图也使用了这个序号,第一帧渲染的时候应该是没有问题的,问题是在第二帧的时候,这个纹理又被重新更新覆盖了。
解决办法很简单,在调用 `getCameraTexture` 前提前激活一个不会用到的纹理号:
gl.disable(gl.DEPTH_TEST); gl.activeTexture(gl.TEXTURE0 + 7); // 比如这样 const { yTexture, uvTexture } = frame.getCameraTexture(gl, "yuv");
如此,问题就解决了。
哎,不开源,只能这样迂回 hack 了。
普通模型加个贴图 都出不来 这种东西 真的是一堆问题