五、使用 uniform 变量 - 绘制不同颜色的点

206 阅读3分钟

关于uniform变量的使用原理: uniform变量在WebGL中是用来传递那些对于一次绘制调用中所有顶点和片元都保持一致的数据。它们是全局的GLSL变量,可以在顶点着色器和片元着色器中访问,但不能在着色器中被修改(即它们是只读的)。因为uniform变量在一次绘制调用中是恒定不变的,所以它们不适合用来传递顶点数据,顶点数据通常是每个顶点不同的,需要使用attribute变量来传递。

1、定义uniform变量

使用uniform变量给片元着色器定义变量的时候,不像顶点着色器一样有默认精度,所以需要设置默认精度,否则会报错。

设置精度:

precision mediump float;

高精度 : highp ,中精度:mediump,低精度:lowp,

定义uniform变量

uniform vec4 uColor

2、获取uniform变量

gl.getUniformLocation(program, name )

  • 此方法使用和入参与 glgetAttribLocation 相同
  • program:包含顶点和片元着色器的程序对象
  • name: uniform 变量的名称

3、给uniform变量赋值

gl.uniform4f(location, v0, v1, v2, v3 )

location:指定 uniform 的存储地

v0:第一个分量的值 r

v1:第二个分量的值 g

v2:第三个分量的值 b

v3:第四个分量的值 a

uniform4f0 同族函数介绍

gl.uniform1f(location, v0)

gl.uniform2f(location, v0, v1)

gl.uniform3f(location, v0, v1, v2)

gl.uniform4f(location, v0, vl, v2, v3)

在赋值的时候有个地方需要注意,在uniform定义变量时,使用的类型不同,使用的方法也不同 当类型为float时,使用uniform1f();

    const FRAGMENT_SHADER_SOURCE = `
             //  设置默认精度
        precision mediump float;
        //  uniform 只能用于传递颜色
        uniform float uColor;
        void main(){
         gl_FragColor = vec4(uColor,0.0,0.0,1.0);
        }
      `;
     const uColor = webgl.getUniformLocation(program, 'uColor')
     webgl.uniform1f(uColor,1.0);

当类型为vec2时,使用uniform2f();

    const FRAGMENT_SHADER_SOURCE = `
            //  设置默认精度
            precision mediump float;
            //  uniform 只能用于传递颜色
            uniform vec2 uColor;
            void main(){
             gl_FragColor = vec4(uColor.r, uColor.g, 0.0,1.0); 
            }

      `;
    const uColor = webgl.getUniformLocation(program, 'uColor')
    webgl.uniform2f(uColor,1.0,0.0)

当类型为vec3时,使用uniform3f();

    const FRAGMENT_SHADER_SOURCE = `
             //  设置默认精度
        precision mediump float;
        //  uniform 只能用于传递颜色
        uniform vec3 uColor;
        void main(){
         gl_FragColor = vec4(uColor.r, uColor.g, uColor.b,1.0);
        }
      `;
    const uColor = webgl.getUniformLocation(program, 'uColor')
    webgl.uniform3f(uColor,1.0,0.0,0.0)

代码展示

let webglDiv = document.getElementById('practice');
let webgl = webglDiv.getContext('webgl');

/*着色器*/
// 顶点着色器
const VERTEX_SHADER_SOURCE = `
        //  attribute 只能用于传递定点数据
       attribute vec4 aPosition ;
        void main(){
          // 要绘制的点的坐标
          gl_Position = aPosition;
          // 点的大小
          gl_PointSize = 20.0;
        }
  `;
// 片元着色器
const FRAGMENT_SHADER_SOURCE = `
        //  设置默认精度
        precision mediump float;
        //  uniform 只能用于传递颜色
        uniform vec4 uColor;
        void main(){
          gl_FragColor =  uColor  ;
        }
  `;

// 创建着色器并绑定程序对象
const program =  initShader(webgl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE);

// 获取attribute变量
const aPosition = webgl.getAttribLocation(program,'aPosition');

// 获取uniform 变量
const  uColor = webgl.getUniformLocation(program,'uColor');

const points = [];
webglDiv.onclick  = function (event){
      // x轴的一半
  let divisorX = webglDiv.offsetWidth/2;
  // y轴的一半
  let divisorY = webglDiv.offsetWidth/2;
  let x  =  (event.offsetX - divisorX)/divisorX;
  let y = (divisorX - event.offsetY)/divisorY;

  points.push({
    x,y
  });
  for (let i = 0; i < points.length; i++) {
    const {x, y} = points[i];
    webgl.vertexAttrib2f(aPosition, x, y);
    webgl.uniform4f(uColor,x, y,1.0,1.0); // uniform 变量赋值
  }

  // 执行绘制
  // drawArrays(绘制的图形,从哪个点开始,使用几个顶点)
  webgl.drawArrays(webgl.POINTS, 0, 1);
};

流程图 image.png