首先我们要知道,限定颜色变量的限定符叫uniform。
uniform 翻译过来是一致、统一的意思。
接下来咱们说一下用js 控制顶点颜色的步骤。
1.在片元着色器里把控制顶点颜色的变量暴露出来。
const fsSource = ` //设置精度 precision mediump float; //暴露颜色 uniform vec4 u_color; void main(){ gl_FragColor=u_color; } `
上面的uniform 就是咱们刚才说过的限定符,vec4 是4维的变量类型,u_FragColor 就是变量名。
这里还要注意一下,第一行的precision mediump float 是对浮点数精度的定义,mediump 是中等精度的意思,这个必须要有,不然画不出东西来。
2.在js 中获取片元着色器暴露出的uniform 变量
//获取片元着色器暴露的变量 const u_color = gl.getUniformLocation(gl.program, 'u_color')
上面的getUniformLocation() 方法就是用于获取片元着色器暴露出的uniform 变量的,其第一个参数是程序对象,第二个参数是变量名。这里的参数结构和获取attribute 变量的getAttributeLocation() 方法是一样的。
3.修改uniform 变量
gl.uniform4f(u_color, r, g, b, a)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <canvas id="canvas" width="400" height="400"></canvas> </body> <script src="../lib/webgl-utils.js"></script> <script src="../lib/webgl-debug.js"></script> <script src="../lib/cuon-utils.js"></script> <script type="module"> let canvas = document.getElementById('canvas'); let gl = canvas.getContext('webgl', { preserveDrawingBuffer: true }); const verSource = ` attribute vec4 a_Position; attribute float pointSize; void main(){ gl_Position=a_Position; gl_PointSize=pointSize; } ` const fsSource = ` //设置精度 precision mediump float; //暴露颜色 uniform vec4 u_color; void main(){ gl_FragColor=u_color; } ` initShaders(gl, verSource, fsSource); const points = [{ x: -0.3, y: 0, size: 10.0, color: { r: 1, g: 0, b: 0, a: 1 } }, { x: 0.3, y: 0, size: 10.0, color: { r: 0.5, g: 0, b: 0, a: 1 } }]; //获取a_Position的存储空间,然后通过js改变储存空间的内容 const a_Position = gl.getAttribLocation(gl.program, 'a_Position'); const pointSize = gl.getAttribLocation(gl.program, 'pointSize'); //获取片元着色器暴露的变量 const u_color = gl.getUniformLocation(gl.program, 'u_color') gl.clearColor(0, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); gl.vertexAttrib2f(a_Position, -0.3, 0) gl.vertexAttrib1f(pointSize, 10) const tem = new Float32Array([1, 0, 0, 1]) // gl.uniform4f(u_color, r, g, b, a) gl.uniform4fv(u_color, tem) gl.drawArrays(gl.POINTS, 0, 1); gl.vertexAttrib2f(a_Position, 0.3, 0) gl.vertexAttrib1f(pointSize, 10) const tem1 = new Float32Array([0, 1, 0, 1]) // gl.uniform4f(u_color, r, g, b, a) gl.uniform4fv(u_color, tem1) gl.drawArrays(gl.POINTS, 0, 1); canvas.addEventListener('click', e => { //获取鼠标点击的位置 const { clientX, clientY } = e; //获取cvavas距离窗口的位置 const { left, top, width, height } = canvas.getBoundingClientRect(); //求出鼠标点距canvas的位置 const [clickX, clickY] = [clientX - left, clientY - top]; //得到canvas的原点位置(像素为单位)。 const [centerX, centerY] = [width / 2, height / 2]; //求出鼠标点位距离中心店的位置 const [xDis, yDis] = [clickX - centerX, clickY - centerY]; //webgl中正向的y其实是负向的y const clickTop = -yDis; //现在有了中心位置,和点击的位置,求出比例即可 const [x, y] = [xDis / centerX, clickTop / centerY]; const size = Math.random() * 50; const n = Math.random(); gl.vertexAttrib2f(a_Position, x, y) gl.vertexAttrib1f(pointSize, Math.random() * 20); const color = { r: n, g: n, b: n, a: 1 } const tem1 = new Float32Array([n, n, n, 1]) // gl.uniform4f(u_color, color.r, color.g, color.b, color.a) gl.uniform4fv(u_color, tem1) gl.drawArrays(gl.POINTS, 0, 1); }) </script> </html>
uniform4fv() 方法
我们在改变uniform 变量的时候,既可以用uniform4f() 方法一个个的写参数,也可以用uniform4fv() 方法传递类型数组。
uniform4f 中,4 是有4个数据,f 是float 浮点类型,在我们上面的例子里就是r、g、b、a 这四个颜色数据。
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 高很多。
发表评论
侧栏公告
寄语
譬如朝露博客是一个分享前端知识的网站,联系方式11523518。
热评文章
标签列表
热门文章
友情链接