CyberLens

A scanline shader experiment celebrate the release of Cyberpunk 2077

This shader use sin and fraction on the world space Y position to produce a repeating set of scanline. It also add on with transparency, additive blending, HDR colour tint and a Fresnel effect. I added distortion and glitching effects to make it more interesting when applied to quads.

  • This is an Unlit shader, using Transparent surface mode and Additive blending.

  • Distortion and glitch effects only really look good for textured quads. Similar effects in 3D can be done by offsetting vertices (like the waterball in SummerTime).

  • 在世界空间Y位置上使用正弦函数和分数函数来生成重复的扫描线。

  • 我又额外添加了失真和撕裂效果,可以应用于四边形的面片。 如果想在3D中也实现类似效果,需要进一步偏移顶点。

  • HDR颜色和菲涅耳效果。

  • 这是一个不发光的着色器,使用透明表面模式和添加混合。

Breakdown 步骤详解

Scanning line 扫描线

This shader is baased on the combination of two scanning line effects.

First, I use Position node to obtain the World position of fragment. Then, Split the Position, take the Y coord and multiply by a vertical scaling value for scanning lines. Use a Sine node to return values between -1 and 1. Clamp the values in Saturate node, so the result comes out between 0 and 1. The scaling value control the numer of lines.

For animation, I use the Time output Multiply a value to control the scroll speed. Add it with the G from Split note to create offset.

扫描线的效果由两部分效果组合而成。

第一部分效果使用时间和片元的Y坐标输入正弦节点产生均匀滚动的线条。

首先,获取片元的世界坐标。然后,拆分世界坐标以取Y坐标,并获取时间码,乘以一个可控制变量控制范围,与之相加。给得到的结果乘以可控制变量,此处设定为70. 这个变量可以控制扫描线的行数。将结果输入正弦节点,返回-1和1之间的值,并在饱和节点中,将结果限制在0和1之间。

Then, an alternative way to make scanning lines effect is to use the Fraction. This produces a sawtooth wave with harsh transitions between the lines.

Last, I combine the above two together.

Here I am not setting the scroll speed and vertical scaling at first by adding a Multiply at value 1, so I can adjust them later. When using the same value to scale the Sine and Fraction nodes they output different number of lines. We could multiply by 2*Pi before putting a value into the Sine node to ensure the scaling is the same for both, but this isn’t too important).

另一部效果使用``分数''产生锯齿波。将第一部分的正弦节点换成保留输入值小数部分的取小数节点,并使用指数节点调整范围。

完成后,将两部分相加效果。 此时,两部分输出的行数不同。因为第一个函数中Sin函数的周期为2Pi。所以我将Sin函数的输入值先乘以2*Pi,这样两者的缩放比例就会比较协调了。

I’m also going to put the output of that Fraction node into a Power node with a value of 2 to make it less linear and then take the output of this and the Sine node from before and Add them together.

Before we add some colour, we can also apply a rim or fresnel effect which improves the hologram effect for 3D objects. Create a Fresnel Effect node and Add its output with our current result.

A good way of applying colour is by using a texture and colour to tint it. By using this combination we can use a black & white mask texture to get a specific shape, and then colour it using the tint colour, or just leave the tint colour as white and display a texture normally.

To do this Multiply the output from the previous Add node with the RGBA output from a Sample Texture 2D node. We’ll then take the output of that and Multiply again by a Color property (use the blackboard in the top left to create this, or create a Color node, right-click and Convert To Property). I’m using a colour property with HDR mode and an Intensity of 2 along with some post processing Bloom to make the effect ‘glow’ more.

Finally put the output of that into the Color input on the Master node and click the cog to change it to Transparent and use Additive blending if you haven’t done so already.

我还将把该分数节点的输出放到值为2的Power节点,以使其线性度降低,然后将其和正弦节点的输出从之前合并到一起。 在添加颜色之前,我们还可以应用边缘或菲涅耳效果,以改善3D对象的全息效果。创建一个``菲涅耳效果''节点并将其输出与我们当前的结果相加。 施加颜色的一种好方法是使用纹理和颜色对其进行着色。通过使用这种组合,我们可以使用黑白蒙版纹理来获得特定的形状,然后使用色调颜色对其进行着色,或者仅将色调颜色保留为白色并正常显示纹理。 为此,将上一个Add节点的输出与Sample Texture 2D节点的RGBA输出相乘。然后,我们将其输出并再次乘以Color属性(使用左上角的黑板来创建它,或者创建一个Color节点,右键单击并转换为属性)。我正在使用具有HDR模式和2强度的颜色属性以及一些后期处理Bloom,以使效果更加``发光''。 最后,将其输出放入主节点上的``颜色''输入中,然后单击齿轮将其更改为``透明'',如果尚未使用,请使用添加混合。

