Video Uploading

代碼分析說明:

import { makeSample, SampleInit } from '../../components/SampleLayout';

import fullscreenTexturedQuadWGSL from '../../shaders/fullscreenTexturedQuad.wgsl';
import sampleExternalTextureWGSL from '../../shaders/sampleExternalTexture.frag.wgsl';

const init: SampleInit = async ({ canvas, pageState, gui }) => {
  // Set video element
 //  創(chuàng)建一個(gè)視頻元素
  const video = document.createElement('video');
  video.loop = true;
  video.autoplay = true;
  video.muted = true;
  video.src = '../assets/video/pano.webm';
 // 加載完成后自動(dòng)播放視頻
  await video.play();

  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  if (!pageState.active) return;

  const context = canvas.getContext('webgpu') as GPUCanvasContext;
  const devicePixelRatio = window.devicePixelRatio;
  canvas.width = canvas.clientWidth * devicePixelRatio;
  canvas.height = canvas.clientHeight * devicePixelRatio;
  const presentationFormat = navigator.gpu.getPreferredCanvasFormat();

  context.configure({
    device,
    format: presentationFormat,
    alphaMode: 'premultiplied',
  });

  const pipeline = device.createRenderPipeline({
    layout: 'auto',
    vertex: {
      module: device.createShaderModule({
        code: fullscreenTexturedQuadWGSL,
      }),
      entryPoint: 'vert_main',
    },
    fragment: {
      module: device.createShaderModule({
        code: sampleExternalTextureWGSL,
      }),
      entryPoint: 'main',
      targets: [
        {
          format: presentationFormat,
        },
      ],
    },
    primitive: {
      topology: 'triangle-list',
    },
  });

  const sampler = device.createSampler({
    magFilter: 'linear',
    minFilter: 'linear',
  });

  const settings = {
    requestFrame: 'requestAnimationFrame',
  };

  gui.add(settings, 'requestFrame', [
    'requestAnimationFrame',
    'requestVideoFrameCallback',
  ]);

  function frame() {
    // Sample is no longer the active page.
    if (!pageState.active) return;

    const uniformBindGroup = device.createBindGroup({
      layout: pipeline.getBindGroupLayout(0),
      entries: [
        {
          binding: 1,
          resource: sampler,
        },
        {
          binding: 2,
           // 使用 importExternalTexture 綁定視頻
          resource: device.importExternalTexture({
            source: video,
          }),
        },
      ],
    });

    const commandEncoder = device.createCommandEncoder();
    const textureView = context.getCurrentTexture().createView();

    const renderPassDescriptor: GPURenderPassDescriptor = {
      colorAttachments: [
        {
          view: textureView,
          clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
          loadOp: 'clear',
          storeOp: 'store',
        },
      ],
    };

    const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(0, uniformBindGroup);
    passEncoder.draw(6);
    passEncoder.end();
    device.queue.submit([commandEncoder.finish()]);
  
   
    if (settings.requestFrame == 'requestVideoFrameCallback') {
      // 根據(jù)視頻播放的回調(diào)渲染
      video.requestVideoFrameCallback(frame);
    } else {
      // 瀏覽器的逐幀回調(diào)
      requestAnimationFrame(frame);
    }
  }
};

頂點(diǎn)著色器

@group(0) @binding(0) var mySampler : sampler;
@group(0) @binding(1) var myTexture : texture_2d<f32>;

struct VertexOutput {
  @builtin(position) Position : vec4<f32>,
  @location(0) fragUV : vec2<f32>,
}

@vertex
fn vert_main(@builtin(vertex_index) VertexIndex : u32) -> VertexOutput {
  // 頂點(diǎn)數(shù)據(jù)為 quad
  const pos = array(
    vec2( 1.0,  1.0),  // 右上
    vec2( 1.0, -1.0),  // 右下
    vec2(-1.0, -1.0),  // 左下
    vec2( 1.0,  1.0),   // 右上
    vec2(-1.0, -1.0),  // 右下
    vec2(-1.0,  1.0),  // 左上
  );
// 對(duì)于的UV 坐標(biāo), 左上是 0 0 點(diǎn)
  const uv = array(
    vec2(1.0, 0.0),    
    vec2(1.0, 1.0),
    vec2(0.0, 1.0),
    vec2(1.0, 0.0),
    vec2(0.0, 1.0),
    vec2(0.0, 0.0),  
  );

  var output : VertexOutput;
  output.Position = vec4(pos[VertexIndex], 0.0, 1.0);
  output.fragUV = uv[VertexIndex];
  return output;
}

