成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一起學 WebGL:紋理對象學習

開發 前端
紋理對象,是將像素(Texels)以數組方式傳給 GPU 的對象,常見場景是貼圖,就是將圖片的數據應用到 3D 物體上。

大家好,我是前端西瓜哥,今天我們來了解 WebGL 的紋理對象(Texture)

紋理對象,是將像素(texels)以數組方式傳給 GPU 的對象,常見場景是貼圖,就是將圖片的數據應用到 3D 物體上。

紋理對象創建和綁定

先創建紋理對象:

const texture = gl.createTexture(); // 創建紋理對象

然后綁定到紋理單元:

gl.bindTexture(gl.TEXTURE_2D, texture); // 將紋理對象綁定上去

填充方式

紋理是要貼到畫布的某個區域上的,并不一定剛好設置一下填充方式。

紋理比繪制區域大,就要做縮放;紋理比繪制區域小,就要做放大;紋理沒能完全填充繪制區域,就要在水平和垂直方向進行填充。

這些場景都需要對應設置不同的策略。

// 縮小和放大都都使用 “最近點采樣”
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

紋理單元

WebGL 支持設置多個紋理單元(Texture Unit),即我們可以將多個圖片放到多個單元中,然后進行切換。

就好像手里拿著不同的蓋章,想印哪種圖案就掏出哪個蓋上去。

紋理單元是有上限的,至少要支持 8 個,主流瀏覽器一般支持 16 個。

具體支持幾個,可通過下面代碼獲得。

gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) // 通常是 16

默認使用 0 號紋理單元,可通過下面這一行代碼來切換紋理單元:

gl.activeTexture(gl.TEXTURE1); // 開啟 1 號紋理單元

注意這個要 在將紋理對象綁定紋理單元之前 執行。

最后我們需要設置一下我們的紋理采樣器選擇使用哪個紋理單元:

gl.uniform1i(u_Sampler, 0); // 開啟 0 號紋理對象

不主動調用這個方法,默認會使用 0 號紋理單元。

切換紋理單元是有一定的性能代價的,不建議你在短時間內不斷地切換紋理單元。簡單的渲染場景可忽略不計。

純色紋理

畫個純純的紅色紋理。

// 紅色
const data = new Uint8Array([
  255, 0, 0
]);

gl.texImage2D(
  gl.TEXTURE_2D, // 紋理目標,這里是二維紋理
  0, // 細節級別,0 表示最高級別
  gl.RGB, // 紋理內部格式,還支持其他的比如 gl.RGBA、LUMINANCE(流明)
  1, // 寬(寬高的單位為像素,且為 2 的 n 次冪)
  1, // 高
  0, // 是否描邊。必須為 0(但 opengl 支持)
  gl.RGB, // 源圖像數據格式
  gl.UNSIGNED_BYTE, // 紋素(單個像素)數據類型
  data // 數據數組,一個個像素點
);

主要注意的是,gl.texImage2D() 方法支持函數重載,有多種傳入的參數的方式,注意分辨。具體看 官方文檔。

這里選擇使用 gl.RGB 格式,設置了一個 (255, 0, 0) 的紅色顏色值。

最后我們成功畫出一個純紅色塊。

圖片

完整代碼:

