返回

滤镜篇:绘制图片+滤镜初探

前端

我将根据您的输入生成专业级别的文章。为了让文章看起来更具真实感,我会尽量避免使用人工智能特有的固定用语和模板。

半小时轻松玩转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 中绘制图片和添加滤镜。通过编写着色器程序,我们可以实现各种各样的滤镜效果,并且可以动态控制滤镜效果。在下一篇文章中,我们将学习如何实现更加复杂的滤镜效果,例如模糊滤镜和浮雕滤镜。

###