Distortion 扭曲效果

To improve the effect I added a horizontal distortion effect to the texture sampling. This is fairly simple to do, we just need to offset the UV coordinates going into the Sample Texture 2D node. (Note, this will only work when applying the shader to a quad. If you want a 3D object distortion approach you would need to manipulate vertex positions instead, or possibly use a post-processing based distortion effect (similar to heat distortion?), both of which I’m not going into in this post).

In order to create our horizontal distortion we first need to create a UV node and Split it. We can then use the Y/G output in order to create some noise which we will use to offset the X/R output. Since we’re basing the noise off this vertical Y/G value pixels going horizontally won’t change, which is what we need in order to offset that entire line of the texture uniformly. To help adjust our distortion we’ll also use a few Vector1 properties along the way. (To create these use the plus button on the shadergraph blackboard or create a Vector1 node, right-click, and select Convert To Property. To rename it, right-click the property in the blackboard).

First we’ll Multiply the Y/G output with a Vector1 property named Distortion Scale, then put this into the first input on an Add node. Create a Time node and Multiply the Time output with another Vector1 property, named Distortion Scroll Speed. Then put that into the second input in that Add node from a second ago.

We’ll then put the output from that Add node into a Gradient Noise node, using 10 as the noise Scale input. (For a less wobbly distortion, we could instead use a Random Range node to generate random noise, with a Multiply and Floor node before it to control the height of each line).

Since this noise returns a value between 0 and 1 we will Subtract 0.5, so our distortion will be centered. Then Multiply by 0.1, and Multiply again by a Vector1 property named Distortion Strength. (Note that I’m just multiplying by 0.1 so that our strength value is more reasonable, as without it, a value of 1 would distort the texture by a maximum of half of itself (since our noise is between -0.5 and 0.5), which is quite a lot of distortion).

扭曲效果依靠纹理采样时偏移UV坐标。 首先,创建一个UV节点并将其拆分。使用Y坐标输出创造一些噪声,并用时间值与之相加,产生动画。将得到的结果与X坐标相加,偏移X输出。这样,就可以整体均匀的创造偏移效果了。然后,为每个主要的节点添加控制变量调整扭曲效果。在创造噪音的阶段,将一个变量与Y轴坐标相乘,用以调整噪音的幅度;将一个变量与时间输出相乘,用以调节动画循环的速度。同样,为得到的噪音节点添加与之相乘的变量以调节噪音的每条线的高度。噪声返回的值介于0和1之间,因此我们将减去0.5,将效果居中。最后,将得到的结果将作为X值输入UV坐标。

Glitching 撕裂效果

Another effect we could add is a glitching effect, as seen in the tweet above. (Again note, this will only work when applying the shader to a quad).

We first need to create a UV node and Split it. (If you did the distortion effect above you can use the split from that one instead).

We’ll be offsetting our Y/G output, but rather than making it scroll downwards I want the glitching effect to be more static (not moving), but still animated so that it changes over time. If we put the Time output from a Time node into a Multiply and then into a Floor node it will keep the same value until it increases past the next integer value (which is each second, since the time output is measured in seconds). By changing the value in the Multiply we can scale this, so it reaches the next integer slower or faster.

We’ll take the output of our Floor node and the Y/G output from our Split and Add them together. I’m then going to Multiply it by 10 and put the output into a Random Range node to generate random values between a Min and Max value of -1 and 1.

These random values will be how much offset to apply, before we use this though it would be useful to control the glitching more. We can probably do this in a number of ways, but I put the random output into an Absolute node, and then into the Edge input on a Step node. (Returns the absolute value so everything is in the positive range, above 0. So values like -0.5 become 0.5 instead. The step then returns 1 if the In input is greater than or equal to the edge input, otherwise it returns 0).

We’ll put a Glitch Amount Vector1 property into the second input of the Step node to control the amount of glitching that will get past the step. (A value of 0 will allow no glitching through, 0.5 half of it, while 1 will allow all of it). We can then Multiply our random input by this step output, Multiply by 0.1 and Multiply again by Glitch Strength Vector1 property to control the strength of our glitching effect.

