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

一起學(xué) WebGL:三角形加上漸變色

開發(fā) 前端
本節(jié)講了Varying 的能力:將頂點(diǎn)著色器中的變量傳遞給片元著色器。并演示了使用兩個緩沖區(qū)對象,位置數(shù)據(jù)和顏色數(shù)據(jù),以及將它們組合成一個緩沖區(qū)對象的實(shí)現(xiàn)。

大家好,我是前端西瓜哥。之前教大家繪制一個紅色的三角形,這次我們來畫個有漸變的三角形。

原來的寫法,顏色是在片元著色器中寫死的,這次我們來像傳頂點(diǎn)數(shù)據(jù)一樣,聲明一個顏色數(shù)據(jù)傳遞過去。

顏色需要在片元著色器中賦值給內(nèi)部變量 gl_FragColor,但 attribute 動態(tài)類型卻不能在片元著色器中使用。

這時候就要用到一個新的類型 varying 了。(意思為:“變化的“)

varying 用于從頂點(diǎn)著色器中將變量傳遞到片元著色器中

兩個緩沖區(qū)對象的寫法

著色器代碼:

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
 gl_Position = a_Position;
 v_Color = a_Color;
}
`;

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

這里我們需要在兩種著色器中同時聲明 varing 變量,后面的類型也必須是相同的 vec4,變量名也要一致,只能說是完全相同了。

頂點(diǎn)著色器中需要通過 v_Color = a_Color; 賦值。然后在片元著色器中,再將同步過來的 v_Color 賦值給 gl_FragColor。

然后是新增的顏色數(shù)組的聲明,以及對應(yīng)緩存區(qū)的創(chuàng)建。

/**** 顏色數(shù)據(jù) ****/
// prettier-ignore
const colors = new Float32Array([
  1, 0, 0, // 紅色
  0, 1, 0, // 綠色
  0, 0, 1, // 藍(lán)色
])
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
const a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Color);

貼一下完整代碼:

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

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
 gl_Position = a_Position;
 v_Color = a_Color;
}
`;

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

/**** 渲染器生成處理 ****/
// 創(chuàng)建頂點(diǎn)渲染器
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;

// 頂點(diǎn)數(shù)據(jù)
// prettier-ignore
const vertices = new Float32Array([
  0, 0.5,  // 第一個點(diǎn)
  -0.5, -0.5,  // 第二個點(diǎn)
  0.5, -0.5,  // 第三個點(diǎn)
]);

// 創(chuàng)建緩存對象
const vertexBuffer = gl.createBuffer();
// 綁定緩存對象到上下文
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
// 向緩存區(qū)寫入數(shù)據(jù)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

// 獲取 a_Position 變量地址
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
// 將緩沖區(qū)對象分配給 a_Position 變量
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

// 允許訪問緩存區(qū)
gl.enableVertexAttribArray(a_Position);

/**** 顏色數(shù)據(jù) ****/
// prettier-ignore
const colors = new Float32Array([
  1, 0, 0, // 紅色
  0, 1, 0, // 綠色
  0, 0, 1, // 藍(lán)色
])
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
const a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Color);

/*** 繪制 ***/
// 清空畫布,并指定顏色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 繪制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);

demo 地址:

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

渲染結(jié)果:

圖片

我們其實(shí)只是給三個頂點(diǎn)設(shè)置了紅、綠、藍(lán)三個顏色,然后 WebGL 會基于它們計(jì)算出中間的過內(nèi)插顏色,將它們填充滿三個點(diǎn)圍成區(qū)域的像素點(diǎn)。

單緩沖區(qū)的實(shí)現(xiàn)

前面的實(shí)現(xiàn)用了兩個緩沖區(qū)對象分別保存位置信息和顏色信息。

但實(shí)際上可以將它們組合在一起,讓數(shù)據(jù)更緊湊放在一個緩沖區(qū)里。

浮點(diǎn)數(shù)數(shù)組為:

// prettier-ignore
const verticesColors = new Float32Array([
  0, 0.5, 1, 0, 0,  // 點(diǎn) 1 的位置和顏色信息
  -0.5, -0.5, 0, 1, 0,  // 點(diǎn) 2
  0.5, -0.5, 0, 0, 1,  // 點(diǎn) 3
]);

然后是和前一種寫法有一些不同的地方:

// 每個數(shù)組元素的字節(jié)數(shù)
const SIZE = verticesColors.BYTES_PER_ELEMENT;

// 獲取 a_Position 變量地址
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, SIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);

const a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, SIZE * 5, SIZE * 2);
gl.enableVertexAttribArray(a_Color);

主要是 gl.vertexAttribPointer 方法的最后兩個參數(shù) stride 和 offset。

我們看下面這個:

gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, SIZE * 5, SIZE * 2);

