WebGL - 初相识 - 着色器 - 变量

前言

书接上回,在上篇文章中我们一起探讨了 WebGL 的着色器,并了解到了如何创建着色器以及将其绘制到画布当中。

那么~!就有一个问题了,当我们想改变顶点着色器的位置数据或者片元着色器中的颜色数据要怎么做?

总不能修改着色器源码(GLSL)后,再走一次着色器的创建和渲染流程吧?那太繁琐了!

那么有更优雅的形式来变更着色器中的数据吗?

答案是肯定的,这也是我们这次需要讨论的内容 Attribute 变量以及 Uniform 变量!

注释1:代码示例部分都会把 HTML 省略掉!同时也去掉了之前的注释以让代码更加简洁!

Attribute 变量

Attribute 变量(属性变量)只能在 顶点着色器 中定义,它的作用是接收 JavaScript 程序传递过来的与 顶点 有关的数据,比如 顶点颜色法线坐标 等,它们是顶点的属性。

注释2:目前可以不纠结属性变量的可用范围,先简单理解它可以动态修改顶点着色器的位置数据即可!

声明 Attribute 变量并赋值

要使用 Attribute 变量,就必须修改之前的着色器源码。

首先需要在 main 函数外面,预先定义 Attribute 变量!而且在 main 函数内部定义的话是会报错的!

Attribute 变量的定义语法为:

ini 复制代码
变量类型    数据类型    变量名称  
attribute   vec4       aPosition;

具体示例如下所示:

csharp 复制代码
const vertexShaderSource = `
    // 这里就是定义 Attribute 变量,变量名为 aPosition,变量的数据类型为 vec4!
    // 注意,Attribute 变量的声明是在 main 函数外面!!
    // 这里虽然没有赋值,但是实际上是有默认值的,默认值是: vec4(0.0, 0.0, 0.0, 1.0) !!!
    attribute vec4 aPosition;
    // ----
    void main () {
        // 赋值
        gl_Position = aPosition; 
        gl_PointSize = 100.0;
    }
`

获取程序对象中 Attribute 变量的存储地址和渲染

这里主要是描述如何对已经渲染后的顶点着色器中的 Attribute 变量进行修改,这里我们需要用到 getAttribLocation 方法。

getAttribLocation 方法可以从指定的程序对象(WebGLProgram)中获取指定的 Attribute 变量(定义的属性变量的变量名)的 存储地址

arduino 复制代码
// 使用 getAttribLocation 方法获取某个 程序对象 中的 存储地址
//                                      程序对象     变量名
const aPosition = ctx.getAttribLocation(program, 'aPosition')

获取了指定 Attribute 变量的存储地址后,还需要给其设置新的值,并进行渲染操作才能真正的让画布更新,想要对存储地址重新设置值就需要用到 vertexAttrib[1,2,3,4]f[v] 方法族,这里只需要修改 x 坐标的值,所以可以直接使用 vertexAttrib1f 方法来修改 x 坐标的数值。

vertexAttrib[1,2,3,4]f[v] 中的 1,2,3,4 可以理解成入参个数分别对应 vec4 的数据格式,v 表带浮点数组类型,vertexAttrib3fv(new Float32Array(local, [10.0, 5.0, 2.0]))

scss 复制代码
// 修改 attribute 变量的值
ctx.vertexAttrib1f(aPosition, x)
// 重新绘制
ctx.drawArrays(ctx.POINTS, 0, 1)

Uniform 变量

Uniform 变量是用来修饰全局变量,它既可以在 顶点着色器 中定义,也可以在 片元着色器 中定义,用来接收与 顶点 无关的数据,例如:标量(如整数、浮点数)向量矩阵颜色 等。

声明 Uniform 变量并赋值

Uniform 变量的使用基本规则和 Attribute 变量基本一样!

需要注意的是,在使用 Uniform 变量进行声明的时候,需要声明变量的数据类型,你问我为什么?emmm 我母鸡呀~!先就这么记吧!当然如果你知道为什么的话麻烦告诉我一下,感谢!🤪

Uniform 变量的定义语法为:

sql 复制代码
变量类型    数据类型    变量名称  
uniform    vec4       aPosition;

限定符      精度        数据类型
precision  mediump     float

具体示例如下所示:

csharp 复制代码
const fragmentShaderSource = `
    // 指定精度,顶点着色器默认是高精度,所以不用设置,但是片元着色器没有默认精度
    // 低精度:lowp 中精度:mediump 高精度:highp
    precision mediump float;
    // 存储限定符 类型 变量名
    uniform vec4 uColor;
    void main () {
        gl_FragColor = uColor; 
    }
`

获取程序对象中 Uniform 变量的存储地址和渲染

同样基本上和 Attribute 变量的规则基本一致!

这里我们需要用到 getUniformLocation 方法。

getUniformLocation 方法可以从指定的程序对象(WebGLProgram)中获取指定的 Uniform 变量(定义的属性变量的变量名)的 存储地址

arduino 复制代码
// 使用方法和 getAttribLocation 一样 
//                                    程序对象   变量名
const uColor = ctx.getUniformLocation(program, 'uColor')

获取了指定 Uniform 变量的存储地址后,也需要通过 uniform[1234][fi][v] 方法族来修改变量,也是对标 Attribute 变量的 vertexAttrib[1,2,3,4]f[v] 的方法族,用法也相似,就不多说了,点进去看文档吧。

scss 复制代码
// 修改 uniform 变量的值
ctx.uniform4f(uColor, 1.0, 0.0, 0.0, 1.0)
// 重新绘制
ctx.drawArrays(ctx.POINTS, 0, 1)

总结

怎么说呢!对 GLSL 的语法了解还是太浅了,而且也没什么好的调试方法,出错了真就只能一行一行的看,相当困难!

当然先整些容易出效果的案例,后面对 WebGL 了解到一定程度后,再来系统的学习 GLSL 语法,可能会更让人容易接受吧!

完整代码太长了就不贴文章里面了,查看完整的代码用例 -> 地址

相关推荐
遗憾何来33 分钟前
第9章综合案例————众成远程教育
前端·javascript·css
开心工作室_kaic34 分钟前
ssm117网络教学平台的设计与实现+vue(论文+源码)_kaic
前端·javascript·vue.js
OEC小胖胖35 分钟前
Vue 3 中的 v-bind 完全指南
前端·javascript·vue.js·前端框架·web
Dreams°12336 分钟前
【Vue组件中使用数据绑定】
前端·javascript·vue.js
叶子_o40 分钟前
vue 获取摄像头拍照,并旋转、裁剪生成新的图片
前端·javascript·vue.js
xcLeigh40 分钟前
VUE3实现简洁的特色美食网站源码
前端·源码·vue3
果壳~1 小时前
【Java】SpringBoot模拟流式输出,前端使用流式接收数据并打印
java·前端·spring boot
DN金猿2 小时前
vue项目PC端和移动端实现在线预览pptx文件
前端·javascript·vue.js·ppt
hahaqi95272 小时前
layui 表格点击编辑感觉很好用,实现方法如下
前端·javascript·layui
我爱学习_zwj2 小时前
ArkTS的进阶语法-4(函数补充,正则表达式)
前端·华为·正则表达式·harmonyos