WebGL - 通过 js 程序向 attribute 和 uniform 变量赋值

本文介绍了如何在WebGL中通过attribute和uniform变量向着色器传递数据,控制顶点的位置和大小。首先,讲解了attribute变量的声明、获取存储位置和赋值方法,如gl.vertexAttrib3f()。接着,阐述了uniform变量的使用,包括声明、获取存储地址以及使用gl.uniform4f()系列方法进行赋值。通过示例代码,详细展示了向顶点和片元着色器传递常量数据的过程。
摘要由CSDN通过智能技术生成

有两种方式可以通过js程序向着色器传递数据

  • 通过 attribute变量 – 传输的是与顶点相关的数据
  • 通过 uniform变量 – 传输的是对所有顶点都相同或者与顶点无关的数据

通过上一个程序,在webgl中绘制了一个顶点,但是顶点的位置不能通过js程序来控制,下面通过js给顶点着色器传递数据来控制顶点的位置。

1、在顶点着色器中生命 attribute 变量

// 顶点着色器
// 声明一个 attribute 变量 类型是 vec4
attribute vec4 a_Position;
void main(){
    
}

2、将 attribute 变量赋值给 gl_Position

// 顶点着色器
// 声明一个 attribute 变量 类型是 vec4
attribute vec4 a_Position;
void main(){
    // 将声明的变量赋值给gl内置的变量
    gl_Position = a_Position;
    // 设置顶点的大小单位是像素
    gl_PointSize = 10.0; 
}

3、通过 js 向 attribute 变量传值

// 获取 attribute 变量 a_Position 的存储地址
var a_Position = gl.getAttribLocation(gl.program,'a_Position');

// 创建一个类型话数组
var positions = new Float32Array([0.5, 0.0, 0.0, 1.0]);

// 将顶点位置传递给 attribute 变量
gl.vertexAttrib4fv(a_Position,positions);

通过以上三个步骤就实现了,通过jswebgl着色器传递数据

1、存储限定符

上面代码中的 attribute vec4 a_Position;

关键词 attribute 是存储限定符,表示接下来的声明的变量是一个attribute变量

注意:attribute变量必须声明为全局变量

变量的声明格式

格式示例
<存储限定符><类型><变量名>;attribute vec a_Position;

2、获取变量的存储位置

着色器代码中每个变量都有一个 存储地址,以便于通过 存储地址向变量传输数据

获取 attribute 变量 存储地址的方法是,挂载在gl对象上的 gl.getAttribLocation()方法

该方法的第一个参数是一个程序对象 gl.proram,包含了顶点着色器和片元着色器

第二个参数是想要获存储地址的 attribute变量的名称字符串

var a_Position = gl.getAttribLocation(gl.program,'a_Position');

返回值是一个存储地址

变量名参数返回值
gl.getAttribLocation(program, name)program:程序对象name:变量名称大于等于0是:拿到地址-1:变量不存在

3、向变量赋值

// 向顶点位置传输数据
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

**gl.vertexAttrib3f(location, v0, v1, v2)**是将数据(v0, v1, v2)传给有location指定的attribute变量

4、gl.vertexAttrib3f()的同族方法

  • gl.vertexAttrib1f(location, v0)
  • gl.vertexAttrib2f(location, v0, v1)
  • gl.vertexAttrib3f(location, v0, v1, v2)
  • gl.vertexAttrib4f(location, v0, v1, v2, v3)

以上系列方法的主要任务就是将数据从js传输给attribute变量,以上每个方法都有一个矢量版本,上面的是以 f结尾,矢量版本是以 v结尾,并且可以接受一个类型化数组

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypedArray

// 创建一个类型话数组
var positions = new Float32Array([0.5, 0.0, 0.0, 1.0]);

// 将顶点位置传递给 attribute 变量
gl.vertexAttrib4fv(a_Position,positions);

既然可以通过js程序改变顶点的位置,那么也可以改变大小

顶点着色器

// 声明 attribute 变量 传递顶点位置
attribute vec4 a_Position;
// 声明 attribute 变量 传递顶点大小
attribute float a_PointSize;

void main(){
    gl_Position = a_Position;
    gl_PointSize = a_PointSize;
}

获取存储地址并传值

var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
var a_PointSize = gl.getAttributLocation(gl.program, 'a_PointSize');

// 传递顶点位置
gl.vertexAttrib3f(a_Position, 0.0, 0.0, 0.0);

// 传递顶点大小
gl.vertexAttrib1f(a_PointSize, 10.0);
示例代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>通过 attribute 向着色器传递数据</title>
    <link rel="stylesheet" href="../css/common.css">
</head>
<body>
<canvas id="webgl" width="512" height="512"></canvas>
</body>
<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>

<script>
    (function () {

        // 获取canvas对象
        var canvas = document.getElementById('webgl');

        // 获取webgl 上下文对象
        var gl = getWebGLContext(canvas);

        // 顶点着色器
        var vertex_shader_source = '' +
            'attribute vec4 a_Position;' +
            'void main() {' +
            '   gl_Position = a_Position;' +
            '   gl_PointSize = 10.0;' +
            '}';
        // 片元着色器
        var fragment_shader_source = '' +
            'void main() {' +
            '   gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' +
            '}';

        // 初始化着色器
        if (!initShaders(gl, vertex_shader_source, fragment_shader_source)) {
            console.log('初始化着色器失败!');
            return false;
        }

        // 获取 attribute 变量 a_Position 的存储地址
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');

        if (a_Position < 0) {
            console.log('获取 a_Position 变量地址失败!');
            return false;
        }

        // 将顶点位置传递给 attribute 变量
        // gl.vertexAttrib1f(a_Position, -0.5);
        // gl.vertexAttrib2f(a_Position, -0.5, -0.5);
        // gl.vertexAttrib3f(a_Position, -0.5, -0.5, 0.0);
        // gl.vertexAttrib4f(a_Position, -0.5, -0.5, 0.0, 1.0);

        var positions = new Float32Array([0.5, 0.0, 0.0, 1.0]);
        gl.vertexAttrib4fv(a_Position, positions);

        // 指定需要清除的颜色
        gl.clearColor(0.0, 0.5, 0.5, 1.0);

        // 清除颜色
        gl.clear(gl.COLOR_BUFFER_BIT);

        // 绘制顶点
        gl.drawArrays(gl.POINTS, 0, 1);

    }());


</script>
</html>

uniform

1、存储限定符

向顶点着色器中传递数据是通过 attribute,向片元着色器中传递数据就需要使用 uniform声明变量,uniform变量传递的数据是一致的不变的数据例如所有的颜色应用的都是这个变量但是所有点的位置是不一样的,而 attribute传递的数据是变化的。

uniformattribute一样都是存储限定符;

2、获取存储地址

通过方法 gl.getUniformLocation(program, name)可以获取 uniform变量的存储地址

功能和gl.getAttribLocation(ptogram, name)一样,注意如果变量不存在或者使用保留字此时**gl.getUniformLocation(program, name)**返回的是 null不是 -1.

3、gl.uniform4f()同族方法

gl.vertexAttribute3f()基本一样

示例代码

// 声明 uniform 变量 储存颜色值
uniform vec4 u_FragColor;
void main(){
    // 将uniform 变量赋值
    gl_FragColor = u_FragColor; 
}
// 获取 uniform 变量
var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');

// 赋值
gl.uniform4f(u_FragColor, 0.0, 1.0, 0.0, 1.0);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值