日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

這是我最近在 CodePen 上制作的 WebGL 演示案例。它可以捕獲網(wǎng)絡(luò)攝像頭的數(shù)據(jù)(或在無法訪問網(wǎng)絡(luò)攝像頭時(shí),從 placekitten 獲取備用圖像),并將其實(shí)時(shí)轉(zhuǎn)換為 ASCII 圖像藝術(shù)。

如何使用 WebGL 進(jìn)行實(shí)時(shí)視頻處理

 

為了獲得更多的復(fù)古性,我使用了 90 年代 DOS PC 中常見的 8x8 像素光柵字體(您可能會(huì)在某些 BIOS 中看到這種字體)。

要將圖像內(nèi)容映射到特定字符,我通過使用亮度圖選擇最佳匹配。我計(jì)算每個(gè) 4x4 正方形的像素。在畫板內(nèi)向下滾動(dòng)以查看亮度圖:

如何使用 WebGL 進(jìn)行實(shí)時(shí)視頻處理

 

我還為這些字體創(chuàng)建了一個(gè)編輯器: https://terabaud.github.io/pi...

若干 WebGL 基礎(chǔ)知識(shí)

我將介紹 WebGL 的一些基礎(chǔ)知識(shí),但這里僅涉及部分問題。獲取有關(guān)詳細(xì)指導(dǎo),建議您訪問 https://webglfundamentals.org

對(duì)于 WebGL,一個(gè)常見誤解是把它當(dāng)作瀏覽器中的 3D 引擎。盡管 WebGL 技術(shù)能使我們?cè)跒g覽器中提供 GPU 加速的 3D 內(nèi)容,但 WebGL 本身不是 3D 引擎。在 WebGL 之上,有專門用于 GPU 加速的 2D 或 3D 內(nèi)容的圖形庫(kù)(例如用于 2D 的 Pixi,用于 3D 的 ThreeJS)。

WebGL 本身是很基礎(chǔ)的繪圖標(biāo)準(zhǔn)庫(kù),并且是一個(gè)以 GPU 加速的方式,將點(diǎn)、線和三角形繪制到 html <canvas> 元素上的庫(kù)。

可以通過 getContext (類似于 2D canvas API )檢索 WebGL 渲染上下文:

const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');

一個(gè) WebGL 程序包含多個(gè)著色器組件,著色器是運(yùn)行在 GPU 上的代碼,它們不是用 JAVAScript 編寫的,而是具有自己的語言,稱為 GLSL(GL 著色器語言)。

GLSL 快速概覽

  • 類似 C語言,著色器程序包含 void main()
  • 變量聲明也像在 C 語言中一樣
  • 原始數(shù)據(jù)類型: int , float , double
  • 向量: vec2 , vec3 , vec4 , ...
  • 矩陣: mat2 , mat3 , mat4 , ...
  • 訪問紋理數(shù)據(jù)的類型: sampler2D
  • 內(nèi)置向量、矩陣運(yùn)算
  • 大量?jī)?nèi)置功能 , 例如,求取向量的長(zhǎng)度( length(v) )

著色器的類型

WebGL 程序中有兩種類型的著色器。

  • 頂點(diǎn)著色器計(jì)算位置。
  • 片段著色器處理柵格化。

如果您的 WebGL 程序想要在屏幕上繪制一個(gè)三角形,它會(huì)把三角形的 3 個(gè)坐標(biāo)傳遞給頂點(diǎn)著色器。然后,片段著色器的任務(wù)是用像素填充該三角形,這種逐像素處理過程非???,因?yàn)樗轻槍?duì) GPU 上的每個(gè)像素并行運(yùn)行處理的。

在我的演示案例中,我使用 4 個(gè)矢量坐標(biāo)來覆蓋適合整個(gè)屏幕的矩形,所有工作都在片段著色器中完成。

頂點(diǎn)著色器

顧名思義,頂點(diǎn)著色器存在于頂點(diǎn)。它從 JavaScript 代碼提供的緩沖區(qū)中獲取一堆數(shù)據(jù),并根據(jù)這些數(shù)據(jù)計(jì)算在畫布中的相應(yīng)位置。

以下代碼段將數(shù)據(jù)從緩沖區(qū)拉入一個(gè) attribute 變量,并將其傳遞給該 gl_Position 變量:

attribute vec3 position;
void main() {
  gl_Position = vec4(position, 1.0);
}

片段著色器

precision highp float;
void main() {
  vec2 p = gl_FragCoord.xy;  gl_FragColor = vec4(1.0, .5 + .5 * sin(p.y), .5 + .5 * sin(p.x), 1.0);
}

片段著色器針對(duì)每個(gè)片段(像素)并行運(yùn)行。在上面的示例中,片段著色器從 gl_FragCoord 變量讀取當(dāng)前像素坐標(biāo),并通過 gl_FragColor 中的 sin() 計(jì)算運(yùn)行并輸出顏色。

