国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

一起學 WebGL:繪制立方體

開發 前端
現在我們來繪制一個立方體,其實本質和繪制二維圖形是一樣,也是繪制三角形,只是繪制很多個,然后組合起來,作為立方體的幾個面,拼在一起就是一個立方體了。

大家好,我是前端西瓜哥。

之前我們繪制三角形,是一個二維的圖形。

現在我們來繪制一個立方體,其實本質和繪制二維圖形是一樣,也是繪制三角形,只是繪制很多個,然后組合起來,作為立方體的幾個面,拼在一起就是一個立方體了。

繪制三角形,我們用的 API 是:

gl.drawArrays(gl.TRIANGLES, 0, n);

那畫一個立方體,假設選擇 gl.TRIANGLE_FAN 圖元模式,也就是畫 6 個面,每個面有 4 個點。所以我們需要定義 24 個點。

這其實重復定義了頂點,因為一個立方體也就 8 個點,數據是有冗余的。

WebGL 提供了 gl.drawElements() 方法,通過索引值映射的方式來解決這個問題。

首先定義立方體的 8 個頂點(我們命名為 v0 到 v7)的位置和顏色。

const verticesColors = new Float32Array([
  1, 1, 1,     1, 1, 1, // 點 0 白
  -1, 1, 1,    1, 0, 1, // 點 1 品紅
  -1, -1, 1,   1, 0, 0, // 點 2 紅
  1, -1, 1,    1, 1, 0, // 點 3 黃

  1, -1, -1,   0, 1, 0, // 點 4 綠色
  1, 1, -1,    0, 1, 1, // 點 5 青色
  -1, 1, -1,   0, 0, 1, // 點 6 藍色
  -1, -1, -1,  0, 0, 0, // 點 7 黑色
]);

圖片

然后用索引值構造好 6 個面,每個面 2 個三角形:

const indices = new Uint8Array([
  0, 1, 2, 0, 2, 3, // 正面
  0, 3, 4, 0, 4, 5, // 右面
  0, 5, 6, 0, 6, 1, // 上面
  1, 6, 7, 1, 7, 2, // 左面
  7, 4, 3, 7, 3, 2, // 下面
  4, 7, 6, 4, 6, 5, // 背面
]);

和頂點數據類似,索引值也要創建一個緩沖區,并進行綁定,綁定目標變成了 gl.ELEMENT_ARRAY_BUFFER 上。

const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

最后調用 gl.drawElements 方法進行繪制。這里要傳入 indices 數組的長度,WebGL 就會讀取索引值得到對應的頂點信息去一個個繪制三角形啦。

gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_BYTE, 0);

繪制結果:

圖片

完整代碼:

