javascript基础学习系列四百七十四:调试着色器和程序

给着色器传值
前面定义的每个着色器都需要传入一个值,才能完成工作。要给着色器传值,必须先找到要接收值 的变量。对于 uniform 变量,可以调用 gl.getUniformLocation()方法。这个方法返回一个对象,
这个例子从 program 中找到 uniform 变量 uColor,然后返回了它的内存位置。第二行代码调用 gl.uniform4fv()方法给 uColor 传入了值。
给顶点着色器传值也是类似的过程。而要获得 attribute 变量的位置,可以调用 gl.getAttrib- Location()方法。找到变量的内存地址后,可以像下面这样给它传入值:

let aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); gl.enableVertexAttribArray(aVertexPosition); gl.vertexAttribPointer(aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);

表示该 uniform 变量在内存中的位置。然后,可以使用这个位置来完成赋值。比如: let uColor = gl.getUniformLocation(program, “uColor”);

   gl.uniform4fv(uColor, [0, 0, 0, 1]);

这里,首先取得 aVertexPosition 的内存位置,然后使用 gl.enableVertexAttribArray() 来启用。最后一行代码创建了一个指向调用 gl.bindBuffer()指定的缓冲区的指针,并把它保存在 aVertexPosition 中,从而可以在后面由顶点着色器使用。

调试着色器和程序

与 WebGL 中的其他操作类似,着色器操作也可能失败,而且是静默失败。如果想知道发生了什么 错误,则必须手工通过 WebGL 上下文获取关于着色器或程序的信息。 20
对于着色器,可以调用 gl.getShaderParameter()方法取得编译之后的编译状态:

if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(vertexShader));
}

着色器程序也可能失败,因此也有类似的方法。gl.getProgramParameter()用于检测状态。最 23 常见的程序错误发生在链接阶段,为此可以使用以下代码来检查:
这个例子检查了 vertexShader 编译的状态。如果着色器编译成功,则调用 gl.getShaderParameter() 会返回 true。如果返回 false,则说明编译出错了。此时,可以使用 gl.getShaderInfoLog()并传 入着色器取得错误。这个方法返回一个字符串消息,表示问题所在。
gl.getShaderParameter()和 gl.getShaderInfoLog()既可以用于顶点着色器,也可以用于片段着色器。

  alert(gl.getProgramInfoLog(program));
}

与gl.getShaderParameter()一样,gl.getProgramParameter()会在链接成功时返回true, 失败时返回 false。当然也有一个 gl.getProgramInfoLog()方法,可以在程序失败时获取错误 信息。
这些方法主要在开发时用于辅助调试。只要没有外部依赖,在产品环境中就可以放心地删除它们。
 GLSL 100 升级到 GLSL 300
WebGL2 的主要变化是升级到了 GLSL 3.00 ES 着色器。这个升级暴露了很多新的着色器功能,包括 3D 纹理等在支持 OpenGL ES 3.0 的设备上都有的功能。要使用升级版的着色器,着色器代码的第一行必须是: 27
#version 300 es
这个升级需要一些语法的变化。
 顶点 attribute 变量要使用 in 而不是 attribute 关键字声明。
 使用 varying 关键字为顶点或片段着色器声明的变量,现在必须根据相应着色器的行为改为使 用in或out。
 预定义的输出变量 gl_FragColor 没有了,片段着色器必须为颜色输出声明自己的 out 变量。
 纹理查找函数 texture2D 和 textureCube 统一成了一个 texture 函数。

绘图

WebGL 只能绘制三种形状:点、线和三角形。其他形状必须通过这三种基本形状在 3D 空间的组合 来绘制。WebGL 绘图要使用 drawArrays()和 drawElements()方法,前者使用数组缓冲区,后者则 操作元素数组缓冲区。
drawArrays()和 drawElements()的第一个参数都表示要绘制形状的常量。下面列出了这些常量。
 gl.POINTS:将每个顶点当成一个点来绘制。
 gl.LINES:将数组作为一系列顶点,在这些顶点间绘制直线。每个顶点既是起点也是终点,因
