Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
ā Live Streamingā Interactive Chatā Private Showsā HD Qualityā Free Actions
Free to watch ⢠No registration required ⢠HD streaming
A flaming torch inspired by Edward del Villar's tweet: https://t.co/a2huD7T5GR and Simon Trümpler's talk about VFX in Rime: https://www.youtube.com/watch?v=lAYIF0lwy60
Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
ā Live Streamingā Interactive Chatā Private Showsā HD Qualityā Free Actions
Free to watch ⢠No registration required ⢠HD streaming
Introduction: This is a step-by-step breakdown of one of our characterās projectile impacts, shown below. The focus lies predominantly on the actual shader construction, which is a prerequisite component for the complete, more elaborate effect. When attempting to recreate anything shown here, try to experiment with changing these variables and observe the effects of said changes ā it can be very beneficial to the learning process.
Difficulty: Advanced
Subjects: Alpha Masks, Blending, Sheet Animation, UV Manipulation (Rotation, Flowmaps)
Prerequisites: Elementary understanding of Shader Forge (or similar node-based shader editors) and its terminology. Many elements build upon the previous breakdowns, so it is highly recommended to (re)visit these before attempting to follow this particular breakdown.Ā Ā Ā Ā
1.) The Cloud
This effect consists of a gas-like cloud and splitting bacteria within it. First we will construct the gas, which should be a straightforward process if familiar with the Eileen and Sneglii Projectile Breakdowns. We have two textures with their alpha channels properly set up and simply combine them through a Blend Node. A multiplication would also work, but a Hard Light blend gives the images a little more contrast. Experiment with different blend modes to discover different results. Also, donāt forget to add either textureās alpha outputs to one another.
Next up is once again adding flowmap distortion to the UVs of these two textures. The setup below should look familiar by now, but there are some slight alterations in comparison to the setups weāve seen earlier. Weāve added UV rotation to the actual flowmap itself and adjusted the time-driven sine by remapping its values.
When fed to the textures, this creates a sort of pulsating effect. As this exact same flowmap texture is used for the Eileen Projectile, this is a good example to showcase how you can have drastically different results with the same flowmap depending on the processes it is subjected to.
2.) The Bacteria
Now, itās time to add the dividing bacteria by way of an animation sheet. For those who are unfamiliar with the concept, an animation sheet is a single texture that holds multiple animation frames. The individual frames are laid out in a grid, which consists of vertical columns (Y) and horizontal rows (X).
We have the right asset, but now we need to build a system to allow the shader to understands how to read this particular texture. A good way to go about this is to compile a list of parameters you suspect the system will need in order to properly process an animation sheet.Ā
> Total number of animation cells
Ā > Number of rows
Ā Ā > Number of cells per row
Ā > Number of columns
Ā Ā > Number of cells per column
> Read only a single cell at a time
> Read order:
Ā Ā 1. Start top-left
Ā Ā 2. Move right across the row
Ā Ā 3. At the end of row, move down to the next row and start in the first column
Ā Ā 4. Repeat 1. through 3.
Ā Ā 5. When at the last column of the last row, return to 1.
We will now jump ahead to the finished system and the results it produces, and then work backwards to demonstrate how exactly it works. It may seem complicated at first glance, but the network mainly consists of simple calculus operations.
The main input source of the system is the very versatile Vector 4 Node. Weāll be using this node to feed the system information about the grid weāve established before: X for the rows and Y for the columns, which in this case are both 5. We can use the surplus property Z to dictate the speed of the animation, which for now weāll keep at 1.
From here weāll move on to the Time Node, which should be familiar to those whoāve seen previous breakdowns. This node produces a sine wave by default, which results in smooth ease-in and ease-out effects. For this animation sheet, however, we want to have completely linear movement.
Out of focus and shaky. Itās actually a pretty cool effect, just not what we want right now.
To stabilize the movement use the Frac operation to convert the Time Nodeās sine wave to a sawtooth.Ā
As you can see, the output now describes a linear ramp with an instantaneous drop. Almost perfect for scrolling across an animation sheet.
Considering we want to cover the entire sheet in one second (or to whatever you set the time to), it is necessary to multiply the sawtooth with the total number of cells, which we can derive from the multiplication of the number of rows (X) and columns (Y) ā data stored in the aforementioned Vector 4.
To make sure the system only takes whole cells we have to round all decimals in the output up or down to their nearest integers. Conveniently, the appropriately named Round Node does just that. A nice diagnostics tool to test your network is to use a value Slider instead of the Time Node. You can easily track the values that flow through the nodes at any time and observe that the Round Node produces the results we are looking for. Alternatively, if anything in your shader seems to produce inadequate results, you can use this method to troubleshoot problem areas.
The sawtooth after rounding.
The next step is to define the rows and columns as well as the movement through them.
Starting off with the rows, we want to divide the rounded output with X (which is the amount of rows, as specific in the Vector 4). To prevent the shader from showing half frames we want to make sure that the output after division is rounded down. For this we will use the Floor node, which will result in the graph below.
When testing the network with the diagnostics as detailed earlier, you can see the numbers in action.
Now that the rows are defined, it is time to move on to the columns. To achieve this, weāll be using Fmod. Like Divide, this node requires two inputs. The image below demonstrates the effects of Fmod within the current shader network.
The long string of numbers represents the entire grid. This string is divided by X (which is 5; the number of rows). This leaves 5 sequences of five, representing the 5 columns on each row.
To steer the horizontal and vertical movement over the grid we simply have to divide by X and Y, respectively. Notice how the division for the verticality outputs 0.2 at the start of the sequence. This means movement starts on the lower side of the Y axis, which is undesirable. As weāve established in the read order, every sequence ought to start at the top row. To correct this we can use One Minus. This node has made an appearance in an earlier breakdown <link> to invert a Fresnel effect. What it actually does is take the value 1 and subtract its input. Logically, with an input of 0.2 this results in 1 ā 0.2 = 0.8, which is the top of the grid. Make sure to append both paths and youāve got the read order all set up.
Almost there, but we still need to make some adjustments to the UVs. By default, UV coordinates encompass the entire texture, but we want to essentially single out 1/25th of this texture at a time. Take both X and Y from the Vector 4 and Append them and use its output to Divide the UV coordinates.
Finally, add the read order to the UVs and connect it to the animation sheet texture.
3.) Combine
Merging the separate networks together should be relatively straightforward, as the required techniques have been elaborated upon at length in previous shader breakdowns.
Add colour to the animation sheet and use blending to add it to the emission. Be sure to join all alpha channels together.
Extend the flowmap-distorted UVs to the tiling network.
The final results.
Check out Counterspell on Greenlight!
https://steamcommunity.com/sharedfiles/filedetails/?id=643651505
To stay up to date with our latest news, follow us on Twitter!
@PunchButton_DEV
You can also like us on Facebook!
https://www.facebook.com/punchbuttonstudios
Introduction: This is a step-by-step breakdown of one of our characterās projectile impacts, shown below. This is a follow-up to the Eileen Projectile Shader breakdown, where we elaborated on the projectile itself.
Although this particular breakdown deals with some (basic) scripting, it is tailored primarily to (VFX) artists. The goal is to show ways to manipulate specific shader properties through said coding to create the desired effect.
When attempting to recreate anything shown here, try to experiment with changing variables and observing the effects of said changes ā it can be very beneficial to the learning process.
Difficulty: Novice
Subjects: Access & manipulate shader properties, Access & manipulate variables in other components, Animation curves, time.deltatime, C# basicsĀ
Prerequisites: Elementary understanding of Shader Forge (or similar node-based shader editors) and its terminology. As this breakdown builds upon a previous breakdown, it is highly recommended to (re)visit it before attempting to follow this particular breakdown.Ā
Basic understanding of the Unity engine and its interface.This breakdown assumes you are familiar with particular terms such as editor, inspector, hierarchy, gameobject and component.Ā Ā Ā
1.) Shader Forge Preparation
To achieve this impact effect we first need a shader to work with. Weāll be using the previously created projectile shader as a base, and apply the required adjustments from there.
An important aspect of this step is to acknowledge Property nodes in Shader Forge and how they are different from regular nodes. Property nodes are recognized by their green frames, whereas regular nodes are grey.
These are variables that show up in the inspector when you open a material with this shader applied to it.
When hovering over or clicking on these nodes within Shader Forge, you will see an āinternal nameā pop up, which corresponds with the name youāve given to the node. This name - easily recognized due to the prefixed underscore - is very important, as this is what will be referenced and manipulated in the script later.
With that knowledge at our disposal we can start building the required functionality into the shader. The original projectile shader had built-in UV-based rotation. Considering we want to govern rotation by the way of script for the impact effect, we have to take out this UV rotation first.
Next up is a system that allows us to control the size of the hole in the middle of the disc. We will achieve this by creating a second alpha texture to complement the texture weāve established in the earlier breakdown.
We essentially want to be able to blend these two different alphas in varying increments. For this we will use the versatile Lerp Node. Lerp takes three inputs: A, B, and T. In our case, we will equate the original alpha texture to A and the new one - with the bigger hole - to B. Input T will be the blending agent. For our current objective, a simple value slider - ranging from 0 to 1 - will suffice.
0 = A, 1 = B
Now all we need is an extension to the system to be able to fade out the entire texture. Naturally, weāll use Lerp once more. This time we take the output of our previous Lerp for A and a plain value of 0 for B. Alternatively, you could remap the alpha values of either texture from 0 > 1 to 0 > 0 to produce the same effect.
The shader is now all set, with the properties _HoleSizer and _MainFade at our disposal.Ā
2.) Unity Preparation
First off, weāll have to get all the easy stuff out of the way. Create a new empty gameobject, and call it something like āEileenImpactā. Now, add a mesh filter and mesh renderer component to it. Place the disc model from the earlier breakdown in the mesh container, and a material containing the shader in material0 of the mesh renderer. The projectile should be visible now. Finally, we can add a new script component, make sure itās a C# script, and call it āEileenImpactā.
Double-click the name of your script in the inspector or the asset folder to open it. You should be greeted with the following text:
This might not make a lot of sense by itself, which is why Iāve numbered the different parts of the script:
1.) These are used to access classes in different namespaces. Ignore them for now.
2.)Ā This is the name of the script itself. All of our coding will be done between these curly brackets.
3.) Functions, or voids, are used to tell the game which code to run when. For example, all Ā the code you put in void Start() is only called once, before anything else, on the first frame that the script is active. This makes it ideal for initialisation.
4.)Ā Update(), on the other hand, is called every single frame. Depending on how fast your computer is, this could be dozens to hundreds of times per second.
Thatās all you really need to know to write the script. So, letās start programming!
3.) Changing Transparency
Our first goal is to make our object transparent. To do this, weāll have to manipulate the āMainFadeā property we added during step 1. This means weāll have to ātalkā to the gameobjectās material, which is, in turn, stored in the mesh renderer component of our gameobject.Ā Ā
We only want to change the properties of THIS objectās material, not EVERY instance of this material.
First order of business is to give this material a name within our script, so we can talk to it more easily. Add the following line above the start void:
Now we have to tell our script which material weāre referring to by āmyMaterialā. We do this by using the method āGetComponentā. This method will search our gameobject and look for a specific component, in this case the mesh renderer. To get the material within the mesh renderer, add a dot, followed by āmaterialā. We only need to find it once, so we should put this line of code in our Start() function:
Weāre finally ready to set the āMainFadeā property of our material to any value we want. The way to do this is by using a method called āSetFloat()ā. Between the parentheses, youāll need to type the name of the float you want to change (in this case: ā_MainFadeā), followed by a comma, followed by its new value (1, which means fully transparent):
Run the game to see if this works. If you did everything right, the projectile should be fully transparent in play mode, but colorful outside of it.
It works!
4.) Fading Transparency
Of course, we donāt want our little vortex to ājumpā from opaque to fully transparent within a single frame. Rather, we want it to fade out smoothly, over time. Thatās what weāre going to add now. Often, the most intuitive way to do fades and transitions is by using animation curves. So letās add one to our script. Above the start function, add:
But why is this animation curve public instead of private, like our material? Good question. Itās so we can actually change the animation curve in the inspector! Thatās right, letās head back to the inspector, and there should be a little grey rectangle in your script component. Click it, and youāll open a dedicated curve editor:
A familiar sight for most game artists.
Although itās nice to play around with, our animation curve doesnāt really do anything right now. We want the transparency of our gameobject to change over time. This means the y-axis of the curve should correspond with the value of the āMainFadeā property, and the x-axis to the time (in seconds) since our gameobjectās creation.
If implemented correctly, this point on the curve should mean: "After 0.5 seconds, the value of mainfade is 0.5".
So letās add a timer! Like before, we start off by giving this variable a name, ātimerā in this case. Above the Start() function, add:
Weāll also have to make sure that our timer always starts counting from 0. In the Start() function, type:
Now we have a float that sets itself to 0 when itās created, but it doesnāt measure time yet. To get it do this, weāll have to make use of āTime.deltatimeā, which measures the time (in seconds) that has passed since the last frame. This means that if we increase the value of our timer variable by Time.deltatime every frame, weāll have an accurate measurement of time:
Make sure you put this line at the very top of the Update fuction; counting should happen before anything time-based.
Now that our timer works, we can link the animation curve to it. Go to the line of code in the update function, and change the ā1ā into āmainFadeCurve.Evaluate(timer)ā:
This line of code means something like: āSet the value of āMainFadeā to the y-axis value of āmainFadeCurveā at the current point in timeā. So this works now. Try playing around with the animation curve from the curve editor, to see what looks best.
The result of the default curve from 0 to 1, in 0.5 seconds.
5.) Fading Hole Size
Itās time to add another effect: the expansion of the hole in the middle of the vortex. This step is almost identical to the last step. Again, we start by creating an animation curve:
And again, weāve got to link this curve to the timer like so:
And weāre done!
The result of a quickly accelerating curve from 0 to 1, in 0.5 seconds.
6.) Fading Object Size
One of the things that makes the impact effect exciting, is the fact that it expands while itās disappearing. This makes it look like the vortex is made up of some kind of gas, or plasma, which is being dispersed. Letās add this feature to our script! You know the drill by now, just add another animation curve to the top of the class:
To change the size of our gameobject, weāll have to talk to its Transform component. This is where all the values concerning the position, rotation and scale of a gameobject are stored. Unlike other components in Unity, we donāt have to use GetComponent to access our transform. The property of the transform that we need to change its size is called ālocalScaleā. So, if weād treat this property the same way as in the previous steps, weād end up with:
...but this doesnāt work.
Thatās because localScale is not a float, but a vector3, which is a variable that actually contains 3 different values! Theyāre always between parentheses, and separated by commas. The first value is the x scale, the second value the y scale and the last value is the z scale of the object.
This means that localScale expects that we give it a vector3 to work with, instead of a float. In C#, this means creating a ānewā vector3 every frame. We then have to fill all 3 values of newScale with the y-axis value of our curve:
So the above line of code means: the value of localScale.x, localScale.y and localScale.z is the current y value of scaleCurve.
OPTIONAL: We can abbreviate this code to make it less ugly/messy, by typing it like this:
The result:
The result of an exponential-style curve from 1 to 1.5, in 0.5 seconds.
Feel free to try different kinds of curves this time. Making the projectile shrink instead of grow might look good, too!
7.) Fading Object Rotation Speed
For the final effect, we need to spin the disc. The fact that the rotation slows down over time really sells the idea that the disc is dissipating its energy. Here we go again!Blah blah, add a curve:
I'll just assume you know where to put this by now.
As Iāve explained in the previous step, the data concerning rotation is stored in the transform. Transform contains a method called āRotateā, which kind of explains itself. Like localScale, Rotate wants us to feed it a vector3. Since we only want to rotate our object along its y-axis, we just have to fill in the second value of the vector3:
Pay attention! This spinCurve is the first one that needs a high y value to be noticeable. Itās probably best to start with a value of 30:
Right click a key, then click "edit key" to type in values. Will save you a lot of trouble!
The final result, after some tweaking:
Thatās it, folks! I hope you learned something, be sure to leave some constructive criticism if you didnāt. Talk to you later, bye!!!
Check out Counterspell on Greenlight!
https://steamcommunity.com/sharedfiles/filedetails/?id=643651505
To stay up to date with our latest news, follow us on Twitter!
@PunchButton_DEV
You can also like us on Facebook!
https://www.facebook.com/punchbuttonstudios
Introduction: This is a step-by-step breakdown of one of our characterās projectiles, shown below. The focus lies predominantly on the actual shader construction, not so much individual variables such as specific images and values. When attempting to recreate anything shown here, try to experiment with changing these variables and observe the effects of said changes ā it can be very beneficial to the learning process.
Difficulty: Intermediate
Subjects: Fresnel, Light Dispersion, Refraction, Screen-Space Effects, UV Manipulation (Panning, Flowmaps)
Prerequisites: Elementary understanding of Shader Forge (or similar node-based shader editors) and its terminology. Some elements build upon the previous breakdown, so be sure to (re)visit it if necessary.
1.) The Bubble
Snegliiās right arm is based on that of the pistol shrimp; a creature capable of using its oversized claw to propel ābubble bulletsā at potential prey. As such, this projectile will have the characteristics of a bubble: a transparent surface that refracts shapes behind it. As this is Counterspell, the projectile also requires a clear colour indication. To start, weāll set up a simple bubble using a Fresnel effect to also outfit it with a distinguishable colour. A default sphere will work fine to preview this shader while you work on it.
For reasons stated in the previous breakdown, we will use the Unlit shader again.
Use the Fresnel Node, multiply it with a colour of choice and then plug it into the emission. Adjusting values for the Fresnelās exponent controls the thickness of the rim; high values for a thin rim, lower values for something more broad.
We got the colour system in place, but itās anything but transparent. This is easily fixed by using the Fresnel for opacity.Ā
2.) Refraction
Refraction is an operation that distorts the pixels behind the object as you look through it. The particulars of this distortion can be managed by using a normal map.
Considering this distortion is achieved by offsetting UVs, the effect expects the red and green channels associated with UV operations. Extract these channels from the RGB normal map texture by using a Component Mask. Use a Remap Node to tweak the intensity as desired.
To get some movement in the newly created refraction, weāll pan the UVs of the normal map texture. Having values in both U (horizontal) and V (vertical) will get you a nice diagonal scroll.
In order to make the object look more like a liquid, weāll conjure another flowmap. The setup is similar to that of the Eileen Projectile, bar one addition; whereas the animation in the distortion there was driven by the rotation of the UVs, here we will actually animate the flowmap itself as well. To achieve this, create a sine with the Time Node and multiply it with the conventional flowmap setup. Finally add the output to the already panning UVs.
Itās starting to look like a bubble now, but thereās another element that can be added to make it a tad more interesting to look at.
3.) Light Dispersion
Dispersion occurs when white light is separated and āsplitā into different wavelengths. This concept is often demonstrated with the use of a prism, or commonly observed as a natural phenomenon in the form of a rainbow.
Knowing how this effect occurs in the real world, it is now possible to figure out how to simulate a recreation in the shader; we basically need to offset the colours that we see through the projectile. To achieve this, we need to extract the colours that are present in your scene. Conveniently enough, Shader Forge has a Scene Color Node for that. The extraction of the scene colours effectively simulates transparency, so we no longer need to have the Fresnel generating opacity.
Unfortunately this has created a new problem. As you might be able to notice, the projectileās colour is significantly lighter. This is because the Fresnel is now blended with the scene colour data behind it. This means that the colour will be different depending on its background, causing potential inconsistencies in projectile colours. This is highly undesirable in Counterspell, as this may have a negative impact on readability. To correct newly surfaced problem we can use the Fresnel that we have as a mask of sorts to tell the shader to only take the scene colour where the Fresnel doesnāt cover the background.
A good method to achieve this is by inverting the Fresnel using the One Minus Node, and subsequently multiply the scene colour with it.Ā Ā Ā Ā
In order to offset the different āwavelengthsā we need to split the RGB channels of the extracted scene colour, so we can adjust these individually.
With that out of the way, we can start building a system to actually perform the offset. The core of this system is the Screen Position Node, which we use to shift UVs in screen-space. When adding a value to either the U or the V we can ultimately offset colour channels vertically or horizontally. In order to offset to both left and right with the same value we add a Negate Node. You can see the setup in action below.
Now all thereās left to do is hooking up the offset system to the separated scene colour channels.
Check out Counterspell on Greenlight!
https://steamcommunity.com/sharedfiles/filedetails/?id=643651505
To stay up to date with our latest news, follow us on Twitter!
@PunchButton_DEV
You can also like us on Facebook!
https://www.facebook.com/punchbuttonstudios