Fire shadow recommender serial 6-radial fuzzy introduction

Radial Blur is a kind of radiation from the center to the outside, gradually blurring effect. Therefore, Radial Blur often produces some central divergence effect, and there is also Radial Blur filter effect in PS. Radial Blur is often referred to as Zoom Blur. Radial Blur can bring a good sense of speed to the picture. It is a frequent guest of post-processing in various games. It is also commonly used as the simulation of ray casting (volume light) in post-processing effects such as Sun Shaft.

In the game, radial blur is often used to simulate the dynamic effect of some movements. Such as scene switching special effects in ghost cry 4 and some skill strike special effects; Racing games are also used to simulate dynamic blur, such as wild racing, top speed racing and so on. Radial blur is also one of the technical means to realize volume illumination, as shown in the following figure:

Principle of radial ambiguity

The general principle of blur in graphics is the same: it is to find the color of nearby pixels from around the original pixel to jointly affect the current pixel color. For example, Gaussian blur is to take the weighted sum of the colors of the pixels around the original pixel as the color of the original pixel to achieve the purpose of blur.

Different blur is that the algorithm of taking surrounding pixels and weighted summation is different. Radial blur is characterized by scattering and diffusion from a central point, so the pixels to be sampled come from the connecting line between the current pixel and the central point. The number of samples and the distance of sampling steps can be controlled by parameters. The color of a pixel is sampled on the connecting line between the point of the pixel and the center point, and then the weighted average of the colors of these sampling points is calculated. According to the characteristics of radial blur, the closer to the target point, the denser the sampling points are, and vice versa.

Therefore, the general process of realizing radial ambiguity is as follows:

  • Determine the center point of radial blur, which is generally the center point of canvas or the position of the center point of an object in the screen projection. (note that the center point is a two-dimensional coordinate)
  • Calculate the distance and vector line segment between the current pixel and the center point.
  • Sample and weight on the line segment.
  • Perform a superposition synthesis between the blurred result and the original image (may be required)

Realization of radial fuzzy by web GL

Radial blur is a post-processing process. Radial blur can apply effects to static images or dynamically rendered images. In this example, effects are applied to dynamic images. Let's see the effect from the previous picture:

Firstly, several ring objects are drawn, and then radial blur is applied to the drawn image.

Render to texture

To apply radial blur, first draw the ring on the texture object. We know that the drawing effect can be output to the mapped object through the framebuffer technology.
The technology of framebuffer is not the key content of this article. If readers are not familiar with it, they can find relevant materials by themselves. You can also refer to: Render to texture.

Input map object

To output the mapped object to the screen, we need to construct a rectangular object, which is exactly four vertices in the webgl coordinate system. The code is as follows:

function quad() {
  var pos = [-1,1,0, -1,-1,0, 1,-1,0, 1,1,0],
    st = [0,1,0,0,1,0, 1,1],
    idx = [0,1,2,0,2,3];

  return {
    p:pos,
    t:st,
    i:idx,
  }
}

The above objects can output exactly one mapping object to the screen (webgl coordinate system)

Radial blur

Radial blur is mainly implemented in Shader Language, and mainly in slice shader. The following is the code of slice shader:

var ofs = `precision mediump float;
uniform sampler2D texture;
uniform float strength;
varying vec2 vTexCoord;

const float tFrag = 1.0 / 512.0;
const float nFrag = 1.0 / 30.0;
const vec2 centerOffset =www.tyyleapp.com vec2(256.0, 256.0);

float rnd(vec3 scale, www.lafei6d.cn float seed) {
  return fract(sin(dot(gl_FragCoord.stp + seed, scale)) * 43758.5453 + seed);
}

vec4 fragRadialBlur(){
  vec2 fc =www.xingchenylzc.cn vec2(gl_FragCoord.s, 512.0 - gl_FragCoord.t);
  vec2 fcc =www.yifayuled.cn fc -www.fudayulpt.cn      centerOffset;
  vec3 destColor www.pinguo2yl.com= vec3(0.0);
  float random =www.jinmazx.cn  rnd(vec3(12.9898, 78.233, 151.7182), 0.0);
  float totalWeight = 0.0;
  for (float www.qilzixyouyi.com = 0.0; i <= 30.0; i++) {
    float percent =www.lecaixuangj.cn (i + random) * nFrag;
    float weight = percent - percent * percent;
    vec2 t www.hongtuuzhuc.cn= fc - fcc * percent * strength * nFrag;
    destColor += texture2D(texture, t * tFrag).rgb * weight;
    totalWeight += weight;
  }
  return vec4(destColor / totalWeight, 1.0);
}

void main(void) {
  gl_FragColor =  fragRadialBlur();
  
}`;