我们可以添加的另一个效果是毛刺效果,如上面的推文所示。 (再次注意,这仅在将着色器应用于四边形时有效)。   我们首先需要创建一个UV节点并将其拆分。 (如果您进行了上面的失真效果,则可以改用该拆分的效果)。  我们将抵消我们的Y / G输出,但我不想让其向下滚动,而是希望毛刺效果更加静态(不移动),但仍要使其具有动画效果,以便随时间变化。如果我们将时间节点的时间输出放到乘数然后放到地板节点中,它将保持相同的值,直到它增加到下一个整数值为止(每秒,因为以秒为单位测量时间)。通过更改乘数中的值,我们可以缩放此值,以便它更快或更慢地到达下一个整数。  我们将合并节点的输出以及拆分和添加的Y / G输出。然后我将其乘以10并将输出放入``随机范围''节点以生成介于-1到1的最小值和最大值之间的随机值。  这些随机值将是要应用的偏移量,在我们使用它之前,尽管它对于控制更多的毛刺很有用。我们可能可以通过多种方式来做到这一点,但是我将随机输出放入一个Absolute节点,然后放入Step节点的Edge输入。 (返回绝对值,以便所有值都在正范围内,大于0。因此,-0.5之类的值改为0.5。如果In输入大于或等于边沿输入,则该步骤返回1,否则返回0)。  我们将一个``毛刺量向量1''属性放入``步骤''节点的第二个输入中,以控制超过该步骤的毛刺量。 (值为0将不允许出现故障,值为0.5的一半,而值为1将允许所有故障)。然后,我们可以将随机输入与此步输出相乘,再乘以0.1,再将其与``毛刺强度矢量1''属性再次相乘,以控制我们的毛刺效果的强度。

Add the output with the X/R output, from the Split earlier, (or with the Add output from the previous distortion effect if you did that. Note the image above does not include this). Then put this into the X input on a Vector2 node and put the Y/G output into the Y input. The image above shows how I’ve arranged all of this.

The output of that Vector2 node can then be put into the UV input on the Sample Texture 2D node from earlier. You may also want to switch this out for a Sample Texture 2D LOD node with a LOD value of 0 as you might see some unintentional glitchy parts between the lines, (unless you think this adds to the glitch effect I guess).

We can also make the glitching change the colour of the effect. You could use a Hue node to offset the colour, but I found this gave too much variation. Instead, I took the Multiply output (the one including the Random Range and Step inputs). Since this is between -1 and 1 we can colour the positive offsets and negative offsets differently. I simply use a Saturate node to clamp values between 0 and 1 and then Multiply by a red Color property, and do this again but with a Negate node and green Color property. I then Add these two outputs together, as seen in the image below.

从先前的分割中添加带有X / R输出的输出(如果这样做的话,还可以添加来自先前失真效果的输出。请注意,上面的图像不包括此输出)。然后将其放入Vector2节点的X输入中,并将Y / G输出放入Y输入中。上图显示了我如何安排所有这些。  然后可以将Vector2节点的输出从更早的时候放到Sample Texture 2D节点的UV输入中。您可能还希望将其切换为LOD值为0的``样本纹理2D LOD''节点,因为您可能会在行之间看到一些意外的毛刺部分(除非您认为这会增加我猜到的毛刺效果)。  我们还可以使小故障改变效果的颜色。您可以使用``色相''节点来抵消颜色,但是我发现这产生了太多变化。相反,我采用了乘积输出(包括随机范围和阶跃输入的输出)。由于它介于-1和1之间,因此我们可以对正偏移量和负偏移量进行不同的着色。我只需使用一个饱和节点将值限制在0到1之间,然后乘以一个红色的Color属性,然后再次执行此操作,但要使用一个否定节点和绿色的Color属性。然后我将这两个输出加在一起,如下图所示。

We can then Add this to our previous colour that went into the Master node, but before the Sample Texture 2D LOD node to ensure it is masked correctly. You may need to rearrange the nodes a little, but it should look something like below.

然后,我们可以将此颜色添加到进入“主”节点但在“采样纹理2D LOD”节点之前的先前颜色中,以确保正确遮罩该颜色。您可能需要稍微重新排列节点,但是看起来应该如下图所示。

Thanks for reading!

感谢阅读!

Previous
Previous

MANA Bottle

Next
Next

AR Filters