@fragment
fn frag_main(@location(0) fragUV : vec2<f32>) -> @location(0) vec4<f32> {
  return textureSample(myTexture, mySampler, fragUV);
}

片元著色器

@group(0) @binding(1) var mySampler: sampler;
@group(0) @binding(2) var myTexture: texture_external;

@fragment
fn main(@location(0) fragUV : vec2<f32>) -> @location(0) vec4<f32> {
// 從紋理中采樣顏色
  return textureSampleBaseClampToEdge(myTexture, mySampler, fragUV);
}

總結(jié)步驟:

  1. 該示例主要是如何將視頻加入到WebGPU渲染中
  2. 加載視頻
  3. 在createBindGroup中,綁定紋理采用device.importExternalTexture({ source: video, }
  4. 頂點(diǎn)數(shù)據(jù)定位為NDC坐標(biāo)即可,
  5. 逐幀渲染使用盏道,視頻回調(diào)video.requestVideoFrameCallback 或者瀏覽器自帶的requestAnimationFrame
  6. 在片元著色器中萤晴,紋理的的類型為texture_external,需要注意一下
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胀茵,一起剝皮案震驚了整個(gè)濱河市社露,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琼娘,老刑警劉巖峭弟,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異脱拼,居然都是意外死亡瞒瘸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門熄浓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來情臭,“玉大人,你說我怎么就攤上這事赌蔑「┰冢” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵惯雳,是天一觀的道長朝巫。 經(jīng)常有香客問我鸿摇,道長石景,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任拙吉,我火速辦了婚禮潮孽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘筷黔。我一直安慰自己往史,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布佛舱。 她就那樣靜靜地躺著椎例,像睡著了一般。 火紅的嫁衣襯著肌膚如雪请祖。 梳的紋絲不亂的頭發(fā)上订歪,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音肆捕,去河邊找鬼刷晋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的眼虱。 我是一名探鬼主播喻奥,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捏悬!你這毒婦竟也來了撞蚕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤过牙,失蹤者是張志新(化名)和其女友劉穎诈豌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抒和,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矫渔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摧莽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庙洼。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖镊辕,靈堂內(nèi)的尸體忽然破棺而出油够,到底是詐尸還是另有隱情,我是刑警寧澤征懈,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布石咬,位于F島的核電站,受9級(jí)特大地震影響卖哎,放射性物質(zhì)發(fā)生泄漏鬼悠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一亏娜、第九天 我趴在偏房一處隱蔽的房頂上張望焕窝。 院中可真熱鬧,春花似錦维贺、人聲如沸它掂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虐秋。三九已至,卻和暖如春垃沦,著一層夾襖步出監(jiān)牢的瞬間客给,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工栏尚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留起愈,地道東北人只恨。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像抬虽,于是被迫代替她去往敵國和親官觅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 圖形API簡(jiǎn)介 OpenGL(Open Graphics Library) 是一個(gè)跨編程語言阐污,跨平臺(tái)的編程語言休涤,跨...
    砌豬圈的程序員閱讀 643評(píng)論 0 0
  • 原創(chuàng):知識(shí)探索型文章創(chuàng)作不易,請(qǐng)珍惜笛辟,之后會(huì)持續(xù)更新功氨,不斷完善個(gè)人比較喜歡做筆記和寫總結(jié),畢竟好記性不如爛筆頭哈哈...
    時(shí)光啊混蛋_97boy閱讀 959評(píng)論 0 4
  • 使用深度和法線紋理 獲取深度和法線紋理 背后原理 深度紋理實(shí)際就是一張渲染紋理手幢,只不過它里面存儲(chǔ)的像素值不是顏色值...
    BacteriumFox閱讀 825評(píng)論 0 0
  • 本文繼續(xù)對(duì)《UnityShader入門精要》——馮樂樂 第十三章 使用深度和法線紋理 進(jìn)行學(xué)習(xí)參考第13章 使用深...
    合肥黑閱讀 849評(píng)論 0 1
  • 屏幕后處理技術(shù) 很多信息受光照影響和別的影響捷凄。在一些操作計(jì)算時(shí)不時(shí)很準(zhǔn)確。比較邊緣檢測(cè)围来。另外一種更好的辦法就是利用...
    李偌閑閱讀 2,448評(píng)論 0 2