在WebGL这一强大的图形API中,着色器(Shader)是核心组件之一,它们直接控制图形硬件进行顶点处理和像素填充。着色器分为顶点着色器(Vertex Shader)和片断着色器(Fragment Shader,或称像素着色器Pixel Shader)。顶点着色器负责处理图形的顶点数据,如位置、颜色、纹理坐标等,并将这些数据传递给片断着色器;而片断着色器则负责处理每个像素的最终颜色输出。在本章中,我们将深入学习片断着色器的编写,并重点介绍两种关键的变量修饰符:uniform
和attribute
,它们在着色器程序中扮演着至关重要的角色。
片断着色器是WebGL渲染管线中的最后一步,它决定了每个像素的最终颜色。在WebGL中,片段着色器通常使用GLSL(OpenGL Shading Language)编写,这是一种类似于C的编程语言,专为图形处理而设计。
基本结构:
一个基本的片断着色器代码框架如下:
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 将每个像素设置为红色
}
这里,gl_FragColor
是GLSL内置的输出变量,用于存储计算后的像素颜色。vec4
是一个四维向量,分别代表红、绿、蓝和透明度(RGBA)的值,范围从0.0到1.0。
定义与用途:uniform
变量在着色器程序中用于从JavaScript代码向着色器传递只读数据。一旦uniform
变量被设置,它将在整个着色器程序执行期间保持不变,这对于传递如变换矩阵、光源位置、材质属性等在整个渲染过程中不会改变的数据非常有用。
示例:
假设我们想要根据时间改变整个场景的颜色,我们可以使用JavaScript代码更新一个uniform
变量来动态调整颜色。
GLSL端:
precision mediump float;
uniform vec3 u_Color; // 声明一个uniform变量来接收颜色
void main() {
gl_FragColor = vec4(u_Color, 1.0); // 使用uniform变量设置像素颜色
}
JavaScript端:
// 假设已经创建了WebGL上下文和着色器程序
let u_ColorLocation = gl.getUniformLocation(shaderProgram, 'u_Color');
gl.uniform3f(u_ColorLocation, 0.5, 0.0, 0.5); // 设置uniform变量为紫色
定义与用途:
与uniform
不同,attribute
变量用于在顶点着色器中接收每个顶点特有的数据,如顶点的位置、法线、纹理坐标等。每个顶点都会执行一次顶点着色器,并且每次执行时attribute
变量的值都会不同,这取决于当前处理的顶点。
示例:
考虑一个简单的二维三角形,我们需要为三角形的每个顶点指定位置。
GLSL端(顶点着色器):
attribute vec2 a_Position; // 声明一个attribute变量来接收顶点位置
void main() {
gl_Position = vec4(a_Position, 0.0, 1.0); // 将顶点位置传递给gl_Position
}
JavaScript端:
设置attribute
变量通常涉及创建缓冲区(Buffer)对象,并将顶点数据上传到GPU。
// 假设已有WebGL上下文和着色器程序
let a_PositionLocation = gl.getAttribLocation(shaderProgram, 'a_Position');
// 创建缓冲区并上传数据(略去具体细节)
// ...
// 在绘制调用前启用attribute变量
gl.enableVertexAttribArray(a_PositionLocation);
// 将缓冲区对象绑定到attribute变量
gl.vertexAttribPointer(a_PositionLocation, 2, gl.FLOAT, false, 0, 0);
// 绘制三角形(略去具体绘制命令)
// ...
uniform
变量在整个着色器程序中是全局的,用于传递不随顶点变化的数据;而attribute
变量仅在顶点着色器中有效,用于接收每个顶点的特定数据。uniform
变量一旦设置,在整个渲染过程中保持不变,直到被重新设置;attribute
变量则随每个顶点的处理而变化。uniform
变量通过JavaScript代码直接设置,而attribute
变量通常通过缓冲区对象与WebGL的API接口传递。uniform
和attribute
变量对于优化WebGL程序的性能至关重要。尽量减少uniform
的更新次数,因为它们可能会引起渲染状态的改变,从而影响性能。通过本章的学习,您应该已经掌握了WebGL片断着色器的基本编写方法,以及如何通过uniform
和attribute
变量在JavaScript与着色器程序之间传递数据。这些基础知识将为您进一步探索WebGL的复杂功能和优化技术打下坚实的基础。