改变点的颜色

现在,我们对如何将数据从js程序传入着色器有了一个很好的了解。在此基础上来实现一个更复杂的程序。
改变绘制点的颜色。而且颜色依赖它在canvas中的位置。
可以用unifrom变量将颜色值传给着色器,器步骤与用attribute变量传值类似。不同的仅仅是,这次数据传值的目标是片元着色器。

  1. 在片元着色器中准备uniform变量。
  2. 用这个uniform变量想gl_FragColor赋值。
  3. 将颜色数据从js传给uniform变量。

用代码来实现下。

image.png

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. </head>
  10. <body onload="main()">
  11. <canvas id="canvas" height="400" width="400">
  12. 你的浏览器不支持WebGL,请更换新的浏览器
  13. </canvas>
  14. </body>
  15. <script src="../lib/webgl-util.js" ></script>
  16. <script src="../lib/webgl-debug.js" ></script>
  17. <script src="../lib/cuon-utils.js" ></script>
  18. <script>
  19. //顶点着色器程序
  20. var VSHADER_SOURCE="" +
  21. "attribute vec4 a_Position;\n" +
  22. "void main(){\n" +
  23. " gl_Position = a_Position;\n" +//设置坐标
  24. " gl_PointSize = 10.0;\n" +//设置尺寸
  25. "}\n";
  26. //片元着色器程序
  27. var FSHADER_SOURCE = "" +
  28. 'precision mediump float;\n' +
  29. 'uniform vec4 u_FragColor;\n' + // unifrom变量
  30. "void main(){\n" +
  31. " gl_FragColor = u_FragColor;\n" +//设置颜色
  32. "}\n";
  33. function main() {
  34. //首先获取到canvas的dom对象
  35. var canvas = document.getElementById("canvas");
  36. //获取到WebGL的上下文
  37. var gl = getWebGLContext(canvas);
  38. //不支持WebGL的浏览器将打印一个错误,并结束代码运行
  39. if (!gl) {
  40. console.log("浏览器不支持WebGL");
  41. return;
  42. }
  43. //初始化着色器
  44. if(!initShaders(gl,VSHADER_SOURCE,FSHADER_SOURCE)){
  45. console.log("初始化着色器失败");
  46. return;
  47. }
  48. // 获取attribute变量的存储位置
  49. var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  50. var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
  51. // 将顶点位置传输给attribute变量
  52. // gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);
  53. // 注册鼠标点击事件响应函数
  54. canvas.onmousedown = function(ev) {
  55. click(ev, gl, canvas, a_Position, u_FragColor);
  56. }
  57. //指定一个覆盖(清空)canvas的颜色
  58. gl.clearColor(0.0, 0.0, 0.0, 1.0);
  59. //执行清空
  60. gl.clear(gl.COLOR_BUFFER_BIT);
  61. // //绘制一个点
  62. // gl.drawArrays(gl.POINTS,0,1);
  63. }
  64. var g_points = [];
  65. var g_colors = [];
  66. function click(ev, gl, canvas, a_Position, u_FragColor) {
  67. var x = ev.clientX;
  68. var y = ev.clientY;
  69. var rect = ev.target.getBoundingClientRect();
  70. x = ((x - rect.left) - canvas.width/2)/(canvas.height/2);
  71. y = (canvas.height/2 - (y-rect.top)) / (canvas.width/2);
  72. // 将坐标存储到g_points数组中
  73. g_points.push([x, y]);
  74. // 将点的颜色存储在g_colors中
  75. if (x >= 0 && y >= 0) { // 第一象限
  76. g_colors.push([1.0, 0.0, 0.0, 1.0]); //红色
  77. } else if (x < 0 && y < 0) { // 第三象限
  78. g_colors.push([0.0, 1.0, 0.0, 1.0]) // 绿色
  79. } else { // 其他
  80. g_colors.push([1.0, 1.0, 1.0, 1.0]) // 白色
  81. }
  82. console.log(g_colors);
  83. gl.clear(gl.COLOR_BUFFER_BIT);
  84. var len = g_points.length;
  85. for (let i = 0; i < len; i++) {
  86. var xy = g_points[i];
  87. var rgba = g_colors[i];
  88. // 将点的位置传输到a_Position中
  89. gl.vertexAttrib3f(a_Position, xy[0], xy[1], 0.0);
  90. // 将点的色值传输到u_FragColor中
  91. gl.uniform4f(u_FragColor, rgba[0], rgba[1], rgba[2], rgba[3]);
  92. gl.drawArrays(gl.POINTS,0,1);
  93. }
  94. }
  95. </script>
  96. </html>

uniform变量

只有顶点着色器才可以使用attribute变量,使用片元着色器时,需要使用uniform变量。