一起学WebGL:动态绘制点

大家好,我是前端西瓜哥。上一篇文章讲解了如何绘制一个点。但这个点的信息是写死在渲染器源码中的,也就是硬编码。

北湖网站建设公司创新互联公司,北湖网站设计制作,有大型网站制作公司丰富经验。已为北湖上千多家提供企业网站建设服务。企业网站搭建\成都外贸网站制作要多少钱,请找那个售后服务好的北湖做网站的公司定做!

这是系列文章,如果你是初学者,你需要看上一篇文章才好理解这节课的内容。

​​《一起学 WebGL:绘制一个点》​​

如果我们要频繁地改变点的位置去绘制,根据我们之前学到的知识点,那只能通过替换整个着色器代码字符串,不断地编译的方式去修改了,非常不便。

这节课我们会通过 JavaScript 给着色器动态提供数据,而不需要重新编译着色器。

静态绘制点

先贴上上篇文章的静态写法。

demo 地址:

https://codesandbox.io/s/webgl-hui-zhi-yi-ge-dian-2-bpwz8p。

/**
* wegbl 绘制一个点
*/

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

const vertexShaderSrc = `
attrs
void main() {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
gl_PointSize = 20.0;
}
`;

const fragmentShaderSrc = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

/**** 渲染器生成处理 ****/
// 创建顶点渲染器
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;

/** 画布绘制 **/
// 清空画布,并指定颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);

渲染结果:

外部传递点的位置信息

下面我们希望顶点着色器的点的坐标可以通过 JavaScript 动态地修改。

加入 attribute 变量

修改顶点着色器的代码:

const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
gl_PointSize = 20.0;
}
`;

这里西瓜哥我将原本的 vec4 类型的写死的颜色值,换成了一个变量 a_Position。attribute 是存储限定符,表示变量是 attribute 类型,它用于描述顶点数据,值可以通过外部传递被修改。后面我们从外部拿到这个变量,传入我们想要的值。

vec4 则是变量类型,表示一个有四个分量的矢量。

变量通常会用 a_ 作为前缀,表示该变量是 attribute 类型。

外部修改 attribute

然后是在 JavaScript 代码中获取这个 a_Position 变量,并传一个值给它。

const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttrib3f(a_Position, 0, 0.5, 0);

第一行 gl.getAttribLocation 方法的作用,是从 gl.program 程序对象中,取出一个名为 "a_Position" 的 attribute 变量的地址。如果找到,会返回一个大于等于 0 的值,找不到会返回  -1。

第二行,gl.vertexAttrib3f 就是根据地址给 a_Position 变量赋予值。a_Position 是 4 个浮点数组成的矢量类型,我们这里并没有传 4 个值,只传了 3 个。最后一个值对坐标系来说并无意义,但在矩阵变换时会用到,不提供会被自动填充为默认的 1.0。

你也可以用 gl.vertexAttrib4f 提供完成的 4 个浮点数,或者用 gl.vertexAttrib1f 或 gl.vertexAttrib2f 提供第一个或前两个浮点数。缺少的 y、z 默认会用 0.0,z 则使用 1.0。

这里我们给 y 设置了 0.5,渲染结果为:

关于坐标系的文章

《​​一起学 WebGL:坐标系​​》

补充一下 WebGL 的坐标系图示:

完整代码:

/**
* wegbl 绘制一个点
*/

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

const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
gl_PointSize = 20.0;
}
`;

const fragmentShaderSrc = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

/**** 渲染器生成处理 ****/
// 创建顶点渲染器
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;

/** 修改着色器的 attribute */
const a_Position = gl.getAttribLocation(gl.program, "a_Position");
gl.vertexAttrib3f(a_Position, 0, 0.5, 0);

/** 画布绘制 **/
// 清空画布,并指定颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);

demo 地址:

不断修改位置信息

下面我们用一个定时器,不断地修改点的位置。

代码实现:

/**
* webgl 动态绘制点 + 定时器
*/

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

const vertexShaderSrc = `
attribute vec4 a_Position;
void main() {
gl_Position = a_Position;
gl_PointSize = 20.0;
}
`;

const fragmentShaderSrc = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

/**** 渲染器生成处理 ****/
// 创建顶点渲染器
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;

/** 修改着色器的 attribute */
const a_Position = gl.getAttribLocation(gl.program, "a_Position");

let x = -1;
let y = -1;

setInterval(() => {
gl.vertexAttrib3f(a_Position, x, y, 0);
x += 0.25;
if (x > 1) x = -1;
y += 0.25;
if (y > 1) y = -1;

/** 画布绘制 **/
// 清空画布,并指定颜色
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绘制点
gl.drawArrays(gl.POINTS, 0, 1);
}, 180);

在定时器中,我们不断地修用 gl.vertexAttrib3f 修改点的位置,并重绘画布。

demo 地址:

https://codesandbox.io/s/webgl-dong-tai-hui-zhi-dian-ding-shi-qi-gnjx3t。

渲染效果:

结尾

我是前端西瓜哥,欢迎关注我,学习更多前端知识。

这里布置一个小练习:动态修改点的大小,这次要用 float 类型,并对应使用 g1.vertexAttriblf 传递值。

答案在:https://codesandbox.io/s/g4ft9m

下一节我们将学习如何动态修改片元着色器中点的颜色。

分享名称:一起学WebGL:动态绘制点
URL地址:http://www.hantingmc.com/qtweb/news19/43769.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联