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

一起學 WebGL:繪制立方體

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

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

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

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

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

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

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

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

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 黑色
]);

圖片

然后用索引值構(gòu)造好 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, // 背面
]);

和頂點數(shù)據(jù)類似,索引值也要創(chuàng)建一個緩沖區(qū),并進行綁定,綁定目標變成了 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);

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

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

繪制結(jié)果:

圖片

完整代碼:

// 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;
}
`;

/**** 渲染器生成處理 ****/
// 創(chuàng)建頂點渲染器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSrc);
gl.compileShader(vertexShader);
// 創(chuàng)建片元渲染器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSrc);
gl.compileShader(fragmentShader);
// 程序?qū)ο?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, // 背面
]);

// 每個數(shù)組元素的字節(jié)數(shù)
const SIZE = verticesColors.BYTES_PER_ELEMENT;
// 創(chuàng)建緩存對象
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);

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

/**** 構(gòu)造視圖矩陣 ****/
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;
}

/***** 構(gòu)建透視矩陣 *****/
function createPerspective(fov, aspect, near, far) {
  fov = angleToRadian(fov); // 角度轉(zhuǎn)弧度
  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。

責任編輯:姜華 來源: 前端西瓜哥
相關(guān)推薦

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

游戲開發(fā)畫布功能

2019-07-16 16:05:51

PythonScribusRGB

2023-05-06 07:23:57

點贊
收藏

51CTO技術(shù)棧公眾號

国产精品福利一区| 粉嫩aⅴ一区二区三区四区五区| 欧美日韩综合不卡| av免费观看大全| 国产精品久久久久久久久久10秀 | 国产aⅴ精品一区二区三区久久| 欧美精品一二三四| 神马午夜dy888| 精品一区二区三区在线视频| 国产欧美日韩精品丝袜高跟鞋| 国产在线网站| 欧美性猛交99久久久久99按摩| 精品国产成人av在线免| 蜜臀av性久久久久av蜜臀妖精 | 婷婷色在线播放| 国产欧美精品区一区二区三区 | 欧美r级电影在线观看| 日韩偷拍自拍| 欧美视频一二三| 午夜视频在线免费| 欧美色xxxx| 欧美13一16娇小xxxx| 91精选在线观看| a国产在线视频| 国产精品福利视频| а√中文在线8| 综合激情婷婷| 欧美videofree性高清杂交| 一本一道久久久a久久久精品91| 天天综合网天天| 永久91嫩草亚洲精品人人| 日韩av影视综合网| 91精品视频在线看| 污污片在线免费视频| 狠狠色丁香婷婷综合影院| 欧美顶级少妇做爰| www国产免费| 婷婷综合亚洲| 97在线精品视频| 国产suv精品一区| 九九精品在线视频| 99久久亚洲精品蜜臀| 国产香蕉97碰碰久久人人| 青青青手机在线视频观看| 国产精品久久久久久久蜜臀| 91成人在线观看喷潮教学| 日韩电影在线观看一区| 四虎影院一区二区| 99国产精品国产精品毛片| 亚洲乱码一区二区三区| 国产高清不卡一区二区| 国内精品视频一区二区三区| 成人午夜电影网站| 国产精品一区二区小说| 一区二区三区日韩欧美精品| 日韩精品123| 亚洲成人av片| 国产极品一区| 亚洲最大的网站| 国产成人高清在线| 九九99九九精彩| 亚洲成人动漫精品| 在线国产1区| 91精品国产综合久久精品麻豆| 色影视在线观看| 精品视频在线观看日韩| 国内露脸中年夫妇交换精品| 成人福利网站在线观看| 国产精品99一区二区| 日本一道在线观看| 亚洲午夜电影在线| 成人美女视频| 国产精品视频地址| 精品制服美女丁香| 污视频网站免费看| 色yeye香蕉凹凸一区二区av| 国产欧美日韩影院| 国产黄色一级网站| 精品女同一区二区| 在线成人直播| 色av男人的天堂免费在线| 亚洲欧洲午夜一线一品| 一区二区亚洲视频| 国产91免费视频| 老司机午夜精品99久久| 羞羞免费视频网站| 一本色道久久综合亚洲精品按摩| 亚洲欧美成人影院| 国产精品高潮呻吟久久av野狼 | 亚洲欧美中文日韩在线| 欧美日韩 国产精品| 欧美韩国日本在线| 91精品国产综合久久香蕉麻豆| 日韩一区免费| 日韩久久不卡| 精品人伦一区二区三区蜜桃网站| 国产美女一区视频| 欧美挠脚心视频网站| 亚洲1区在线| 97超碰人人爱| 欧美久久久久中文字幕| 成人3d精品动漫精品一二三| 黄www在线观看| 亚洲免费一级电影| 日本vs亚洲vs韩国一区三区| 91啦中文在线| 国产欧美在线看| 在线电影欧美成精品| 欧美在线综合| 日本最新在线视频| 亚洲人成网站在线播放2019| 欧美日韩在线观看一区二区 | 丁香激情视频| 成人h视频在线观看播放| 在线精品视频免费观看| 香蕉视频成人在线观看| 亚洲妇女成熟| 午夜精品福利视频| 精品久久人人做人人爱| 国产精品久久精品日日| 欧美精品国产白浆久久久久| 午夜免费性福利| 99国产超薄肉色丝袜交足的后果| 黑人精品xxx一区一二区| 日韩午夜电影| 日韩脚交footjobhd| 无遮挡又爽又刺激的视频 | 午夜在线观看视频网站| 欧美亚洲黄色片| 国产成人一区二区三区小说| 日韩免费观看高清完整版在线观看| 奇米色一区二区| 欧美一区二区三区另类| av成人资源| 樱花草涩涩www在线播放| 国产精品av免费| 九九久久综合网站| 天天av天天翘天天综合网色鬼国产| 亚州av乱码久久精品蜜桃| 香蕉国产在线| 欧美性受黑人性爽| 国产成人在线播放| 亚洲第一精品自拍| 国产日韩成人精品| 99热在线精品观看| 精品精品视频| 国产在线中文字幕| 国产日产欧美视频| 一区二区三区国产福利| 欧美激情亚洲精品| 亚洲精品www久久久| 日本韩国欧美一区二区三区| 久久er精品视频| 午夜日韩视频| 欧美一区电影| 欧美成人a交片免费看| 成人精品一区二区| 嫩草影院网站在线| 国产原创popny丨九色| 亚洲精品一品区二品区三品区| 欧美亚洲另类制服自拍| 日韩一区二区三区在线观看| 亚洲福利视频三区| 91蜜桃婷婷狠狠久久综合9色| 91首页免费视频| 久久嫩草精品久久久精品| 欧美日韩另类字幕中文| 久久综合久久综合久久| 免费亚洲电影在线| 影音先锋国产精品| 三级电影一区| 国内精品国产成人国产三级粉色| 国产高清不卡| bt在线麻豆视频| 欧美婷婷久久五月精品三区| 人妻互换免费中文字幕| 日韩精品在线视频免费观看| 精品久久sese| 久草精品电影| 欧美亚洲免费在线| 精品1区2区在线观看| 国内成人精品一区| 国产欧洲精品视频| 精品国一区二区三区| 欧美视频一区二区在线观看| 欧美激情一区不卡| 亚洲激情婷婷| 日韩欧美美女在线观看| 午夜精品影视国产一区在线麻豆| 激情视频极品美女日韩| 开心快乐六月丁香婷婷| 白浆爆出在线观看| 一区二区三区四区五区视频| 免费人成在线观看视频播放| 中文字幕亚洲无线码a| 国产精品视频白浆免费视频| 日韩美女视频免费在线观看| 91精品免费视频| 91亚洲永久免费精品| 欧美久久电影|