AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

PixiJS 源碼解讀:繪制矩形的渲染過程講解

來源: 責編: 時間:2023-10-10 18:32:13 285觀看
導讀大家好,我是前端西瓜哥。之前寫了一篇 PixiJS 繪制矩形,簡單說了一下 PixiJS 是怎么繪制矩形的。《PixiJS 源碼解讀:繪制矩形,底層都做了什么?》它更多的講解上層的東西,沒花太多筆墨描繪底層渲染的流程。所以我寫了這篇文

hvu28資訊網——每日最新資訊28at.com

大家好,我是前端西瓜哥。hvu28資訊網——每日最新資訊28at.com

之前寫了一篇 PixiJS 繪制矩形,簡單說了一下 PixiJS 是怎么繪制矩形的。hvu28資訊網——每日最新資訊28at.com

《PixiJS 源碼解讀:繪制矩形,底層都做了什么?》hvu28資訊網——每日最新資訊28at.com

它更多的講解上層的東西,沒花太多筆墨描繪底層渲染的流程。所以我寫了這篇文章,對渲染流程進行補充講解。hvu28資訊網——每日最新資訊28at.com

PixiJS 版本為 7.2.4。hvu28資訊網——每日最新資訊28at.com

要求讀者熟悉 WebGL 的基礎知識。hvu28資訊網——每日最新資訊28at.com

本文會 以繪制設置了填充和描邊的矩形為例子,看底層 WebGL 的調用執行。hvu28資訊網——每日最新資訊28at.com

業務層代碼:hvu28資訊網——每日最新資訊28at.com

