• WebGL笔记:WebGL中的顶点着色器尺寸,颜色的修改


    顶点着色器尺寸修改

    <canvas id="canvas">canvas>
    
    
    <script id="vertexShader" type="x-shader/x-vertex">
      attribute vec4 a_Position;
      attribute float a_PointSize;
      void main() {
          // 点位
          gl_Position = a_Position;
          // 尺寸
          gl_PointSize = a_PointSize;
      }
    script>
    
    
    <script id="fragmentShader" type="x-shader/x-fragment">
        void main(){
            gl_FragColor = vec4(1,1,0,1);
        }
    script>
    
    <script type="module">
        // 这里的 utils.js 参考之前博文,不做重复阐述
    	  import { initShaders } from "./utils.js";
    	
    	  const canvas = document.querySelector("#canvas");
    
    	  canvas.width = 200;
    	  canvas.height = 200;
    	
    	  // 获取着色器文本
    	  const vsSource = document.querySelector("#vertexShader").innerText;
    	  const fsSource = document.querySelector("#fragmentShader").innerText;
    	
    	  // 三维画笔
    	  const gl = canvas.getContext("webgl");
    	
    	  // 初始化着色器
    	  initShaders(gl, vsSource, fsSource);
    	
    	  // 在 js 中 获取 attribute 变量
    	  const a_Position = gl.getAttribLocation(gl.program, "a_Position");
          const a_PointSize = gl.getAttribLocation(gl.program, "a_PointSize");
    
    	  // 存储顶点数据的数组
    	  const a_points = [
    	    { x: 0, y: 0, size: 10 },
    	  ];
    	
    	  render();  
    	
    	  // 渲染方法
    	  function render() {
    	    gl.clearColor(0, 0, 0, 1); // 声明颜色 rgba
    	    gl.clear(gl.COLOR_BUFFER_BIT); // 刷底色
    	    a_points.forEach(({ x, y, size }) => {
    	      gl.vertexAttrib2f(a_Position, x, y); 
    	      gl.vertexAttrib1f(a_PointSize, size); // 这里修改尺寸大小
    	      gl.drawArrays(gl.POINTS, 0, 1);
    	    });
    	  }
    
        // 鼠标点击事件
        canvas.addEventListener("click", ({ clientX, clientY }) => {
          const { left, top, width, height } = canvas.getBoundingClientRect();
          const [cssX, cssY] = [clientX - left, clientY - top];
          // 解决坐标原点位置的差异
          const [halfWidth, halfHeight] = [width / 2, height / 2];
          const [xBaseCenter, yBaseCenter] = [
            cssX - halfWidth,
            cssY - halfHeight,
          ];
          // 解决y方向的差异
          const yBaseCenterTop = -yBaseCenter;
          // 解决坐标基底的差异
          const [x, y] = [xBaseCenter / halfWidth, yBaseCenterTop / halfHeight];
          const size = Math.random() * 50 + 10;
          a_points.push({ x, y, size });
          render();
        });
    	script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 这个和顶点位置的修改是类似的,上面的a_PointSize 是一个浮点类型的变量
    • 在上面的案例中,无论是控制点位的尺寸,还是控制点位的位置,实际上都是对attribute变量的操控
    • 那我们如果想要再改变顶点的颜色呢?那就不能再用attribute限定符了,因为attribute限定符限定的就是顶点相关的数据

    顶点着色器颜色改变

    • 首先,限定颜色变量的限定符叫uniform
    • 基于上述代码结构,下面只添加或修改关键部分代码

    1 )在片元着色器脚本中定义相关代码

    <script id="fragmentShader" type="x-shader/x-fragment">
        precision mediump float;
        uniform vec4 u_FragColor;
        void main() {
            gl_FragColor = u_FragColor;
        }
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 在片元着色器里把控制顶点颜色的变量暴露出来
    • 第一行的precision mediump float 是对浮点数精度的定义,mediump 是中等精度的意思,这个必须要有,不然画不出东西来
    • 上面的uniform就是咱们刚才说过的限定符,vec4是4维的变量类型,u_FragColor就是变量名

    2 )在js中获取片元着色器暴露出的uniform变量

    <script type="module">
      const u_FragColor = gl.getUniformLocation(gl.program,'u_FragColor'); // 关键代码
    script>
    
    • 1
    • 2
    • 3
    • 上面的 getUniformLocation() 方法就是用于获取片元着色器暴露出的 uniform 变量的
    • 其第一个参数是程序对象,第二个参数是变量名
    • 这里的参数结构和获取attribute变量的 getAttributeLocation() 方法是一样的

    3 )修改uniform 变量

    // 设置随机颜色
    const color = new Float32Array([
        Math.random(),
        Math.random(),
        Math.random(),
        1.0
    ]);
    
    gl.uniform4fv(u_FragColor, color); // 在合适的地方进行修改:render方法中的 arr.forEach 循环中处理
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 在上面我们使用 uniform4fv() 方法修改的顶点颜色,也可以用 uniform4f() 方法一个个的写参数
    • uniform4f 中,4 是有4个数据,f 是float 浮点类型,就是r、g、b、a 这四个颜色数据, 如:gl.uniform4f(u_FragColor,1.0,1.0,0.0,1.0);
    • uniform4fv 中,4f 的意思和上面一样,v 是vector 矢量的意思,这在数学里就是向量的意思。由之前的4f可知,这个向量由4个浮点类型的分量构成
    • 在修改uniform变量的时候,这两种写法是一样的
      gl.uniform4f(u_FragColor,1.0,1.0,0.0,1.0);
      //等同于
      const color=new Float32Array([1.0,1.0,0.0,1.0]);
      gl.uniform4fv(u_FragColor,color);
      
      • 1
      • 2
      • 3
      • 4
      • uniform4f() 和uniform4fv() 也有着自己的同族方法,其中的4 可以变成1|2|3
      • uniform4fv() 方法的第二个参数必须是Float32Array 数组,不要使用普通的 Array 对象
      • Float32Array 是一种32 位的浮点型数组,它在浏览器中的运行效率要比普通的 Array 高很多
  • 相关阅读:
    C++右值引用和完美转发
    Cat1模组蓄“光”发展,广和通全场景助力光伏行业零碳发电
    【从零开始一步步学习VSOA开发】并行RPC服务端
    第2-3-1章 文件存储服务系统-nginx/fastDFS/minio/阿里云oss/七牛云oss
    一套完善的设备管理系统能给企业带来什么?
    选择Seata作为分布式事务方案,优秀的选择!
    Java实现数据脱敏
    ubuntu安装ch34x驱动,并安装串口调试助手
    算法37|738,714,968
    RabbitMQ学习笔记之Work Queues
  • 原文地址:https://blog.csdn.net/Tyro_java/article/details/133361364