OpenGL/OpenGL ES introduction: Graphics API and professional term parsing OpenGL/OpenGL ES introduction: Rendering process and fixed storage shader OpenGL/OpenGL ES introduction: Image rendering implementation and rendering problems OpenGL/OpenGL ES introduction: basic transformation – beginning vector/matrix OpenGL/OpenGL ES introduction: texture exploration – common API parsing OpenGL/OpenGL ES introduction: OpenGL/OpenGL ES: Vertex shaders and slice shaders (OpenGL transition OpenGL ES) OpenGL/OpenGL ES 介 绍 : Using OpenGL/OpenGL ES to render images IOS Texture flip strategy parsing OpenGL ES introduction: Rendering pyramid – Color, texture, texture and color blending fill and GLKit implementation OpenGL ES Introduction: Filter – split screen filter OpenGL ES introduction: Filter – vortex, Mosaic
Relative to the last OpenGL ES entry: Filter – vortex, Mosaic filter, the implementation of the filter in this article is much simpler, because there is no so much to calculate, and the effect is also a bit more cool, into the topic.
Scaling filter
Effect:
Vertex shader code:
// Attribute vec4 Position; // Attribute vec2 TextureCoords; TextureCoordsVarying; // Texture coordinates varying VEC2 TextureCoordsVarying; // Time pinch (timely update) uniformfloat Time;
const floatPI = 3.1415926; Void main (void) {// One zoom lasts 0.6floatDuration = 0.6; // Maximum zoomfloatMaxAmplitude = 0.3; // Indicates the time period. Range (0.0 ~ 0.6),floattime = mod(Time, duration); / / amplitude [1.0, 1.3]floatAmplitude = 1.0 + maxAmplitude * abs(sin(time * (PI/duration))); Gl_Position = vec4(position. x * amplitude, position. y * amplitude, position.zw); gl_Position = vec4(position. x * amplitude, position. y * amplitude, position.zw); TextureCoordsVarying = TextureCoords; }Copy the code
The filters in the previous two articles were implemented using custom slice shaders, whereas here we use vertex shaders. The principle of implementation is through the mapping between vertex coordinates and texture coordinates.
In the above code, we pass a uniform Time to change the magnification factor.
Out-of-body filter
Effect:
Fragment shader code:
precision highp float; Uniform sampler2D Texture; TextureCoordsVarying; // Texture coordinates varying VEC2 TextureCoordsVarying; // time group uniformfloatTime; Void main (void) {// The duration of an out-of-body effect is 0.7floatDuration = 0.7; // Transparency capfloatMaxAlpha = 0.4; // Enlarge the image limitfloatMaxScale = 1.8; // progress value [0,1]floatprogress = mod(Time, duration) / duration; // 0~1 // transparency [0,0.4]floatAlpha = maxAlpha * (1.0 - progress); // Zoom ratio [1.0,1.8]floatScale = 1.0 + (maxscale-1.0) * progress; Enlarge / / / / texture coordinates according to the zoom ratio, magnified texture coordinates (0, 0), [0, 1], [1, 1], [1, 0]floatWeakX = 0.5 + (TextureCoordsVarying. X-0.5)/scale;floatWeakY = 0.5 + (TextureCoordsVarying. Y-0.5)/scale; WeakTextureCoords = vec2(weakX, weakY); Vec4 weakMask = texture2D(Texture, weakTextureCoords); Vec4 mask = texture2D(Texture, TextureCoordsVarying); // The Texture of vec4 mask = texture2D(Texture, TextureCoordsVarying); // Default color blending equation = mask * (1.0-alpha) + weakMask * alpha; Gl_FragColor = mask * (1.0-alpha) + weakMask * alpha; }Copy the code
Analysis: The out-of-body effect is achieved by superimposing two layers, the lower layer shows the original image, and the upper layer will gradually enlarge and reduce the opacity as time goes by, using the zoom filter effect above. This is done using a chip shader.
Jitter filter
Effect:
Fragment shader code:
precision highp float; Uniform sampler2D Texture; TextureCoordsVarying; // Texture coordinates varying VEC2 TextureCoordsVarying; // time group uniformfloatTime; Void main (void) {// The length of a jitter filter is 0.7floatDuration = 0.7; // Enlarge the image limitfloatMaxScale = 1.1; // Color deviation step sizefloatOffset = 0.02; / / progress [0, 1]floatprogress = mod(Time, duration) / duration; // 0~1 // Color offset value range [0,0.02] vec2 offset = VEC2 (offset, offset) * progress; // Zoom range [1.0-1.1];floatScale = 1.0 + (maxscale-1.0) * progress; Vec2 ScaleTextureCoords = VEC2 (0.5, 0.5) + (TextureCoordsVarying - VEC2 (0.5, 0.5))/scale; vec2 ScaleTextureCoords = VEC2 (0.5, 0.5) + (TextureCoordsVarying - VEC2 (0.5, 0.5))/scale; Texture2D (Texture, ScaleTextureCoords +offsetCoords); MaskB = texture2D(Texture, ScaleTextureCoords -offsetCoords); Vec4 mask = texture2D(Texture, ScaleTextureCoords); R,mask.g, maskb. b Note that these 3 color values can be scrambled or arbitrarily used. Not necessarily dead. but the effect will be different. Gl_FragColor = vec4(maskr.r, mask.g, maskb.b, mask.a); }Copy the code
The implementation principle is simple: color offset + weak amplification
Flash of white filter
Effect:
Fragment shader code:
precision highp float; Uniform sampler2D Texture; TextureCoordsVarying; // Texture coordinates varying VEC2 TextureCoordsVarying; // time group uniformfloatTime; Void main (void) {// The length of a flash filter is 0.6floatDuration = 0.6; // indicates the time period [0.0,0.6]floattime = mod(Time, duration); Vec4 whiteMask = vec4(1.0, 1.0, 1.0, 1.0); // Amplitude: (0.0,1.0)floatamplitude = abs(sin(time * (PI / duration))); Vec4 mask = texture2D(Texture, TextureCoordsVarying); // use the mixture equation; Gl_FragColor = mask * (1.0-amplitude) + whiteMask * amplitude; }Copy the code
How it works: Add a white layer, and the opacity of the white layer changes over time
Burr filter
Effect:
Fragment shader code:
precision highp float; Uniform sampler2D Texture; TextureCoordsVarying; // Texture coordinates varying VEC2 TextureCoordsVarying; // time group uniformfloatTime; / / random numberfloat rand(floatN) {//fract(x), returns the decimal part of xreturnFract (sin (n) * 43758.5453123); } void main (void) {// Maximum jitterfloatMaxJitter = 0.06; // The length of a burr filterfloatDuration = 0.3; // Red color offsetfloatColorROffset = 0.01; // The green color offsetfloatColorBOffset = 0.025; // Time cycle [0.0,0.6];floatTime = mod(time, duration * 2.0); / / amplitude: [0, 1];floatAmplitude = Max (sin(time * (PI/duration)), 0.0); // Random pixel offset [-1,1]floatJitter = rand(TextureCoordsVarying. Y) * 2.0-1.0; Bool needOffset = abs(jitter) < maxJitter * amplitude; // Get the texture X value. // needOffset = YES, needOffset = YES; // needOffset = NO.floattextureX = TextureCoordsVarying.x + (needOffset ? Jitter: (jitter * amplitude * 0.006)); Vec2 textureCoords = VEC2 (textureX, TextureCoordsVarying. Y); Vec4 mask = texture2D(Texture, textureCoords); Vec4 maskR = texture2D(Texture, textureCoords + vec2(colorROffset * amplitude, 0.0)); Vec4 maskB = texture2D(Texture, textureCoords + vec2(colorBOffset * amplitude, 0.0)); Gl_FragColor = VEC4 (maskr.r, mask.g, maskb.b, mask.a); }Copy the code
Analysis: Let each row/column pixel randomly offset -1 ~ 1 distance, set a threshold value here, reproduction of the whole picture offset, resulting in the original image can not be seen, offset when the offset is less than this threshold value, then multiply a reduction factor. The final rendering is as shown in the above illustration.
These filters are relatively simple, you can control the above effect by uniform transmission of values, interested partners can try by themselves