/** @type {HTMLCanvasElement} */
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl');

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;
void main() {
 gl_Position = a_Position;
 v_TexCoord = a_TexCoord;
}
`;

const fragmentShaderSrc = `
precision highp float;
uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;
void main() {
  gl_FragColor = texture2D(u_Sampler, v_TexCoord);
}
`;

// 創建程序對象
createProgram(gl);

// 頂點坐標,紋理坐標
const verticesTexCoords = new Float32Array([
  // 左上點。
  // 左邊兩個是頂點;右邊兩個是紋理
  -0.5, 0.5, 0.0, 1,
  // 左下
  -0.5, -0.5, 0.0, 0.0,
  // 右上
  0.5, 0.5, 1, 1,
  // 右下
  0.5, -0.5, 1, 0.0,
]);
const FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;

// 創建緩存對象
const verticesTexBuffer = gl.createBuffer();
// 綁定緩存對象到上下文
gl.bindBuffer(gl.ARRAY_BUFFER, verticesTexBuffer);
// 向緩存區寫入數據
gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);

// 獲取 a_Position 變量地址
const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
// 將緩沖區對象分配給 a_Position 變量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
// 允許訪問緩存區
gl.enableVertexAttribArray(a_Position);

// 傳入紋理坐標位置信息
const a_TexCoord = gl.getAttribLocation(gl.program, 'a_TexCoord');
gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
gl.enableVertexAttribArray(a_TexCoord);

/***** 紋理對象 *****/
const texture = gl.createTexture(); // 創建紋理對象
const u_Sampler = gl.getUniformLocation(gl.program, 'u_Sampler'); // 獲取 u_Sampler 地址

// 記載圖片

gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1); // 翻轉紋路圖像的 y 軸
gl.activeTexture(gl.TEXTURE0); // 開啟 0 號紋理單元
gl.bindTexture(gl.TEXTURE_2D, texture); // 將我們的紋理對象綁定上去

// 配置紋理參數
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

// 【----關鍵代碼---】配置紋理圖像
const data = new Uint8Array([255, 0, 0, 0, 255, 255, 0, 255, 0, 0, 255, 0]);
gl.texImage2D(
  gl.TEXTURE_2D, // 紋理目標
  0, // 細節級別
  gl.RGB, // 紋理內部格式
  1,
  1,
  0,
  gl.RGB, // 源圖像數據格式
  gl.UNSIGNED_BYTE, // 紋素數據類型
  data // 數據
);

gl.uniform1i(u_Sampler, 0); // 開啟 0 號紋理對象

/****** 繪制 ******/
// 清空畫布,并指定顏色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 繪制矩形,這里提供了 4 個點
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

/**** 封裝的方法 ****/

function createProgram(gl) {
  /**** 渲染器生成處理 ****/
  // 創建頂點渲染器
  const vertexShader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vertexShader, vertexShaderSrc);
  gl.compileShader(vertexShader);
  // 創建片元渲染器
  const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fragmentShader, fragmentShaderSrc);
  gl.compileShader(fragmentShader);
  // 程序對象
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  gl.useProgram(program);
  gl.program = program;
}

線上 demo:

https://codesandbox.io/s/1hvp4x?file=/index.js。

多個色塊紋理

也可以同時設置多個色塊。

圖片

const data = new Uint8Array([
  255, 0, 0, 255,   // 紅色
  255, 255, 0, 255, // 黃色
  0, 0, 255, 255,  // 藍色
  0, 255, 0, 255,  // 綠色
]);

gl.texImage2D(
  gl.TEXTURE_2D, // 紋理目標
  0, // 細節級別
  gl.RGBA, // 紋理內部格式
  2,
  2,
  0,
  gl.RGBA, // 源圖像數據格式
  gl.UNSIGNED_BYTE, // 紋素數據類型
  data // 數據
);

創建了 2x2 4個像素大小的紋理,并制定了這個 4 個像素點的顏色,然后被放大繪制到指定區域上。

線上演示 demo:

https://codesandbox.io/s/7436cs?file=/index.js。

圖片紋理

圖片紋理,需要加載玩圖片,將圖片對象綁定到紋理對象上。

// 將紋理圖像分配給紋理對象
gl.texImage2D(
  gl.TEXTURE_2D,
  0, // 細節級別
  gl.RGB,
  gl.RGB,
  gl.UNSIGNED_BYTE,
  img // Image 實例
);

結尾

紋理對象是很常用的一個對象,用于指定區域要填充的像素。

常見的是加載圖片,把圖片貼到三維的一個面上。也可以自己指定像素值。

責任編輯:姜華 來源: 前端西瓜哥
相關推薦

2023-04-12 07:46:24

JavaScriptWebGL

2023-03-29 07:31:09

WebGL坐標系

2023-05-04 08:48:42

WebGL復合矩陣

2023-04-26 07:42:16

WebGL圖元的類型

2023-05-31 20:10:03

WebGL繪制立方體

2023-05-16 07:44:03

紋理映射WebGL

2023-04-13 07:45:15

WebGL片元著色器

2023-04-11 07:48:32

WebGLCanvas

2023-05-17 08:28:55

2023-04-27 08:27:29

WebGL變形矩陣

2023-04-17 09:01:01

WebGL繪制三角形

2023-05-08 07:29:48

WebGL視圖矩陣

2022-12-02 14:20:09

Tetris鴻蒙

2022-11-29 16:35:02

Tetris鴻蒙

2023-03-30 09:32:27

2022-11-14 17:01:34

游戲開發畫布功能

2023-05-06 07:23:57

2024-02-28 12:12:20

Pipeline數據機制

2023-02-28 07:28:50

Spritepixijs

2023-11-13 22:27:53

Mapping數據庫
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产欧美在线 | h视频免费在线观看 | 久久久国产精品 | 日本淫视频 | 国产我和子的乱视频网站 | 国产成人精品一区二区三区在线 | 一区二区三区不卡视频 | 一级做a爰片性色毛片视频停止 | 男女激情网站免费 | 国产一区二区三区在线 | 91视频官网 | 97精品国产97久久久久久免费 | 亚洲欧美在线一区 | 国产亚洲成av人片在线观看桃 | 青青草华人在线视频 | 久久久久久久久毛片 | 久久久国产精品一区 | 国产一区二区三区四区区 | 国产亚洲日本精品 | 国产精品视频在线免费观看 | 一区二区三区免费 | 欧美日韩中文字幕在线 | 成人1区2区 | 亚洲国产精品久久久久久 | 中文字幕精品视频在线观看 | 久久国产欧美日韩精品 | 久久亚洲综合 | 亚洲精品99999 | 99在线精品视频 | 久久综合狠狠综合久久综合88 | 一区二区视频在线 | 欧美日韩国产在线观看 | 久久午夜视频 | 亚洲欧洲成人av每日更新 | 日韩一区二区三区在线看 | 日韩精品一二三 | 欧美日韩免费视频 | 成人在线播放网站 | 亚洲国产精品成人无久久精品 | 亚洲福利一区二区 | 久久精品视频在线观看 |