返回
用GLSL编程实现动态彩色冲击波的动画效果
见解分享
2024-01-04 14:07:14
- 准备工作
首先,我们需要准备一个GLSL着色器。着色器是一种程序,它可以在图形硬件上运行,以生成图像。我们将使用WebGL来实现我们的着色器,WebGL是一个JavaScript API,它允许我们在浏览器中运行GLSL着色器。
// 顶点着色器
const vertexShaderSource = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`;
// 片段着色器
const fragmentShaderSource = `
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
void main() {
// 计算圆形坐标
vec2 position = gl_FragCoord.xy - 0.5 * u_resolution;
float distance = length(position);
// 计算颜色
float color = 0.0;
color += smoothstep(0.0, 0.1, distance);
color += smoothstep(0.1, 0.2, distance);
color += smoothstep(0.2, 0.3, distance);
// 输出颜色
gl_FragColor = vec4(color, color, color, 1.0);
}
`;
2. 构建着色器程序
接下来,我们需要将顶点着色器和片段着色器组合成一个着色器程序。着色器程序是可以在图形硬件上运行的完整程序。
// 创建着色器程序
const program = gl.createProgram();
// 附加顶点着色器
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
gl.attachShader(program, vertexShader);
// 附加片段着色器
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
gl.attachShader(program, fragmentShader);
// 链接着色器程序
gl.linkProgram(program);
// 使用着色器程序
gl.useProgram(program);
3. 设置Uniform变量
现在,我们需要设置一些Uniform变量,这些变量可以在着色器程序中使用。Uniform变量是可以在着色器程序中访问的全局变量。
// 设置u_time变量
const u_timeLocation = gl.getUniformLocation(program, "u_time");
gl.uniform1f(u_timeLocation, 0.0);
// 设置u_resolution变量
const u_resolutionLocation = gl.getUniformLocation(program, "u_resolution");
gl.uniform2fv(u_resolutionLocation, [gl.canvas.width, gl.canvas.height]);
4. 绘制图像
最后,我们可以使用着色器程序来绘制图像。
// 清空画布
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
// 绑定顶点数据
const vertices = new Float32Array([-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 绑定位置属性
const a_positionLocation = gl.getAttribLocation(program, "a_position");
gl.vertexAttribPointer(a_positionLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_positionLocation);
// 绘制图像
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
5. 动画
为了实现动画,我们需要不断更新u_time变量的值。
function animate() {
// 请求下一次动画帧
requestAnimationFrame(animate);
// 更新时间
const time = Date.now() * 0.001;
gl.uniform1f(u_timeLocation, time);
// 绘制图像
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
}
// 启动动画
animate();
现在,你应该就可以看到一个动态的彩色冲击波动画效果了。