const app = new PIXI.Application({  width: 500,  height: 300,  background: "#cc0", //(土黃色)});document.body.appendChild(app.view);const graph = new PIXI.Graphics();graph.beginFill(0xff0044); // 紅色填充色graph.lineStyle({ color: "blue", width: 4 }); // 藍色描邊graph.drawRect(90, 70, 300, 100);app.stage.addChild(graph);

繪制結果為:hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

創建 gl

第一步是創建 gl 對象,上下文類型優先使用 "webgl2"。hvu28資訊網——每日最新資訊28at.com

如果不支持,會降級為 "webgl"、"experimental-webgl"。hvu28資訊網——每日最新資訊28at.com

gl = canvas.getContext("webgl2", options);

gl 在 renderer 渲染器初始化的時候構建的,可通過 app.renderer.gl 拿到。hvu28資訊網——每日最新資訊28at.com

構建著色器代碼片段

定義 頂點著色器 和 片元著色器。hvu28資訊網——每日最新資訊28at.com

著色器(Shader)是一種類 C 語言 GLSL,用于描述需要繪制的 頂點信息和顏色信息。hvu28資訊網——每日最新資訊28at.com

著色器模板

首先是 字符串模板,等著根據配置填充成一個完整的著色器代碼片段。hvu28資訊網——每日最新資訊28at.com

頂點著色器的模板(后面會基于它生成真正可用的著色器)位于 packages/core/src/batch/texture.vert 中。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

batch 文件夾都是和 批量繪制 有關的邏輯,批量、減少 draw call 正是 PixiJS 高效繪制的秘訣。hvu28資訊網——每日最新資訊28at.com

precision highp float;attribute vec2 aVertexPosition;attribute vec2 aTextureCoord;attribute vec4 aColor;attribute float aTextureId;uniform mat3 projectionMatrix;uniform mat3 translationMatrix;uniform vec4 tint;varying vec2 vTextureCoord;varying vec4 vColor;varying float vTextureId;void main(void){    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);    vTextureCoord = aTextureCoord;    vTextureId = aTextureId;    vColor = aColor * tint;}

片元著色器和顏色有關。hvu28資訊網——每日最新資訊28at.com

varying vec2 vTextureCoord;varying vec4 vColor;varying float vTextureId;uniform sampler2D uSamplers[%count%];void main(void){    vec4 color;    %forloop%    gl_FragColor = color * vColor;}

這里的 %count% 和%forloop% 是占位符,會在之后進行替換。hvu28資訊網——每日最新資訊28at.com

最終著色器代碼片段

在 renderer 初始化時,上面的模板會進行一系列的改造,兩個著色器最終轉換為下面的樣子。hvu28資訊網——每日最新資訊28at.com

頂點著色器(Vertex Shader)和頂點的位置、大小有關。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

補充一些簡單注釋說明。hvu28資訊網——每日最新資訊28at.com

頂點著色器

precision highp float; // 浮點數使用高精度#define SHADER_NAME pixi-shader-2precision highp float;attribute vec2 aVertexPosition; // 頂點位置 x 和 yattribute vec2 aTextureCoord; // 紋理坐標,會傳給片元著色器attribute vec4 aColor; // 顏色,rgba,會傳給片元著色器attribute float aTextureId; // 紋理單元 ID,會傳給片元著色器uniform mat3 projectionMatrix; // 投影矩陣uniform mat3 translationMatrix; // 平移變換矩陣uniform vec4 tint; // 改變顏色,實現濾鏡效果,會和 aColor 相乘傳給片元著色器varying vec2 vTextureCoord; // varing 都是用來傳遞的varying vec4 vColor;varying float vTextureId;void main(void){    //  進行一系列矩陣乘法運算,將最后的點傳給內置的著色器變量,設置點的位置    gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);   // 下面都是要傳給片元著色器的變量    vTextureCoord = aTextureCoord;    vTextureId = aTextureId;    vColor = aColor * tint;}

片元著色器

片元著色器(Fragment Shader)用于描述頂點圍成區域的像素顏色。hvu28資訊網——每日最新資訊28at.com

下面是片元著色器的最終代碼,同樣我會加一些注釋說明hvu28資訊網——每日最新資訊28at.com

precision mediump float;#define SHADER_NAME pixi-shader-2varying vec2 vTextureCoord; // 紋理坐標,varying vec4 vColor; // 顏色varying float vTextureId; // 使用哪一個紋理采樣器uniform sampler2D uSamplers[16]; // 16 個紋理采樣器void main(void){  vec4 color;   if(vTextureId < 0.5) {    // 從紋理采樣器(比如圖片轉換過來的像素點集合)中,提取特定位置的像素點    color = texture2D(uSamplers[0], vTextureCoord);  }else if(vTextureId < 1.5) {    color = texture2D(uSamplers[1], vTextureCoord);  }  // ...  } else {    color = texture2D(uSamplers[15], vTextureCoord);  }    // 疊加顏色值,和紋理采樣器取得的顏色值,賦值給片元著色器內置變量  gl_FragColor = color * vColor;}

如果沒有設置紋理,PixiJS 會給一個默認的兜底用紋理對象,一個 16x16 的白色方形。hvu28資訊網——每日最新資訊28at.com

這兩個著色器片段會保存到 Shader 實例中,放到 app.render.shader 下。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

編譯著色器程序

第一次調用 renderer 渲染器 render 方法時,PixiJS 會 創建頂點著色器對象和片元著色器對象。hvu28資訊網——每日最新資訊28at.com

這些邏輯是在 generateProgram 方法中實現的。該方法的核心代碼:hvu28資訊網——每日最新資訊28at.com

function generateProgram(gl, program) {  //(1)創建頂點著色器對象、片元著色器對象等  const glVertShader = compileShader(gl, gl.VERTEX_SHADER, program.vertexSrc);  const glFragShader = compileShader(    gl,    gl.FRAGMENT_SHADER,    program.fragmentSrc  );  // 創建程序對象  const webGLProgram = gl.createProgram();  //(2)綁定 attribute  // keys 為 ['aColor', 'aTextureCoord', 'aTextureId', 'aVertexPosition']  for (let i = 0; i < keys.length; i++) {    program.attributeData[keys[i]].location = i;    // 將屬性綁定到頂點著色器的制定位置    // 如:gl.bindAttribLocation(gl.program, 0, "aColor");    gl.bindAttribLocation(webGLProgram, i, keys[i]);  }  // 刪除著色器對象,釋放內存  gl.deleteShader(glVertShader);  gl.deleteShader(glFragShader);  //(3)綁定 uniformLocation(準確來說是拿地址,還沒正式綁定)  // 屬性(對應 i 變量)有:projectionMatrix、tint、translationMatrix、uSamplers  for (const i in program.uniformData) {    const data = program.uniformData[i];    uniformData[i] = {      location: gl.getUniformLocation(webGLProgram, i),      value: defaultValue(data.type, data.size),    };  }  const glProgram = new GLProgram(webGLProgram, uniformData);  return glProgram;}

分成三個主要步驟。hvu28資訊網——每日最新資訊28at.com

創建著色器對象、程序對象。hvu28資訊網——每日最新資訊28at.com

compileShader 實現:hvu28資訊網——每日最新資訊28at.com

function compileShader(gl, type, src) {  const shader = gl.createShader(type);  gl.shaderSource(shader, src);  gl.compileShader(shader);    gl.attachShader(webGLProgram, glVertShader);  gl.attachShader(webGLProgram, glFragShader);  // ...  gl.linkProgram(webGLProgram);  return shader;}

綁定 attribute 類型的變量 (但此時還沒傳入 Buffer 數據,只是設置了如何訪問等操作);hvu28資訊網——每日最新資訊28at.com

綁定 uniform 類型的變量。hvu28資訊網——每日最新資訊28at.com

之后在 app.renderer.shader.bind 方法內執行下面代碼,應用剛剛創建的程序對象。hvu28資訊網——每日最新資訊28at.com

this.gl.useProgram(glProgram.program);

渲染階段

前面做的是準備工作,編譯著色器。hvu28資訊網——每日最新資訊28at.com

接下來就是渲染階段。hvu28資訊網——每日最新資訊28at.com

PIXI.Ticker 定時器會在渲染下一幀前調用 renderer.render 方法,進入 WebGL 的渲染流程。hvu28資訊網——每日最新資訊28at.com

清空畫布填充背景色

首先是清空畫布。hvu28資訊網——每日最新資訊28at.com

// 入口方法:renderer.renderTexture.clearclass ObjectRendererSystem {  render(displayObject, options) {    // ...    // (1) 清空畫布,并指定顏色    renderer.renderTexture.clear();    // ...  }}

它會執行 clear 方法hvu28資訊網——每日最新資訊28at.com

class FramebufferSystem {  clear(r, g, b, a, mask = BUFFER_BITS.COLOR | BUFFER_BITS.DEPTH) {    const { gl } = this;    // 背景色 #cc0 轉換為 rbga 格式:    // (0.800000011920929, 0.800000011920929, 0, 1)    gl.clearColor(r, g, b, a);    // 清空顏色和深度緩存    gl.clear(mask);  }}

遞歸調用 render

遞歸圖形樹(app.stage),調用它們(繼承了 IRenderableObject 接口類型)的 render 方法,它們會拿到 renderer 對象,然后執行自己的渲染邏輯。hvu28資訊網——每日最新資訊28at.com

// app.stage 是 Container 實例class Container extends DisplayObject {  render(renderer) {    // ...    this._render(renderer); // 真正的渲染邏輯    for (let i = 0, j = this.children.length; i < j; ++i) {      this.children[i].render(renderer);    }  }}

對于前文的示例代碼,會分析矩形屬性,構建頂點和片元數據,然后執行 WebGL 的繪制 API。hvu28資訊網——每日最新資訊28at.com

對矩形三角化,構建頂點和片元數據

先基于 x、y、width、height 計算出矩形的 4 個頂點放到 points。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

然后進行三角化。三角化就是將圖形轉換為對應的三角形的組合。hvu28資訊網——每日最新資訊28at.com

所謂圖形的渲染,其實就是繪制一個個小的三角形,組成特定的形狀。這些三角形的點,根據不同圖形(比如矩形和圓形),需要用不同算法去計算出來,然后把數據通過 WebGL 命令交給 GPU,讓它幫我們繪制出來。hvu28資訊網——每日最新資訊28at.com

首先是填充的三角化(對應  buildRectangle.triangulate() )。hvu28資訊網——每日最新資訊28at.com

基于前面的 4 個點得到填充塊的 4 個點,并設置對應的索引值 indices,之后調用 gl.drawElements() 需要用到。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

接著是描邊的三角化(對應 buildLine())。hvu28資訊網——每日最新資訊28at.com

下面是繪制描邊的代碼片段:hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

PixiJS 的計算邏輯很復雜,這是因為涉及到連接方式、末端樣式的情況。hvu28資訊網——每日最新資訊28at.com

同樣,也要計算它的頂點、索引、紋理坐標。hvu28資訊網——每日最新資訊28at.com

西瓜哥我將最終的填充和描邊產生的點,做了一下可視化。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

用的是 desmos 可視化工具,這里給一下這個可視化鏈接:hvu28資訊網——每日最新資訊28at.com

https://www.desmos.com/calculator/r3dwqeweu2?lang=zh-CN。hvu28資訊網——每日最新資訊28at.com

最后計算好的三角化數據會保存到 graph 對象的 batches 數組下(batches 表示要批量處理的意思)。hvu28資訊網——每日最新資訊28at.com

batch 對象包括頂點坐標(vertexData)、顏色(_batchRGB)、索引(indices)和紋理坐標(uvs)。hvu28資訊網——每日最新資訊28at.com

下面是填充色對應的數據:hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

批量渲染

這里產生了兩個 batch 對象(對應填充和描邊),然后遍歷傳給 BatchRender 類的 render 方法。說是 render 方法,其實并不立即 render,而是將 batch 對象的數據解讀和保存起來,之后 flush 時才正式將數據加到 WebGL 里。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

這些屬性會組合拼裝在一個類型數組里。6 個一組,逐頂點繪制。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

傳完后,會調用 BatchRender 類的 flush 方法,將頂點數據和索引數組通過 gl.bufferData() 進行綁定。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

綁定 uniform 值

在 ShaderSystem 類的 syncUniforms 中,會依次設置好各個 uniform 變量:tint、translationMatrix、uSamplers、projectionMatrix。hvu28資訊網——每日最新資訊28at.com

class ShaderSystem {    syncUniforms(group, glProgram, syncData) {    // 生成同步 uniform 的函數(不同 uniform 的函數不同)    const syncFunc =         group.syncUniforms[this.shader.program.id] ||         this.createSyncGroups(group);    // 同步!    syncFunc(glProgram.uniformData, group.uniforms, this.renderer, syncData);  }  createSyncGroups(group) {    const id = this.getSignature(group, this.shader.program.uniformData, "u");    if (!this.cache[id]) {      this.cache[id] = generateUniformsSync(group, this.shader.program.uniformData);    }    group.syncUniforms[this.shader.program.id] = this.cache[id];    return group.syncUniforms[this.shader.program.id];  }  }

下面是設置 tint 的方法:hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

綁定紋理

綁定紋理。hvu28資訊網——每日最新資訊28at.com

class TextureSystem {  bind(texture, location = 0) {    const { gl } = this;    // 開啟    gl.activeTexture(gl.TEXTURE0 + location);    // ...    gl.bindTexture(texture.target, glTexture.texture);    // ...  }}

因為示例并不繪制圖片,PixiJS 會提供默認的的白色紋理對象(所有值都是 1),這樣顏色值和其相乘,結果還是原來的顏色值。hvu28資訊網——每日最新資訊28at.com

渲染

最后調用 drawBatches 進行繪制。hvu28資訊網——每日最新資訊28at.com

drawBatches() {  const dcCount = this._dcIndex;  const { gl, state: stateSystem } = this.renderer;  const drawCalls = _BatchRenderer._drawCallPool;  let curTexArray = null;  for (let i = 0; i < dcCount; i++) {    const { texArray, type, size, start, blend } = drawCalls[i];    if (curTexArray !== texArray) {      curTexArray = texArray;      // 剛剛提到的紋理綁定邏輯      this.bindAndClearTexArray(texArray);    }    this.state.blendMode = blend;    stateSystem.set(this.state);    // 繪制 API    gl.drawElements(type, size, gl.UNSIGNED_SHORT, start * 2);  }}

最后我們就繪制出一個有填充和描邊的矩形了。hvu28資訊網——每日最新資訊28at.com

hvu28資訊網——每日最新資訊28at.com

之后 Ticker 會不斷地在繪制下一幀時調用 renderer 的 render 方法進行渲染,如果圖形沒改變(比如通過 dirtyId 和 cacheDirty 是否相同判斷),我們會跳過三角化的環節,使用緩存好的數據去繪制渲染。hvu28資訊網——每日最新資訊28at.com

結尾

PixiJS 繪制圖形使用了 WebGL,為了利用 GPU 的并行能力,需要給著色器一次性提供盡可能多的頂點和顏色信息。hvu28資訊網——每日最新資訊28at.com

PixiJS 提供了一些基礎圖形,比如矩形。繪制時會根據圖形屬性信息進行三角化,最后將所有的信息組合起來,一次性提供給 WebGL。hvu28資訊網——每日最新資訊28at.com

這篇文章其實斷斷續續寫了好久,PixiJS 里的彎彎道道挺多的,經常調試了半天就是找不著北了,一度擱置。最后還是硬著頭皮不斷地調試和思考,總算把這篇文章結束掉了。hvu28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-12747-0.htmlPixiJS 源碼解讀:繪制矩形的渲染過程講解

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Java 集合框架超詳細!

下一篇: Springboot整合Hutool自定義注解實現數據脫敏

標簽:
  • 熱門焦點
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 每天一道面試題-CPU偽共享

    前言:了不起:又到了每天一到面試題的時候了!學弟,最近學習的怎么樣啊 了不起學弟:最近學習的還不錯,每天都在學習,每天都在進步! 了不起:那你最近學習的什么呢? 了不起學弟:最近在學習C
  • 消費結構調整丨巨頭低價博弈,拼多多還卷得動嗎?

    來源:征探財經作者:陳香羽隨著流量紅利的退潮,電商的存量博弈越來越明顯。曾經主攻中高端與品質的淘寶天貓、京東重拾&ldquo;低價&rdquo;口號。而過去與他們錯位競爭的拼多多,靠
  • 東方甄選單飛:有些鳥注定是關不住的

    文/彭寬鴻編輯/羅卿東方甄選創始人俞敏洪帶隊的&ldquo;7天甘肅行&rdquo;直播活動已在近日順利收官。成立后一年多時間里,東方甄選要脫離抖音自立門戶的傳聞不絕于耳,&ldquo;7
  • 馮提莫簽約抖音公會 前“斗魚一姐”消失在直播間

    來源:直播觀察提起&ldquo;馮提莫&rdquo;這個名字,很多網友或許聽過,但應該不記得她是哪位主播了。其實,作為曾經的&ldquo;斗魚一姐&rdquo;,馮提莫在游戲直播的年代影響力不輸于現
  • 三星電子Q2營收60萬億韓元 存儲業務營收同比仍下滑超過50%

    7月27日消息,據外媒報道,從三星電子所發布的財報來看,他們主要利潤來源的存儲芯片業務在今年二季度仍不樂觀,營收同比仍在大幅下滑,所在的設備解決方案
  • Android 14發布:首批適配機型公布

    5月11日消息,谷歌在今天凌晨舉行了I/O大會,本次發布會谷歌帶來了自家的AI語言模型PaLM 2、谷歌Pixel Fold折疊屏、谷歌Pixel 7a手機,同時發布了Androi
  • SN570 NVMe SSD固態硬盤 價格與性能兼具

    SN570 NVMe SSD固態硬盤是西部數據發布的最新一代WD Blue系列的固態硬盤,不僅閃存技術更為精進,性能也得到了進一步的躍升。WD Blue SN570 NVMe SSD的包裝外
  • 三翼鳥智能家居亮相電博會,讓用戶體驗更真實

    2021電博會在青島國際會展中心開幕中,三翼鳥直接把“家”搬到了現場,成為了展會的一大看點。這也是三翼鳥繼9月9日發布了行業首個一站式定制智慧家平臺后的
Top