卿¬æ¼ç¤ºä¸ï¼æä»¬ä»¥ä¸ä¸ä¸ªç¤ºä¾ä¸ºåºç¡ï¼å°éæçº¹çæ¿æ¢ä¸ºæ£å¨ææ¾ç mp4 è§é¢æä»¶ç帧ãå®é
ä¸ï¼è¿å¾å®¹æåå°ï¼èä¸è§çèµ·æ¥å¾æè¶£ï¼æä»¥è®©æä»¬å¼å§å§ãä½ å¯ä»¥ä½¿ç¨ç±»ä¼¼çä»£ç æ¥ä½¿ç¨ä»»ä½ç±»åçæ°æ®ï¼ä¾å¦ <canvas>
ï¼ä½ä¸ºçº¹ççæºã
ç¬¬ä¸æ¥æ¯å建å°ç¨äºæ£ç´¢è§é¢å¸§ç <video>
å
ç´ ï¼
夿³¨ï¼ 请å°ä»¥ä¸å£°ææ·»å å°âwebgl-demo.jsâèæ¬çå¼å¤´ï¼
// å½è§é¢å¯ä»¥å¤å¶å°çº¹ç䏿¶å°è¢«è®¾ç½®ä¸º true
let copyVideo = false;
夿³¨ï¼ 请å°ä»¥ä¸å½æ°æ·»å å°âwebgl-demo.jsâèæ¬ä¸ï¼
function setupVideo(url) {
const video = document.createElement("video");
let playing = false;
let timeupdate = false;
video.playsInline = true;
video.muted = true;
video.loop = true;
// çå¾
以ä¸ä¸¤ä¸ªäºä»¶
// ç¡®ä¿ video ä¸å·²ææ°æ®
video.addEventListener(
"playing",
() => {
playing = true;
checkReady();
},
true,
);
video.addEventListener(
"timeupdate",
() => {
timeupdate = true;
checkReady();
},
true,
);
video.src = url;
video.play();
function checkReady() {
if (playing && timeupdate) {
copyVideo = true;
}
}
return video;
}
é¦å
ï¼æä»¬å建ä¸ä¸ªè§é¢å
ç´ ãæä»¬å°å
¶è®¾ç½®ä¸ºèªå¨ææ¾ãéé³åå¾ªç¯ææ¾è§é¢ãç¶åï¼æä»¬è®¾ç½®äºä¸¤ä¸ªäºä»¶ä»¥ç¡®ä¿è§é¢æ£å¨ææ¾å¹¶ä¸æ¶é´è½´å·²æ´æ°ãæä»¬éè¦è¿è¡è¿ä¸¤é¡¹æ£æ¥ï¼å ä¸ºå¦æå°å°æ å¯ç¨æ°æ®çè§é¢ä¸ä¼ å° WebGLï¼å®å°äº§çéè¯¯ãæ£æ¥è¿ä¸¤ä¸ªäºä»¶å¯ç¡®ä¿æå¯ç¨æ°æ®ï¼å¹¶ä¸å¯ä»¥å®å
¨å°å¼å§å°è§é¢ä¸ä¼ å° WebGL 纹çãå¨ä¸é¢ç代ç ä¸ï¼æä»¬ç¡®è®¤æ¯å¦åæ¶åçäºè¿ä¸¤ä¸ªäºä»¶ã妿æ¯è¿æ ·ï¼æä»¬å°å
¨å±åé设置 copyVideo
为 trueï¼ä»¥è¡¨ç¤ºå¯ä»¥å®å
¨å°å¼å§å°è§é¢å¤å¶å°çº¹çã
æåï¼æä»¬å° src
屿§è®¾ç½®ä¸º start å¹¶è°ç¨ play
以å¼å§å è½½åææ¾è§é¢ã
æ¥ä¸æ¥çæ´æ¹æ¯åå§å纹çï¼è¿å¾ç®åï¼å 为å®ä¸åéè¦å è½½å¾åæä»¶ãç¸åï¼å®æåçåªæ¯å建ä¸ä¸ªç©ºç纹ç对象ï¼å¨å ¶ä¸æ¾ç½®ä¸ä¸ªåç´ ï¼ç¶åè®¾ç½®å ¶è¿æ»¤æ¡ä»¶ä»¥ä¾åç»ä½¿ç¨ï¼
夿³¨ï¼ 请å°âwebgl-demo.jsâä¸ç loadTexture()
彿°æ¿æ¢ä¸ºä»¥ä¸ä»£ç ï¼
function initTexture(gl) {
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// å 为è§é¢å¿
é¡»éè¿äºèç½ä¸è½½
// å¯è½éè¦ä¸äºæ¶é´æè½åå¤å¥½
// å æ¤å¨çº¹ç䏿¾ç½®ä¸ä¸ªåç´ ï¼ä»¥ä¾¿æä»¬
// å¯ä»¥ç«å³ä½¿ç¨å®ã
const level = 0;
const internalFormat = gl.RGBA;
const width = 1;
const height = 1;
const border = 0;
const srcFormat = gl.RGBA;
const srcType = gl.UNSIGNED_BYTE;
const pixel = new Uint8Array([0, 0, 255, 255]); // ä¸éæçèè²
gl.texImage2D(
gl.TEXTURE_2D,
level,
internalFormat,
width,
height,
border,
srcFormat,
srcType,
pixel,
);
// å
³é mips å¹¶å°å
裹ï¼wrappingï¼è®¾ç½®ä¸ºè¾¹ç¼åå²ï¼clamp to edgeï¼
// è¿æ ·æ 论è§é¢ç尺寸å¦ä½ï¼é½å¯ä»¥æ£å¸¸å·¥ä½ã
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);
return texture;
}
夿³¨ï¼ 请å°ä»¥ä¸å½æ°æ·»å å°âwebgl-demo.jsâä¸ï¼
function updateTexture(gl, texture, video) {
const level = 0;
const internalFormat = gl.RGBA;
const srcFormat = gl.RGBA;
const srcType = gl.UNSIGNED_BYTE;
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(
gl.TEXTURE_2D,
level,
internalFormat,
srcFormat,
srcType,
video,
);
}
ä½ ä¹åå·²ç»çè¿æ¤ä»£ç ãå®ä¸ä¸ä¸ä¸ªç¤ºä¾ä¸ç image onload 彿°å ä¹ç¸åââé¤äºæä»¬è°ç¨ texImage2D()
æ¶ä¼ å
¥çæ¯ <video>
å
ç´ ï¼è䏿¯ Image
对象ãWebGL ç¥éå¦ä½è·åå½å帧并å°å
¶ç¨ä½çº¹çã
ç¶åï¼æä»¬éè¦å¨ main()
彿°ä¸è°ç¨å 个æ°ç彿°ã
夿³¨ï¼ å¨ä½ ç main()
彿°ä¸ï¼å°è°ç¨ loadTexture()
çä»£ç æ¿æ¢ä¸ºä»¥ä¸å
容ï¼
const texture = initTexture(gl);
const video = setupVideo("Firefox.mp4");
夿³¨ï¼ ä½ è¿éè¦å° Firefox.mp4 æä»¶ä¸è½½å°ä½ æ¬å°ä¸ä½ ç JavaScript æä»¶ç¸åçç®å½ä¸ã
夿³¨ï¼ å¨ä½ ç main()
彿°ä¸ï¼å° render()
彿°æ¿æ¢ä¸ºä»¥ä¸å
容ï¼
// éå¤ç»å¶åºæ¯
function render(now) {
now *= 0.001; // 转æ¢ä¸ºç§
deltaTime = now - then;
then = now;
if (copyVideo) {
updateTexture(gl, texture, video);
}
drawScene(gl, programInfo, buffers, texture, cubeRotation);
cubeRotation += deltaTime;
requestAnimationFrame(render);
}
妿 copyVideo
为çï¼æä»¬å°ä¼å¨è°ç¨ drawScene()
ä¹åè°ç¨ updateTexture()
ã
è¿å°±æ¯å®ç°å¨ç»çº¹ççå ¨é¨å 容ï¼
æ¥ç宿´ç代ç | 卿°é¡µé¢ä¸æå¼è¿ä¸ªæ¼ç¤º
åè§RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4