// Create a cube
//    v6----- v5
//   /|      /|
//  v1------v0|
//  | |     | |
//  | |v7---|-|v4
//  |/      |/
//  v2------v3

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

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute vec4 a_Color;
uniform mat4 u_ViewMatrix;  // 視圖矩陣
uniform mat4 u_ProjMatrix; // 正射投影矩陣
mat4 u_MvpMatrix = u_ProjMatrix * u_ViewMatrix;
varying vec4 v_Color;
void main() {
 gl_Position = u_MvpMatrix * a_Position;
 v_Color = a_Color;
}
`;

const fragmentShaderSrc = `
precision highp float;
varying vec4 v_Color;
void main() {
  gl_FragColor = v_Color;
}
`;

/**** 渲染器生成處理 ****/
// 創建頂點渲染器
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;

// prettier-ignore
const verticesColors = new Float32Array([
  1, 1, 1,     1, 1, 1, // 點 0 白
  -1, 1, 1,    1, 0, 1, // 點 1 品紅
  -1, -1, 1,   1, 0, 0, // 點 2 紅
  1, -1, 1,    1, 1, 0, // 點 3 黃

  1, -1, -1,   0, 1, 0, // 點 4 綠色
  1, 1, -1,    0, 1, 1, // 點 5 青色
  -1, 1, -1,   0, 0, 1, // 點 6 藍色
  -1, -1, -1,  0, 0, 0, // 點 7 黑色
]);

// prettier-ignore
const indices = new Uint8Array([
  0, 1, 2, 0, 2, 3, // 正面
  0, 3, 4, 0, 4, 5, // 右面
  0, 5, 6, 0, 6, 1, // 上面
  1, 6, 7, 1, 7, 2, // 左面
  7, 4, 3, 7, 3, 2, // 下面
  4, 7, 6, 4, 6, 5, // 背面
]);

// 每個數組元素的字節數
const SIZE = verticesColors.BYTES_PER_ELEMENT;
// 創建緩存對象
const vertexColorBuffer = gl.createBuffer();
const indexBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);

// 獲取 a_Position 變量地址
const a_Position = gl.getAttribLocation(gl.program, 'a_Position');
const a_Color = gl.getAttribLocation(gl.program, 'a_Color');
/****** 正射投影 ******/
const u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');

// prettier-ignore
const viewMatrix = createViewMatrix(
  3, 4, 8, // 觀察點
  0, 0, 0, // 視點
  0, 1, 0 // 上方向
)
gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix);

/****** 正射投影 ******/
const u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');
// prettier-ignore
const projMatrix = createPerspective(
  30, canvas.width / canvas.height, 1, 100
)
gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix);

gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, SIZE * 6, 0);
gl.enableVertexAttribArray(a_Position);

gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, SIZE * 6, SIZE * 3);
gl.enableVertexAttribArray(a_Color);

/*** 繪制 ***/
// 清空畫布,并指定顏色
gl.clearColor(0, 0, 0, 1);
gl.enable(gl.DEPTH_TEST); // 啟動深度檢測,處理錯誤的像素覆蓋問題

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// 繪制三角形
// gl.drawArrays(gl.TRIANGLES, 0, 8);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_BYTE, 0);

/************ 后面都是一些工具類方法 ******/

/**** 構造視圖矩陣 ****/
function createViewMatrix(eyeX, eyeY, eyeZ, atX, atY, atZ, upX, upY, upZ) {
  const normalize = (v) => {
    const length = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
    return [v[0] / length, v[1] / length, v[2] / length];
  };
  const subtract = (v1, v2) => {
    return [v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]];
  };
  const cross = (v1, v2) => {
    return [
      v1[1] * v2[2] - v1[2] * v2[1],
      v1[2] * v2[0] - v1[0] * v2[2],
      v1[0] * v2[1] - v1[1] * v2[0],
    ];
  };

  const zAxis = normalize(subtract([eyeX, eyeY, eyeZ], [atX, atY, atZ]));
  const xAxis = normalize(cross([upX, upY, upZ], zAxis));
  const yAxis = normalize(cross(zAxis, xAxis));

  return new Float32Array([
    xAxis[0],
    yAxis[0],
    zAxis[0],
    0,
    xAxis[1],
    yAxis[1],
    zAxis[1],
    0,
    xAxis[2],
    yAxis[2],
    zAxis[2],
    0,
    -(xAxis[0] * eyeX + xAxis[1] * eyeY + xAxis[2] * eyeZ),
    -(yAxis[0] * eyeX + yAxis[1] * eyeY + yAxis[2] * eyeZ),
    -(zAxis[0] * eyeX + zAxis[1] * eyeY + zAxis[2] * eyeZ),
    1,
  ]);
}

function angleToRadian(angle) {
  return (Math.PI * angle) / 180;
}

/***** 構建透視矩陣 *****/
function createPerspective(fov, aspect, near, far) {
  fov = angleToRadian(fov); // 角度轉弧度
  const f = 1.0 / Math.tan(fov / 2);
  const nf = 1 / (near - far);
  // prettier-ignore
  return new Float32Array([
    f / aspect, 0, 0, 0,
    0, f, 0, 0,
    0, 0, (far + near) * nf, -1,
    0, 0, 2 * far * near * nf, 0,
  ]);
}

線上體驗 demo:

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

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

2023-04-12 07:46:24

JavaScriptWebGL

2023-05-16 07:44:03

紋理映射WebGL

2023-04-11 07:48:32

WebGLCanvas

2023-04-17 09:01:01

WebGL繪制三角形

2023-04-26 07:42:16

WebGL圖元的類型

2023-05-04 08:48:42

WebGL復合矩陣

2023-06-26 15:14:19

WebGL紋理對象學習

2023-03-29 07:31:09

WebGL坐標系

2023-04-13 07:45:15

WebGL片元著色器

2023-05-17 08:28:55

2023-04-27 08:27:29

WebGL變形矩陣

2023-03-02 07:44:39

pixijsWebGL

2023-02-22 09:27:31

CanvasWebGL

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

游戲開發畫布功能

2019-07-16 16:05:51

PythonScribusRGB

2023-05-06 07:23:57

點贊
收藏

51CTO技術棧公眾號

国产三区四区在线观看| 日韩av中文| 国产啊啊啊视频在线观看| 亚洲国产另类av| 91精品91久久久中77777老牛| 一区二区精品| 成人动漫视频在线观看免费| 色乱码一区二区三区网站| 97av在线视频免费播放| 成人av在线播放| 国产小视频国产精品| 松下纱荣子在线观看| 亚洲成人网在线| 免费的黄网站在线观看| 91高清视频在线| 爽爽视频在线观看| 亚洲动漫第一页| 意大利激情丛林无删减版dvd| 国产精品久久久久四虎| 99视频免费| 国产精品美女久久久久av爽李琼 | 日韩不卡手机在线v区| 免费看毛片的网址| 国产亚洲欧美色| 一本色道久久亚洲综合精品蜜桃| 五月天国产精品| 精品magnet| 日韩少妇内射免费播放18禁裸乳| 你微笑时很美电视剧整集高清不卡 | 午夜激情在线观看视频| 中文字幕不卡三区视频| 亚洲二区在线播放视频| 成人女同在线观看| 欧美日韩另类字幕中文| 欧美激情 国产精品| 91丨porny丨首页| 三级a在线观看| 亚洲老妇xxxxxx| 天堂av在线免费观看| 欧美日韩亚洲国产综合| 三级在线观看视频| 久久香蕉国产线看观看网| 九色成人国产蝌蚪91| 国产日韩欧美一区二区三区四区| 日本91福利区| 少妇性l交大片| 日韩a**中文字幕| 中文字幕日韩视频| 香蕉人人精品| 亚洲最大福利视频| 另类小说欧美激情| 牛夜精品久久久久久久| 精品久久久久久久大神国产| www免费在线观看| 一区二区亚洲精品国产| 日韩伦理一区二区三区| 精品国产免费人成电影在线观...| 免费看男男www网站入口在线| 国产成人激情小视频| 一区二区激情| 九九热视频这里只有精品| 欧美人与拘性视交免费看| 国产精品免费视频一区二区| 国产+成+人+亚洲欧洲自线| 成人黄色免费| 欧美一区二区视频免费观看| 午夜免费性福利| 日本一区二区三区四区视频| 欧美亚洲一级| 羞羞网站免费观看| 精品免费国产一区二区三区四区| 国产二区三区在线| 综合网日日天干夜夜久久| 欧美gayvideo| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 在线播放91灌醉迷j高跟美女| 国产999精品在线观看| 成人av蜜桃| 国产亚洲短视频| sm捆绑调教国产免费网站在线观看| 中文在线资源观看视频网站免费不卡 | 欧美va天堂在线| 桥本有菜av在线| 亚洲自拍与偷拍| 是的av在线| 国产超碰91| 亚洲日本丝袜连裤袜办公室| 中文在线8资源库| 亚洲自拍偷拍在线| 国产精品久久久久影院老司| 伊人久久国产| 国产精品免费一区二区| 国产精品国产精品国产专区不蜜| 天堂av中文在线观看| 国产区日韩欧美| 亚洲激情网站免费观看| 亚洲欧美专区| 亚洲一区二区三区涩| 欧美天堂在线观看| 欧美黑白配在线| 人人妻人人添人人爽欧美一区| 欧美一区二区三区视频在线| 91精品国产福利在线观看麻豆| 99999色| 欧美裸体男粗大视频在线观看| 极品尤物av久久免费看| 岛国在线视频| 成人综合网网址| 亚洲乱码国产乱码精品精可以看| 日韩城人网站| 国产二区视频在线| 亚洲精品一区二区久| 亚洲美女一区| 激情福利在线| 国产精品爽爽爽| 亚洲欧美激情插| 日韩人体视频| jizzjizzjizz亚洲女| 久久久免费电影| 国产亚洲一本大道中文在线| 日韩成人在线电影| 免费网站在线观看视频| 精品亚洲aⅴ在线观看| 麻豆精品视频在线观看视频| 国产精品美女在线| 久久久不卡网国产精品二区| 国产精品69毛片高清亚洲| 免费在线国产| 欧美激情xxxx| 91视频免费播放| 国产美女精品视频免费播放软件| 国产在线播放观看| 最近2019年中文视频免费在线观看 | 国产a级一级片| 日韩有码在线播放| 成人avav影音| 99精品美女视频在线观看热舞| 好吊妞无缓冲视频观看| 欧美精品性视频| 国产精品久久精品日日| 亚洲人挤奶视频| 啦啦啦啦免费高清视频在线观看1| 国产精品久久97| 亚洲成人av一区二区三区| 影音先锋日韩在线| av在线免费观看网址| 亚洲欧美日韩在线综合| 亚洲色图激情小说| 久久久99久久精品欧美| 伊人久久大香线蕉无限次| 三上悠亚在线免费观看| 国产精品成人观看视频免费| 欧美一级欧美三级| 国产一区二区三区黄视频 | 午夜爽爽视频| 7777精品伊久久久大香线蕉语言| 在线观看亚洲a| 欧美aaa在线| 国产激情欧美| 91麻豆福利| 精品欧美国产| 亚洲精品中文字幕女同| 国产亚洲欧美激情| 久久久久久久久久久久久久久久久久 | av毛片久久久久**hd| 国产欧美三级电影| 免费a在线观看| 中文字幕久久综合| 久久综合五月天| 亚洲国产精品久久久男人的天堂| 国内自拍一区| 51一区二区三区| 日本福利视频| 五月婷婷一区| 国内精品久久久久久影视8| 欧美影院一区二区| av电影在线观看完整版一区二区| 欧美视频免费| 国产伦理精品| 天天草夜夜草| 宅男一区二区三区| 欧美尤物巨大精品爽| 欧美成va人片在线观看| 国产亚洲综合性久久久影院| 激情欧美日韩| 榴莲视频成人app| 欧美r级在线| 午夜免费高清视频| 日本一区二区不卡高清更新| 久久久久久久国产精品视频| 91精品欧美久久久久久动漫| 国产精品美女久久久久久| 日本在线观看不卡视频| 精品美女久久| 成人黄色免费观看| 国产一级片在线播放| 国产免费视频传媒| 亚州欧美一区三区三区在线| 国产精品96久久久久久又黄又硬| 亚洲人成毛片在线播放|