stride 為 SIZE * 5(單位為字節(jié),所以要乘以一個數(shù)組元素的字節(jié)大小),表示 5 個數(shù)組元素為一趟,然后 offset 為 SIZE  * 2,表示從第 2 個元素,取 3 個元素作為這一趟的數(shù)據(jù)內(nèi)容。

完整代碼實(shí)現(xiàn):

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

const vertexShaderSrc = `
attribute vec4 a_Position;
attribute vec4 a_Color;
varying vec4 v_Color;
void main() {
 gl_Position = a_Position;
 v_Color = a_Color;
}
`;

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

/**** 渲染器生成處理 ****/
// 創(chuàng)建頂點(diǎn)渲染器
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;

// 頂點(diǎn)數(shù)據(jù)
// prettier-ignore
const verticesColors = new Float32Array([
  0, 0.5, 1, 0, 0,  // 點(diǎn) 1 的位置和顏色信息
  -0.5, -0.5, 0, 1, 0,  // 點(diǎn) 2
  0.5, -0.5, 0, 0, 1,  // 點(diǎn) 3
]);
// 每個數(shù)組元素的字節(jié)數(shù)
const SIZE = verticesColors.BYTES_PER_ELEMENT;

// 創(chuàng)建緩存對象
const vertexColorBuffer = gl.createBuffer();
// 綁定緩存對象到上下文
gl.bindBuffer(gl.ARRAY_BUFFER, vertexColorBuffer);
// 向緩存區(qū)寫入數(shù)據(jù)
gl.bufferData(gl.ARRAY_BUFFER, verticesColors, gl.STATIC_DRAW);

// 獲取 a_Position 變量地址
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, SIZE * 5, 0);
gl.enableVertexAttribArray(a_Position);

const a_Color = gl.getAttribLocation(gl.program, "a_Color");
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, SIZE * 5, SIZE * 2);
gl.enableVertexAttribArray(a_Color);

/*** 繪制 ***/
// 清空畫布,并指定顏色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 繪制三角形
gl.drawArrays(gl.TRIANGLES, 0, 3);

demo 地址:

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

結(jié)尾

本節(jié)講了 varying 的能力:將頂點(diǎn)著色器中的變量傳遞給片元著色器。并演示了使用兩個緩沖區(qū)對象,位置數(shù)據(jù)和顏色數(shù)據(jù),以及將它們組合成一個緩沖區(qū)對象的實(shí)現(xiàn)。

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

2023-04-17 09:01:01

WebGL繪制三角形

2023-11-01 07:51:15

WebGPU3D 圖形

2016-10-20 13:36:28

WebRTC瀏覽器服務(wù)器

2021-10-19 10:09:21

三角形個數(shù)數(shù)組

2022-03-16 14:27:49

CSS三角形前端

2021-08-29 18:32:18

CSS

2020-12-09 08:34:24

css生成器設(shè)計(jì)師

2023-04-26 07:42:16

WebGL圖元的類型

2024-02-20 18:30:53

CSS屬性邊框

2023-04-12 07:46:24

JavaScriptWebGL

2023-03-29 07:31:09

WebGL坐標(biāo)系

2023-05-04 08:48:42

WebGL復(fù)合矩陣

2023-06-26 15:14:19

WebGL紋理對象學(xué)習(xí)

2022-09-14 15:17:26

ArkUI鴻蒙

2021-07-16 05:59:27

CSS 技巧帶圓角的三角形

2013-09-26 13:43:13

iOS開發(fā)OpenGL ES教程圖元

2018-03-02 15:54:37

三角形主機(jī)比特幣

2021-04-15 06:02:50

CSS 三角形技巧

2023-05-16 07:44:03

紋理映射WebGL

2023-05-31 20:10:03

WebGL繪制立方體
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 99r在线 | 99精品99久久久久久宅男 | 色妞av| 亚洲精品乱码久久久久久按摩观 | 久久久久久久久99精品 | 精品久久久网站 | 国产美女在线看 | www.国产视频 | 一本色道久久综合亚洲精品高清 | 日本一区二区三区精品视频 | 亚洲欧美国产视频 | 午夜视频免费在线观看 | 国产精品视频一二三区 | 亚洲成人国产精品 | 美女天堂在线 | 久久久久久久久久一区 | 日韩中文一区二区三区 | 户外露出一区二区三区 | 欧美激情99| 91视频在线看 | 久久国产精品视频观看 | 国产综合精品一区二区三区 | 成人欧美一区二区三区在线播放 | 在线观看中文字幕视频 | 日韩国产免费 | 久久久久久高潮国产精品视 | 日本免费一区二区三区四区 | 亚洲精品福利在线 | 亚洲精品综合 | av网站在线看 | 免费在线观看黄色av | 久久国产秒 | 99精品在线观看 | 国产一区二区视频在线 | 国产亚洲一区二区三区 | jvid精品资源在线观看 | 色久在线 | 日韩欧美精品在线 | a级在线观看 | 日韩电影中文字幕 | 国产黄色大片 |