如何将HTML5播放器视频绘制投影到Unity WebGL的3D平面上
问题解决方案
核心错误点
- 你错误使用了
WebGL2RenderingContext.texImage3D()接口:该接口用于创建三维体积纹理,你要上传的视频帧是普通二维图像,直接使用texImage2D()即可,这是你代码报错的首要原因。 - 你提到的「本地自有文件无CORS问题」认知有误:如果直接通过
file://协议打开HTML文件,就算是本地资源也会触发浏览器的跨源安全限制,抛出安全异常,你需要用本地HTTP服务启动项目访问。
可直接运行的修改后代码
我调整了你的JS逻辑,补充了WebGL纹理初始化的必要步骤,修改后代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebGL</title> <style> body { background-color: aquamarine; } </style> </head> <body> <video muted autoplay width="480" height="270" crossorigin="anonymous"> <source src="./test.mp4" type="video/mp4" /> </video> <br> <canvas width="1080" height="720"></canvas> <button onclick="captureVideoFrame()">Capture</button> <script> let gl, videoTexture; // 初始化WebGL纹理 function initGL() { const canvas = document.querySelector("canvas"); gl = canvas.getContext("webgl2"); // 创建纹理对象 videoTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, videoTexture); // 设置纹理参数,避免非2的幂尺寸视频报错 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); } function captureVideoFrame() { const video = document.querySelector("video"); // 首次调用初始化GL if (!gl) initGL(); gl.bindTexture(gl.TEXTURE_2D, videoTexture); // 直接上传视频帧到2D纹理 gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video ); // 这里后续可以加纹理传递给Unity的逻辑 } // 可选:如果要逐帧更新,用requestAnimationFrame自动调用 function updateFrameLoop() { captureVideoFrame(); requestAnimationFrame(updateFrameLoop); } // 视频可播放后启动逐帧更新 document.querySelector('video').addEventListener('canplay', () => { updateFrameLoop(); }) </script> </body> </html>
Unity侧对接说明
你不需要手动操作Unity底层的WebGL上下文,Unity已经提供了对应能力:
- 你在Unity中创建一个
RenderTexture或者普通2D纹理,把纹理ID传递到JS侧 - JS侧可以直接用
GLctx.bindTexture(GLctx.TEXTURE_2D, 纹理ID)绑定Unity的纹理,再执行texImage2D上传视频帧即可 - 逐帧更新的性能完全达标,1080p@60fps的视频更新不会造成明显性能损耗,浏览器底层对视频帧上传到WebGL纹理有硬件加速优化
HLS适配说明
你计划用hls.js的方案完全可行,只需要在HTML的video标签初始化逻辑中加入hls.js的加载代码即可,不需要修改纹理上传的核心逻辑,视频帧读取的接口是统一的。
内容的提问来源于stack exchange,提问作者verified_tinker
相关产品推荐
相关产品推荐

