当前位置:  首页>> 技术小册>> 微信小程序全栈开发实战(上)

41 | WebGL介绍(五):学习片断着色器编写,了解变量修饰符Uniform与Attribute

在WebGL这一强大的图形API中,着色器(Shader)是核心组件之一,它们直接控制图形硬件进行顶点处理和像素填充。着色器分为顶点着色器(Vertex Shader)和片断着色器(Fragment Shader,或称像素着色器Pixel Shader)。顶点着色器负责处理图形的顶点数据,如位置、颜色、纹理坐标等,并将这些数据传递给片断着色器;而片断着色器则负责处理每个像素的最终颜色输出。在本章中,我们将深入学习片断着色器的编写,并重点介绍两种关键的变量修饰符:uniformattribute,它们在着色器程序中扮演着至关重要的角色。

一、片断着色器基础

片断着色器是WebGL渲染管线中的最后一步,它决定了每个像素的最终颜色。在WebGL中,片段着色器通常使用GLSL(OpenGL Shading Language)编写,这是一种类似于C的编程语言,专为图形处理而设计。

基本结构
一个基本的片断着色器代码框架如下:

  1. precision mediump float;
  2. void main() {
  3. gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 将每个像素设置为红色
  4. }

这里,gl_FragColor是GLSL内置的输出变量,用于存储计算后的像素颜色。vec4是一个四维向量,分别代表红、绿、蓝和透明度(RGBA)的值,范围从0.0到1.0。

二、理解Uniform变量

定义与用途
uniform变量在着色器程序中用于从JavaScript代码向着色器传递只读数据。一旦uniform变量被设置,它将在整个着色器程序执行期间保持不变,这对于传递如变换矩阵、光源位置、材质属性等在整个渲染过程中不会改变的数据非常有用。

示例
假设我们想要根据时间改变整个场景的颜色,我们可以使用JavaScript代码更新一个uniform变量来动态调整颜色。

GLSL端

  1. precision mediump float;
  2. uniform vec3 u_Color; // 声明一个uniform变量来接收颜色
  3. void main() {
  4. gl_FragColor = vec4(u_Color, 1.0); // 使用uniform变量设置像素颜色
  5. }

JavaScript端

  1. // 假设已经创建了WebGL上下文和着色器程序
  2. let u_ColorLocation = gl.getUniformLocation(shaderProgram, 'u_Color');
  3. gl.uniform3f(u_ColorLocation, 0.5, 0.0, 0.5); // 设置uniform变量为紫色

三、探索Attribute变量

定义与用途
uniform不同,attribute变量用于在顶点着色器中接收每个顶点特有的数据,如顶点的位置、法线、纹理坐标等。每个顶点都会执行一次顶点着色器,并且每次执行时attribute变量的值都会不同,这取决于当前处理的顶点。

示例
考虑一个简单的二维三角形,我们需要为三角形的每个顶点指定位置。

GLSL端(顶点着色器)

  1. attribute vec2 a_Position; // 声明一个attribute变量来接收顶点位置
  2. void main() {
  3. gl_Position = vec4(a_Position, 0.0, 1.0); // 将顶点位置传递给gl_Position
  4. }

JavaScript端
设置attribute变量通常涉及创建缓冲区(Buffer)对象,并将顶点数据上传到GPU。

  1. // 假设已有WebGL上下文和着色器程序
  2. let a_PositionLocation = gl.getAttribLocation(shaderProgram, 'a_Position');
  3. // 创建缓冲区并上传数据(略去具体细节)
  4. // ...
  5. // 在绘制调用前启用attribute变量
  6. gl.enableVertexAttribArray(a_PositionLocation);
  7. // 将缓冲区对象绑定到attribute变量
  8. gl.vertexAttribPointer(a_PositionLocation, 2, gl.FLOAT, false, 0, 0);
  9. // 绘制三角形(略去具体绘制命令)
  10. // ...

四、Uniform与Attribute的比较

  • 作用域与用途uniform变量在整个着色器程序中是全局的,用于传递不随顶点变化的数据;而attribute变量仅在顶点着色器中有效,用于接收每个顶点的特定数据。
  • 更新频率uniform变量一旦设置,在整个渲染过程中保持不变,直到被重新设置;attribute变量则随每个顶点的处理而变化。
  • 数据传递方式uniform变量通过JavaScript代码直接设置,而attribute变量通常通过缓冲区对象与WebGL的API接口传递。

五、进阶应用与最佳实践

  • 性能优化:合理使用uniformattribute变量对于优化WebGL程序的性能至关重要。尽量减少uniform的更新次数,因为它们可能会引起渲染状态的改变,从而影响性能。
  • 数据管理:对于复杂的数据结构,如骨骼动画中的骨骼权重和位置,可能需要更复杂的策略来管理数据传递,比如使用GLSL的数组或结构体,以及更复杂的缓冲区绑定策略。
  • 调试与测试:着色器代码的错误调试相比JavaScript更为复杂,因为它们运行在GPU上。使用WebGL的调试工具(如Chrome的WebGL Inspector)和着色器编译器输出的日志信息来定位和解决问题。

通过本章的学习,您应该已经掌握了WebGL片断着色器的基本编写方法,以及如何通过uniformattribute变量在JavaScript与着色器程序之间传递数据。这些基础知识将为您进一步探索WebGL的复杂功能和优化技术打下坚实的基础。


该分类下的相关小册推荐: