This article is the answer to the previous oneOpenGL ES Filter — Split screen filterDid supplement. Added several filter effect: gray scale, inversion, Mosaic, hexagon Mosaic, triangle Mosaic.
1. Gray
There are five ways to achieve grayscale filter:
- Floating-point algorithm :Gray=R0.3 + G0.59 * 0.11 + B
- Integer square method :Gray=(R30+G59+B*11)/100
- Shift square method :Gray =(R76+G151+B*28)>>8;
- Gray=(R+G+B)/3;
- Gray=G;
The most commonly used method is method 1 above. Note that the sum of weights must be equal to 1. Green has the highest proportion, which means that human eyes are most sensitive to green. The darker the green value is, the darker the image color is observed. The implementation principle of method 5 is that when taking an RGB color, only its green value is taken. The code is as follows:
precision highp float; uniform sampler2D Texture; varying vec2 TextureCoordsVarying; // Const highp vec3 W = vec3(0.2125, 0.7154, 0.0721); Vec4 mask = texture2D(Texture, TextureCoordsVarying); void main (void) {// Get the color of the corresponding Texture coordinates. Float luminance = dot(mask.rgb, W); float luminance = dot(mask.rgb, W); / / by vec3 generates a 3 d vector (luminance, luminance, luminance) / / opacity to 1 gl_FragColor = vec4 (vec3 (mask) g), 1.0); }Copy the code
2. The horse
The inversion of the image is relatively easy, just need to flip the texture coordinate y value.
precision highp float; uniform sampler2D Texture; varying vec2 TextureCoordsVarying; Void main (void) {color = texture2D(Texture, vec2(TextureCoordsVarying. X, 1.0-Texturecoordsvarying. gl_FragColor = color; }Copy the code
3. The Mosaic
The Mosaic effect is to represent a sizable area of the picture with the color of the same point. Think of it as massively reducing the resolution of the image and hiding some of the details of the image. The renderings are as follows:We can divide the picture into many small rectangles, and the color value of each rectangle is filled with the color of a point in the rectangle. In this example we take the color value of the top left vertex of the rectangle as the color value of the fill of the small rectangle.
The code and comments are as follows:
precision highp float; uniform sampler2D Texture; varying highp vec2 TextureCoordsVarying; // Const vec2 TexSize = vec2(400.0, 400.0); // Const vec2 MosaicSize = vec2(10.0, 10.0); Void main(){// Texture coordinates multiplied by image size, Vec2 intXY = VEC2 (TextureCoordsVarying. X *TexSize. X, TextureCoordsVarying. Y *TexSize. // Floor (x) returns the maximum integer x less than or equal to x/ / Floor (intxy.x/mosaicsie.x)* mosaicsie.x returns the x value of the vertex of the small rectangle Vec2 XYMosaic = vec2(floor(intxy.x/mosaicsie.x)* mosaicsie.x)* mosaicsie.x, floor(intXY.y/MosaicSize.y)*MosaicSize.y); Vec2 UVMosaic = vec2(XYMosaic. X/texsize. x, XYMosaic. Y/texsize. y); Gl_FragColor = texture2D(Texture, UVMosaic); }Copy the code
4. Hexagonal Mosaic
The same principle of the Mosaic above is the same, but the small rectangle is replaced by a small hexagon. This time we take the color of the center of the hexagon as the filling color of the hexagon.As you can see from the image above, we can still divide the image with rectangles. But the attribution of the middle point of the rectangle, which hexagon it belongs to, needs our judgment. Is the little red dot in the figure below a hexagon D1 or a hexagon D2?Let’s take it one step at a time. First we need to determine the size of the rectangle.
4.1 Determine the rectangle size
From the regular hexagon properties, we can derive the above values. If the sides of a regular hexagon are 1, then the width of the rectangle is 1.5 and the height of the rectangle is √ 3/2, which means that the width and height of the rectangle are 3:√3.
Define the following three variables
Const float mosaicSize = 0.03; Const float TW = 1.5; Const float TH = 0.866025;Copy the code
MosaicSize is the unit length, TW is the multiple of the width of the rectangle relative to the unit length, and TH is the multiple of the height of the rectangle relative to the unit length.
4.2 Determine the position of the rectangle
float x = TextureCoordsVarying.x;
float y = TextureCoordsVarying.y;
int wx = int(x/mosaicSize/TW);
int wy = int(y/mosaicSize/TH);
Copy the code
Wx is the X-axis index of the rectangle, wy is the X-axis index of the rectangle. Then, based on the width and height of the rectangle, the vertex positions of the rectangle can be easily determined.
// top left vec2(float(wx)*mosaicSize*TW, float(wy)*mosaicSize*TH); // Vec2 (float(wx+1)*mosaicSize*TW, float(wy)*mosaicSize*TH); Vec2 (float(wx+1)*mosaicSize*TW, float(wy+1)*mosaicSize*TH); Vec2 (float(wx)*mosaicSize*TW, float(wy+1)*mosaicSize*TH);Copy the code
4.3 Determine the attribution of points
Given the position of the rectangle, we can continue to discuss the question of which hexagon points belong to. In fact, we can also know from the previous picture that the closer a point is to the hexagon, the more it belongs to the hexagon. But there are two other cases that we need to talk about. Should WE compare the distance from v1 to v2, or should we compare the distance from v3 to v2? We need to calculate these two rows separately.We see that when wx+wy is even, it’s case 1, and otherwise, it’s case 2.
vec2 v1, v2, vn; if ((wx + wy)/2 * 2 == (wx + wy)) { v1 = vec2(float(wx)*mosaicSize*TW, float(wy)*mosaicSize*TH); v2 = vec2(float(wx+1)*mosaicSize*TW, float(wy+1)*mosaicSize*TH); } else { v1 = vec2(float(wx+1)*mosaicSize*TW, float(wy)*mosaicSize*TH); v2 = vec2(float(wx)*mosaicSize*TW, float(wy+1)*mosaicSize*TH); } float s1 = SQRT (pow (v1. X - x 2.0) + pow (2.0) v1. - y, y); Float s2 = SQRT (pow(v2.x-x, 2.0) + pow(v2.y-y, 2.0)); float s2 = SQRT (pow(v2.x-x, 2.0) + pow(v2.y-y, 2.0)); if (s1 < s2) { vn = v1; } else { vn = v2; }Copy the code
4.4 Final determination of color
By identifying the points, we can fill the whole hexagon with colors, depending on the color of the vertices.
vec4 color = texture2D(Texture, vn);
gl_FragColor = color;
Copy the code
5. Triangle Mosaic
The triangle Mosaic is evolved on the basis of the hexagonal Mosaic. A hexagon consists of six triangles. Fill the triangle with the colors of the center points of each triangle.
precision highp float; uniform sampler2D Texture; varying highp vec2 TextureCoordsVarying; Const float mosaicSize = 0.03; Const float TW = 1.5; Const float TH = 0.866025; Const float PI6 = 0.523599; void main(){ float x = TextureCoordsVarying.x; float y = TextureCoordsVarying.y; int wx = int(x/mosaicSize/TW); int wy = int(y/mosaicSize/TH); vec2 v1, v2, vn; if ((wx + wy)/2 * 2 == (wx + wy)) { v1 = vec2(float(wx)*mosaicSize*TW, float(wy)*mosaicSize*TH); v2 = vec2(float(wx+1)*mosaicSize*TW, float(wy+1)*mosaicSize*TH); } else { v1 = vec2(float(wx+1)*mosaicSize*TW, float(wy)*mosaicSize*TH); v2 = vec2(float(wx)*mosaicSize*TW, float(wy+1)*mosaicSize*TH); } float s1 = SQRT (pow (v1. X - x 2.0) + pow (2.0) v1. - y, y); Float s2 = SQRT (pow(v2.x-x, 2.0) + pow(v2.y-y, 2.0)); float s2 = SQRT (pow(v2.x-x, 2.0) + pow(v2.y-y, 2.0)); if (s1 < s2) { vn = v1; } else { vn = v2; Float vecx = x-vn.x; float vecx = x-vn.x; float vecx = x-vn.x; float vecx = x-vn.x; float vecx = x-vn.x; float vecx = x-vn.x; float vecy = y-vn.y; float a = atan(vecy,vecx); Vec2 center1 = vec2(vn.x, vn.y - mosaicSize * TH / 2.0); Vec2 center2 = vec2(vn.x + mosaicSize / 2.0, vn.y - mosaicSize * TH / 2.0); Vec2 center3 = vec2(vn.x + mosaicSize / 2.0, vn.y + mosaicSize * TH / 2.0); Vec2 center4 = vec2(vn.x, vn.y + mosaicSize * TH / 2.0); Vec2 center5 = vec2(vn.x - mosaicSize / 2.0, vn.y + mosaicSize * TH / 2.0); Vec2 center6 = vec2(vn. x-mosaicsize / 2.0, vn. y-mosaicsize * TH / 2.0); If (a<PI6* 4.0&&a >=PI6*2.0) {vn = center1; } else if (a<PI6* 2.0&&a >=0.0){vn = center2; } else if (a< 0.0&&a >= -pi6 *2.0) {vn = center3; } else if (a < - PI6 * 2.0 && a > = - PI6 * 4.0) {.vn = center4; } else if (a < - PI6 * 4.0 && a > = - PI6 * 6.0) {.vn = center5; } else if (a<PI6*6.0 &&a >=PI6*4.0) {vn = center6; } vec4 color = texture2D(Texture, vn); gl_FragColor = color; }Copy the code
Float atan(float y, float x) is an arctangent function that returns an Angle whose tangent is y/x. The x and y symbols are used to determine the quadrant of the Angle. This function returns values in the range [0, π]. Float atan(float y/x) is an arctangent function that returns an Angle whose tangent is y/x. The range of values returned by this function is – PI /2, PI /2. You can’t distinguish between quadrants.