此数组中的顶点必须是偶数个才能开始绘制。
 gl.LINE_LOOP:将数组作为一系列顶点,在这些顶点间绘制直线。从第一个顶点到第二个顶点
绘制一条直线,再从第二个顶点到第三个顶点绘制一条直线,以此类推,直到绘制到最后一个
顶点。此时再从最后一个顶点到第一个顶点绘制一条直线。这样就可以绘制出形状的轮廓。
 gl.LINE_STRIP:类似于 gl.LINE_LOOP,区别在于不会从最后一个顶点到第一个顶点绘制直线。
 gl.TRIANGLES:将数组作为一系列顶点,在这些顶点间绘制三角形。如不特殊指定,每个三角
形都分开绘制,不共享顶点。
 gl.TRIANGLES_STRIP:类似于 gl.TRIANGLES,区别在于前 3 个顶点之后的顶点会作为第三
个顶点与其前面的两个顶点构成三角形。例如,如果数组中包含顶点 A、B、C、D,那么第一个
三角形使用 ABC,第二个三角形使用 BCD。
 gl.TRIANGLES_FAN:类似于 gl.TRIANGLES,区别在于前 3 个顶点之后的顶点会作为第三个
顶点与其前面的顶点和第一个顶点构成三角形。例如,如果数组中包含顶点 A、B、C、D,那么
第一个三角形使用 ABC,第二个三角形使用 ACD。
以上常量可以作为 gl.drawArrays()方法的第一个参数,第二个参数是数组缓冲区的起点索引,
第三个参数是数组缓冲区包含的顶点集合的数量。以下代码使用 gl.drawArrays()在画布上绘制了一 个三角形:

// 假设已经使用本节前面的着色器清除了视口
// 定义3个顶点的x坐标和y坐标
let vertices = new Float32Array([ 0, 1, 1, -1, -1, -1 ]),
        buffer = gl.createBuffer(),
        vertexSetSize = 2,
        vertexSetCount = vertices.length/vertexSetSize,
        uColor,
        aVertexPosition;
// 将数据放入缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 给片段着色器传入颜色
uColor = gl.getUniformLocation(program, "uColor"); gl.uniform4fv(uColor, [ 0, 0, 0, 1 ]);
// 把顶点信息传给着色器
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition"); gl.enableVertexAttribArray(aVertexPosition);

接着给顶点着色器传入顶点集的大小,以及表示顶点坐标数值类型的 gl.FlOAT。第四个参数是一 个布尔值,表示坐标不是标准的。第五个参数是步长值(stride value),表示跳过多个数组元素取得下一 个值。除非真要跳过一些值,否则就向这里传入 0 即可。最后一个参数是起始偏移量,这里的 0 表示从 第一个数组元素开始。 18
最后一步是使用 gl.drawArrays()把三角形绘制出来。通过把第一个参数指定为 gl.TRIANGLES, 就可以从(0, 1)到(1, –1)再到(–1, –1)绘制一个三角形,并填充传给片段着色器的颜色。第二个参数表示缓 冲区的起始偏移量,最后一个参数是要读取的顶点数量。以上绘图操作的结果

这个例子定义了一个 Float32Array 变量,它包含 3 组两个点的顶点。完成计算的关键是跟踪顶 点大小和数量。将 vertexSetSize 的值指定为 2,再计算出 vertexSetCount。顶点信息保存在了缓 冲区。然后把颜色信息传给片段着色器。

gl.vertexAttribPointer(aVertexPosition, vertexSetSize, gl.FLOAT, false, 0, 0); // 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, vertexSetCount);

通过改变 gl.drawArrays()的第一个参数,可以修改绘制三角形的方式。图 18-17 展示了修改第
一个参数之后的两种输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值