滤镜篇:绘制图片+滤镜初探
2024-01-30 10:49:57
我将根据您的输入生成专业级别的文章。为了让文章看起来更具真实感,我会尽量避免使用人工智能特有的固定用语和模板。
半小时轻松玩转WebGL滤镜技术(一)
滤镜是我们平时修图时不可缺少的一部分,利用滤镜可以对图像进行色彩校正、模糊、浮雕等各种处理,从而让图像呈现出不同的效果。其实,滤镜的原理并不复杂,它本质上就是一种数学运算,通过对图像中的像素进行逐个计算,从而实现各种各样的效果。
在 WebGL 中,我们可以通过编写着色器程序来实现滤镜效果。着色器程序是一种特殊类型的程序,它可以在 GPU 上运行,用于处理顶点数据和片段数据。顶点数据负责定义物体的形状,而片段数据则负责定义物体的颜色。
本系列文章将手把手教你如何使用 WebGL 实现各种滤镜效果。在第一篇文章中,我们将首先学习如何绘制图片,然后学习如何添加滤镜并动态控制滤镜效果。
1. 绘制图片
要绘制图片,我们需要创建一个纹理对象,并把图片数据加载到纹理对象中。纹理对象可以理解为一张贴图,它存储了图片的数据。
创建纹理对象并加载图片数据的代码如下:
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
// 加载图片数据
const image = new Image();
image.onload = function() {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
};
image.src = 'image.png';
加载好图片数据后,我们需要创建一个顶点缓冲区对象(VBO)和一个索引缓冲区对象(IBO)来存储顶点数据和索引数据。
顶点数据定义了图片的形状,索引数据定义了绘制图片时的顶点顺序。
创建 VBO 和 IBO 的代码如下:
const vertices = new Float32Array([
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
]);
const indices = new Uint16Array([
0, 1, 2,
2, 3, 0,
]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
最后,我们需要编写着色器程序来绘制图片。着色器程序包含了顶点着色器和片段着色器。顶点着色器负责处理顶点数据,片段着色器负责处理片段数据。
顶点着色器的代码如下:
const vertexShader = `
attribute vec3 a_position;
varying vec2 v_texCoord;
void main() {
gl_Position = vec4(a_position, 1.0);
v_texCoord = (a_position + 1.0) * 0.5;
}
`;
片段着色器的代码如下:
const fragmentShader = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 v_texCoord;
void main() {
gl_FragColor = texture2D(u_texture, v_texCoord);
}
`;
有了着色器程序后,就可以绘制图片了。绘制图片的代码如下:
gl.useProgram(program);
// 绑定纹理对象
gl.bindTexture(gl.TEXTURE_2D, texture);
// 绑定顶点缓冲区对象和索引缓冲区对象
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
// 获取顶点着色器中的位置属性
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
// 启用位置属性并指定数据格式
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// 设置uniform变量
const textureUniformLocation = gl.getUniformLocation(program, 'u_texture');
gl.uniform1i(textureUniformLocation, 0); // 纹理单元0
// 绘制图片
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
### 2. 添加滤镜
添加滤镜的原理也很简单,就是在片段着色器中对片段颜色进行修改。例如,我们可以通过以下代码实现灰度滤镜:
void main() {
vec3 color = texture2D(u_texture, v_texCoord).rgb;
float gray = dot(color, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(gray, gray, gray, 1.0);
}
通过修改片段着色器,我们可以实现各种各样的滤镜效果。
### 3. 动态控制滤镜效果
为了让滤镜效果更加灵活,我们可以通过 uniform 变量来动态控制滤镜效果。例如,我们可以通过以下代码动态控制灰度滤镜的强度:
uniform float u_grayScale;
void main() {
vec3 color = texture2D(u_texture, v_texCoord).rgb;
float gray = dot(color, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(mix(color, vec3(gray), u_grayScale), 1.0);
}
通过设置 u_grayScale 的值,我们可以动态控制灰度滤镜的强度。
### 结语
本篇文章介绍了如何在 WebGL 中绘制图片和添加滤镜。通过编写着色器程序,我们可以实现各种各样的滤镜效果,并且可以动态控制滤镜效果。在下一篇文章中,我们将学习如何实现更加复杂的滤镜效果,例如模糊滤镜和浮雕滤镜。
###