Today I'm going to explain vertex painting on (landscape) materials using only blueprints. It's quite easy to implement and does the job nicely, but... it is also not working the way I want it to. So it was quite a nice experiment, but I have to look for another solution to my problem. To prevent disappointment for the people that have the same problem as I did (don't worry, I have a solution now!) I'll quickly explain what this approach can and cannot do, before going in dept on how to do it.
So after I implemented this I could paint on the material on a per pixel basis, using only blueprints. The problems I encountered were that it doesn't use a separate layer, meaning that the resulting 'drawing' can't be used as a mask. And the biggest problem was persistence, it seems that Unreal Engine renders the material in a separate thread. I managed to send the player location to this using so called material parameter collections, but I can only use this to send one vector. So if I want to draw a path, ideally stored in something like an array, I have no way to send it all at once. The result was a terrain that flickered as different parts of the array where being drawn and erased in sequence. So take that as a warning before you read on and spend time on implementing this.
Now on to the exciting stuff! As always I had no real plan on how to tackle this issue, so I headed out to google and the Unreal community forums and founds some interesting suggestions. For this particular solution, this one inspired me most. It shows nicely how to change the color of a mesh using only blueprints.
This is a screenshot of the material I made to color the landscape material based on the location of the player.
As usually the problem with blueprints is that they can get quite messy as they get bigger. Maybe I can write a blog about organizing blueprints one day, something that I obviously didn't do this time. But if you look carefully and just follow the lines you must be able to figure this one out.First thing you have to know about material blueprints is that they are evaluated per pixel, so for every pixel in the material this blueprint is run and determines the color for that pixel. It is very essential to keep this in mind since it gets confusing quickly when you start thinking about the blueprint as setting the whole material at once (trust me, I've been there). Starting from the upper left corner you can see how the blueprint gets the current pixel's location and compares it to the player location. If it is within the affected radius it should be colored with a linear interpolation (Lerp) between green and grey, this gives a nice fall off effect where the green intensity decreases the further the pixel is from the player. If the pixel is outside the affected radius it is simply colored grey.
Now that I have a material that can change it's color based on the player location I have covered the hardest part of this solution. One thing that remains is actually getting the player location in this material, since it can't access it directly. This is where material parameter collections come in. If you want to know how to use them, check the link to the official documentation, I don't have anything to add to that. However I will show how I implemented the setting of these parameters in my solution.
I made this simple function that sets the parameter, I think this speaks for itself. Then I simply call this function every tick and pass the current player location to it: You can place this function in your level blueprint or to any other class blueprint that you want to use for this.Now the only thing you have to do is to apply the material we just created to the landscape. Then when you compile and run the game it should look something like this:
As you can see it paints nicely on the landscape, but as I explained before, it doesn't stay. And there is no way to send more data to it then just the vector with a location. So unfortunately I have to find yet another solution.
No comments:
Post a Comment