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>
  • 这个和顶点位置的修改是类似的,上面的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>
  • 在片元着色器里把控制顶点颜色的变量暴露出来
  • 第一行的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>
  • 上面的 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 循环中处理
  • 在上面我们使用 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);
    
    • uniform4f() 和uniform4fv() 也有着自己的同族方法,其中的4 可以变成1|2|3
    • uniform4fv() 方法的第二个参数必须是Float32Array 数组,不要使用普通的 Array 对象
    • Float32Array 是一种32 位的浮点型数组,它在浏览器中的运行效率要比普通的 Array 高很多

你可能感兴趣的:(Canvas,Webgl,Three.js,webgl,着色器)