gl_FragColor 是一個(gè) vec4 向量,其中包含(紅色,綠色,藍(lán)色,alpha),取值各為 0 .. 1。

GLSL 變量的類型

attribute
uniformvarying

上傳圖像數(shù)據(jù)

您可以使用圖像數(shù)據(jù)訪問到著色器中的 WebGLRenderingContext,并將其上傳到 紋理 中。(另請(qǐng)參見: WebGL 基礎(chǔ)知識(shí):圖像處理 )

您可以使用 texImage2D 內(nèi)部方法 WebGLRenderingContext 將圖像數(shù)據(jù)上傳到紋理中。

// gl is the WebGLRenderingContext 
const texture = gl.createTexture()
gl.activeTexture(gl.TEXTURE0 + textureIndex);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
// more info about these parameters in the webglfundamentals
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);

您傳遞給 texImage2D 的圖像數(shù)據(jù),可以是 img 元素、視頻元素、ImageData 等。

由于視頻的圖像數(shù)據(jù)不斷變化,因此您必須在 requestAnimationFrame 動(dòng)畫循環(huán)內(nèi)更新紋理。以下是獲取完成的 texSubImage2D 。

gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video);

在著色器代碼中讀取紋理數(shù)據(jù)

您可以通過 texture 的 2Dglsl 函數(shù)訪問紋理的像素?cái)?shù)據(jù)。

當(dāng)紋理坐標(biāo)從(0,0)變?yōu)椋?,1)時(shí),圖像會(huì)上下顛倒。同時(shí),我正處于水平鏡像圖像中(就像用相機(jī)自拍一樣)。

uniform sampler2D texture0;
void main() {
  vec2 coord = 1.0 - gl_FragCoord.xy / vec2(width, height);
  gl_FragColor = texture2D(texture1, coord);
}

訪問網(wǎng)絡(luò)攝像頭

要從網(wǎng)絡(luò)攝像頭獲取圖像數(shù)據(jù),我們可以使用 video 標(biāo)簽,并使用 getUserMediaAPI :

function accessWebcam(video) {
  return new Promise((resolve, reject) => {
    const mediaConstraints = { audio: false, video: { 
        width: 1280, 
        height: 720,
        brightness: {ideal: 2} 
      }    };    navigator.mediaDevices.getUserMedia(      mediaConstraints).then(mediaStream => {
        video.srcObject = mediaStream;        video.setAttribute('playsinline', true);
        video.onloadedmetadata = (e) => {
          video.play();          resolve(video);        }      }).catch(err => {
        reject(err);      });    }  );}// 使用說明:
// const video = await accessWebcam(document.querySelector('video'));
// or via promises:
// accessWebcam(document.querySelector('video')).then(video => { ... });

要訪問網(wǎng)絡(luò)攝像頭,您可以使用 getUserMedia API 來訪問網(wǎng)絡(luò)攝像頭,如上所述。

提供后備圖像

如果用戶阻止了對(duì)網(wǎng)絡(luò)攝像頭的訪問,或者沒有可用的網(wǎng)絡(luò)攝像頭,則可以提供一個(gè)備用圖像供您使用。

我也將 new Image() 中的 onload 操作包裝成一個(gè) promise 。

function loadImage(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.crossOrigin = 'Anonymous';
    img.src = url;    img.onload = () => {
      resolve(img);    };    img.onerror = () => {
      reject(img);    };  });}

合并全部操作

為了使事情變得容易一些,我將常用的 WebGL 函數(shù)放入了我創(chuàng)建的一個(gè)小助手庫(kù) GLea 中。

它初始化 WebGL 應(yīng)用上下文,編譯 WebGL 著色器代碼,并為頂點(diǎn)著色器創(chuàng)建屬性和緩沖區(qū):

默認(rèn)情況下, position 為頂點(diǎn)著色器提供一個(gè)屬性,該屬性帶有一個(gè)緩沖區(qū),該緩沖區(qū)包含 4 個(gè) 2D 坐標(biāo),覆蓋整個(gè)屏幕上的 2 個(gè)三角形。

import GLea from 'glea.js';
const frag = ` ... `; // 片段著色器代碼
const vert = ` ... `; // 頂點(diǎn)著色器代碼
const glea = new GLea({
  shaders: [    GLea.fragmentShader(frag),    GLea.vertexShader(vert)  ]}).create();function loop(time = 0) {
  const { gl, width, height } = glea;  glea.clear();  glea.uniV('resolution', [width, height]);
  glea.uni('time', time * 1e-3);
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  requestAnimationFrame(loop);
}window.addEventListener('resize', () => {
  glea.resize();});loop(0);

結(jié)論

基本上就是這樣。我希望您喜歡閱讀本文,并對(duì)自己探索 WebGL 感到好奇。我會(huì)在這里放一些資源。

分享到:
標(biāo)簽:視頻處理
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定