WebGL小姐姐教我学画画之起手式

Posted 枫之叶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL小姐姐教我学画画之起手式相关的知识,希望对你有一定的参考价值。

题图来源网络,为WebGL logo。

初次接触WebGL,如有错误之处欢迎留言,共同学习进步. *v*

WebGL的自画像

我,WebGL,全名 WebGraphicsLibrary,是为了让死宅程序猿们(摊手)能在浏览器上为所欲为的画女朋友,并还能动手动脚,而屈尊降临于猿类的世界内。哇哈哈哈哈,快来臣服于我吧,哇嘎嘎嘎嗝~

WebGL启动说明书

WebGL小姐姐神通广大,法力无边。那我们怎么用她来创造一个猿猿幸(有)福(女)美(朋)满(友)的世界呢?

首先,我们需要一个名为 canvas的祭坛,举行一个召唤 WebGL小姐姐的小仪式。

 
   
   
 
  1. const canvas = document.createElement('canvas');

  2. const webGl = canvas.getContext('webgl');

那么, WebGL小姐姐Get到手了,接下来我们需要先将两样'祭品'交给她的两名侍女。

  1. 准备用于创建躯体的原材料和赋予灵魂的色彩两样祭品

  • gl_Position是每次绘制的点,是vec4类型,分别空间点 (x,y,z)和最后一个 w。对于 w可以参考文章Explaining Homogeneous Coordinates & Projective Geometry,可以理解为投影仪与空间点的距离,距离不同会导致缩放效应,距离远则投放的物体越大。我们这里使用没有缩放效果的值 1.0,并使用了 position这个定义的变量值。每次绘制 gpu buffer会更新 position的值.

 
   
   
 
  1. const vertexShaderSource = `

  2. precision mediump float;

  3. attribute vec2 position;

  4. void main(void) {

  5.    gl_Position = vec4(position.x, position.y, 0.0, 1.0);

  6. }

  7. `;

  • 每次绘制都会使用 glFragColor定义的颜色值,同样是vec4类型,分别代表 (r,g,b,a)

 
   
   
 
  1. const fragmentShaderSource = `

  2. precision mediump float;

  3. void main(void) {

  4.    gl_FragColor = vec4(0.7, 0.5, 0.38, 0.0);

  5. }

  6. `

关于 precision:由于 openGL没有声明 float类型的默认精度,所以其姐妹 WebGL也就需要为 shader声明精度。又由于高精度 openGL没有支持,低精度在手机上可以有兼容问题,所以默认推荐 mediump。参考https://stackoverflow.com/a/28540641/2326199 和 Use mediump precision in WebGL when possible

  1. 唤醒侍女并让她们把祭品处理好

 
   
   
 
  1. const vertexShader = gl.createShader(gl.VERTEX_SHADER); // 唤醒

  2. gl.shaderSource(vertexShader, vertexShaderSource); // 上交祭品

  3. gl.compileShader(vertexShader); // 处理祭品

  4. if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {

  5.    // 由于祭品偶尔不新鲜或者侍女偷懒,我们要好好确认祭品是否处理完毕

  6.    throw new Error(`Error in compileing vertexShader: ${gl.getShaderInfoLog(vertexShader)}`);

  7. }

  8. const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);

  9. gl.shaderSource(fragmentShader, fragmentShaderSource);

  10. gl.compileShader(fragmentShader);

  11. if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {

  12.    throw new Error(`Error in compileing vertexShader: ${gl.getShaderInfoLog(vertexShader)}`);

  13. }

祭品已准备妥当,接下来就是要请出 WebGL小姐姐御用创世神器 program并使用祭品开光,然后交与小姐姐手中。

 
   
   
 
  1. const program = gl.createProgram(); // 神器现世

  2. gl.attachShader(program, vertexShader); // 开第一封印:原料

  3. gl.attachShader(program, fragmentShader); // 开第二封印:色开

  4. gl.linkProgram(program); // 交与小姐姐

  5. if(!gl.getProgramParameter(program, gl.LINK_STATUS)) {

  6.    // 咳咳,由于神器与祭品偶尔无法契合,导致神器失效,需要检查一下 ~_~

  7.    throw new Error(`invalid program: ${gl.getProgramInfoLog(program)}`);

  8. }

注意了注意了, WebGL小姐姐起手式完毕,开天辟地,万物复苏。我们现在可以向她许愿,描述我们心中的 猩福世界了~v;v~

WebGL的许愿池上的许愿树

WebGL小姐姐有多个许愿池,我们这里使用 gl.ARRAY_BUFFER。然后告诉神器 program怎么收取愿望。

 
   
   
 
  1. const buffer = gl.createBuffer(); // 创建许愿树

  2. gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // 将许愿树种到`ARRAY_BUFFER`这个许愿池内

  3. // 获取神器`program`的`position`之力

  4. const position = gl.getAttribLocation(program, 'position');

  5. // position之力为2个float类型的数一组,不转化`buffer`类型,

  6. // 从头开始,不跳过任何一个愿望

  7. gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);

  8. gl.enableVertexAttribArray(position);

WebGl的创世之作

小姐姐迎着丝毫都没有的狂风,望着漫无编辑器的虚无黑暗,眼角迸发出一丝丝精光,大笔一挥, 左一划右一挥。

 
   
   
 
  1. gl.viewport(0, 0, 400, 400);

  2. gl.useProgram(program);

  3. gl.clearColor(255 / 255, 192 / 255, 203 / 255, 1.0);

  4. gl.clear(gl.COLOR_BUFFER_BIT);

  5. gl.lineWidth(1.5);

  6. const points = new Float32Array([

  7.    -0.9, 0.9,

  8.    0.0, 0.0,

  9.    0.9, -0.9,

  10. ]);

  11. gl.bufferData(gl.ARRAY_BUFFER, points, gl.STATIC_DRAW);

  12. gl.drawArrays(gl.LINE_LOOP, 0, points.length / 2);

  13. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([

  14.    -0.9, -0.9,

  15.    0.0, 0.0,

  16.    0.9, 0.9

  17. ]), gl.STATIC_DRAW);

  18. gl.drawArrays(gl.LINE_LOOP, 0, 3);



最后来一张 WebGL绘制整个过程的流程图:



未完待续




以上是关于WebGL小姐姐教我学画画之起手式的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js起手式+Vue小作品实战

html [Vue] Vue + Webpack起手式

Vue - 起手式

React全解之00React起手式

企业数字化转型的起手式是什么?

企业数字化转型的起手式是什么?