Random function

Firstly, a rnd function is declared. This function is a simple random number generator. When the directional quantity and seed value are given, it will return the random number in the range of 0 to 1.
The purpose of using random numbers is to make the effect of fuzziness present a certain random state, rather than fuzziness according to a certain consistency principle.
rnd is called in every slice shader, so try to use a lightweight implementation, otherwise it may cause performance load.

Define related variables

const float tFrag = 1.0 / 512.0;
const float nFrag = 1.0 / 30.0;
const vec2  centerOffset = vec2(256.0, 256.0);

Then define the relevant variables. In this example, the center point of the zoom is set to the center of the canvas.
The size of the canvas is 512 pixels, so the above code declares some constants accordingly.
The vec2 variable centerOffset is used to define the center position.
The float variable tFrag is used for normalization, converting the two-dimensional vertex coordinates into normalized uv coordinates to correctly reference the texture pixels in the shader.
Another float type constant nFrag is used for iterative processing and normalization of the for statement in the shader.

Radial fuzzy logic

vec4 fragRadialBlur(){
  vec2 fc = vec2(gl_FragCoord.s, 512.0 - gl_FragCoord.t);
  vec2 fcc = fc - centerOffset;
  vec3 destColor = vec3(0.0);
  float random = rnd(vec3(12.9898, 78.233, 151.7182), 0.0);
  float totalWeight = 0.0;
  for (float i = 0.0; i <= 30.0; i++) {
    float percent = (i + random) * nFrag;
    float weight = percent - percent * percent;
    vec2 t = fc - fcc * percent * strength * nFrag;
    destColor += texture2D(texture, t * tFrag).rgb * weight;
    totalWeight += weight;
  }
  return vec4(destColor / totalWeight, 1.0);
}

First, through gl_FragCoord calculates the variable fc, which represents the coordinates of the current pixel on the canvas. Attention GL_ The origin of the fragcoord coordinate is in the lower left corner, while the origin of the canvas coordinate is in the upper left corner. A flip calculation is made according to this:

512.0 - gl_FragCoord.t

Calculate the variable fcc, which represents the vector from the current coordinate to the center point.

The definition variable destColor is used to save the final pixel color to be output. Then calculate a random value random. totalWeight represents the sum of the proportion of sampled pixels in each iteration.

Then start iterative processing.

In the fragment shader, iterate through the for statement, use the sum of i and random numbers to calculate the percentage of the target pixel, and then use percent - percent * percent to turn the linear specific gravity data into nonlinear specific gravity.
Then a sampled coordinate point t is calculated through percent and strength, where strength represents the intensity of radial blur. The greater this value is, the greater the deviation is, and the stronger the blur effect is. The color value of the corresponding coordinate point is obtained through the texture2D function, then multiplied by weight and added to destColor, and finally calculate totalWeight.

Finally, after completing the iterative process, normalize destColor: destColor / totalWeight.

explain

We used 30 iterations here, and it doesn't seem to have much impact on performance. In the actual process, different iteration times can be selected to achieve the balance of effect and performance.

The final effect is as follows:,

This article is also published in my webgl column. The complete code can be obtained in the column:

https://xiaozhuanlan.com/topic/6480975213

The next article describes the effect of using radial blur to realize volume light. First, see the effect in the previous figure:

Posted by BenMo on Fri, 20 May 2022 10:23:05 +0300