[Unity Shader] Special Effects (3) Shiny Shiny (UI)

Updated: September 2, 2021.
Github source code: [Click me to get the source code]

shiny

Shiny implements LOGO streamer in another way , which is almost the same in terms of performance. The difference is that Shiny does not need to specify streamer masks and flowing image textures. It directly calculates an area through UV, and then superimposes colors , in order to achieve a shiny effect, the final rendering:
insert image description here

Idea analysis

First of all, according to the idea of ​​LOGO streamer, we only need to select a uv area, superimpose color for the area, and make 区域的中心越亮, more and more 区域的两边扩散越暗, without considering the animation, this is the area shining effect we want.

Because we want to give people a feeling of passing by, so we 闪亮区域must be up and down (moving left and right) or left and right (moving up and down), as in the final rendering above, the shiny area is up and down, Move left and right to achieve a flashing effect.

shiny area

Let's first consider the way of connecting up and down. In our vision, our shiny area is as follows:
insert image description here

We will 闪亮的值imagine that 0-1the center of the area is 1 (the brightest), and the more it spreads to the two sides, the closer it is to 0 (the darkest): According to experience, it is
insert image description here
obvious that we can use the abscissa of uv to convert to 闪亮的值, known uv The range of abscissa values ​​is as follows:
insert image description here

Then our algorithm is clear, that is, to [0,1](也即是uv.x的取值范围)map intervals to intervals [0,1,0]!

First, intervals [0,1]can be further abstracted into intervals [0,0.5,1], and then, first [0,0.5,1]map intervals to intervals [-1,0,1]:

	//将区间[0,0.5,1],映射到区间[-1,0,1]
	half value1 = uv.x * 2 - 1;

Then [-1,0,1]map the interval to the interval by taking the absolute value [1,0,1]:

	//将区间[0,0.5,1],映射到区间[-1,0,1]
	half value1 = uv.x * 2 - 1;
	//将区间[-1,0,1],映射到区间[1,0,1]
	half value2 = abs(value1);

Finally, [1,0,1]invert the interval to get our desired result, the interval [0,1,0]:

	//将区间[0,0.5,1],映射到区间[-1,0,1]
	half value1 = uv.x * 2 - 1;
	//将区间[-1,0,1],映射到区间[1,0,1]
	half value2 = abs(value1);
	//倒置区间[1,0,1],得到区间[0,1,0]
	half value3 = 1 - value2;

At this point, the obtained value value3is returned according to the current input uv.x value. 闪亮的值The range of this value is, [0,1,0]the middle is bright, and the two sides are dark.

softness

value3 [0,1,0]We can smooth the values ​​as follows to get powerour final shiny intensity:

	//通过smoothstep将区间[0,1,0]平滑,得到闪亮强度power
	half power = smoothstep(0, softness, value3);

Here softnessis the value of the external input, we named it 柔和度, why can the softness achieve a smooth effect? Let's look at the picture and analyze it.

First, when the softness is the lowest (0.01 here), the effect is 完全不柔和:

insert image description here
Let's analyze the formula and bring the softness 0.01 into:

	//通过smoothstep将区间[0,1,0]平滑,得到闪亮强度power
	half power = smoothstep(0, 0.01, value3);

According to smoothstepthe characteristics of the method, as long as the input value3value is greater than 0.01, it will return 1, given power, that is to say, after a round of smoothing operations, our original value3interval:

	//扩大区间细节
	[0,0.1,0.2,...0.9,1,0.9...0.2,0.1,0]

is converted to poweran interval:

	//扩大区间细节
	[0,1,1,...1,1,1...1,1,0]

That is to say, the extremely low softness makes all 稍微有一点亮度places become soft 亮度为1, which is the embodiment of softness.

Conversely, when the softness is the highest (1 here), the smoothing operation will return to value3the original value, which itself is an interval with a smoothing effect:
insert image description here

Gloss

From the above, we have obtained the shiny brightness value power. We multiply the brightness value by one 颜色to get our final shiny color. Here, we introduce a control parameter again 光泽度, and use it to control our output color value :

	//通过光泽度插值得到闪光颜色shinyColor
	half3 shinyColor = lerp(fixed3(1, 1, 1), color.rgb, gloss);
	//输出最终颜色(原始颜色 + 闪亮颜色)
	color.rgb += shinyColor * power;

The glossiness here is interpolated glossbetween 纯白色and 本身颜色, when the glossiness is 0, the shiny color is white (the values ​​of the three channels are equal, powerand some values ​​will be reduced after multiplication), RGBafter the three channels of any color are accumulated with the same value, and It will not change it 色相, that is to say, whether it should be red or red , should it be blue or blue , it just looks a little brighter overall, without gloss:
insert image description here
when the glossiness is 1, the shiny color is itself Color, its own color is added to its own color, which makes the red place redder , and the blue place bluer , very shiny:
insert image description here

to rotate

According to the above calculation, what we get is only a vertical one that runs through up and down 闪亮区域. We want to rotate it arbitrarily, for example, as follows: this
insert image description here
:
insert image description here
this:
insert image description here
how to achieve such an effect?

Let's recall the algorithm for obtaining the shiny area at the beginning: input a uv coordinate, and obtain the coordinate point according to the x value of the uv coordinate 闪亮颜色强度.

We want to achieve the rotation effect, and then input the uv coordinates directly 旋转, the output is not the real coordinate point of the uv coordinates 闪亮颜色强度!

So the algorithm is very simple, just do it, just turn uv:

//uv旋转
uv = RotatePoint2(uv, float2(0.5, 0.5), radians(_Rotation));

The function of RotatePoint2 is to rotate the input two-dimensional point along a specified arc along a circle center:

//将二维顶点point2,沿着圆心center,顺时针旋转radian弧度
float2 RotatePoint2(float2 point2, float2 center, half radian)
{
    
    
	half radius = distance(point2, center);
	half angle = atan((point2.y - center.y) / (point2.x - center.x)) - radian;
	point2.x = cos(angle) * radius + center.x;
	point2.y = sin(angle) * radius + center.y;
	return point2;
}

The algorithm is also a trigonometric function, so I won't explain it in detail here.

shiny animation

To achieve shiny animation, we only need to change _Positionthe value of the input, without using _Timeparameters, directly add an animation player:

insert image description here

At this point, this simple shiny effect is basically over. If there is still something you don’t understand, you can refer to the source code. Of course, the code in the blog may not be exactly the same as the source code. The original intention here is just to introduce ideas. In the specific implementation process There may be some statement optimization, of course the core algorithm is the same.

Guess you like

Origin blog.csdn.net/qq992817263/article/details/120066411