Home Unreal Engine

[UDK] Player Position-based Material

Recently, a coworker posed a question to me:
"How do you pass the player position to a material in UDK?"

"Well, couldn't you just use the CameraWorldPosition node? The player and the camera are so close together the effect should be enough, right?" replied I.

"That could work, but I want to do a far-back third-person camera," he countered.

"Oh..." I said.

After attempting a solution that was, admittedly, rather hacky involving trying to programmatically derive the location of the player based off a known distance between the camera and the player, I opted for something that could be considered hacky, but is as close to a programatic solution as an artist can get.

Looking into the situation, I thought perhaps I could use Kismet to pass the position of the player to a Material Instance using the Set VectorParam node... only to find out that node was taken offline back in 2010. Of course, with the clever use of "Append Vector" nodes, three scalar parameters can quickly turn into a float3, right?

Do excuse the garish colors. They were chosen to best showcase what's happening. This could certainly be used to implement more subtle effects.

So that's what I did. Here's the base material (click to enlarge)

playerPos_material.jpg

And the kismet setup. I put a delay after the operation is complete, otherwise Kismet throws a "too many operations" error. The delay is .033 seconds, or roughly 1 frame at 30 frames per second. The delay is barely perceptible, and it minimizes the number of calculations that have to happen. (click to enlarge)

playerPos_kismet.jpg

Combining all that, you get this (video forthcoming):

playerPos_playerView.jpg

From a CameraActor:

playerPos_cameraView.jpg

Replies

  • unstoppablex
    that is pretty awesome!
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    in uscript you could write a custom player pawn, which could easily pass the location onto the material as a vector 3, since there is a method to get player location in uscript and uscript isnt limited to olny dealing with constants like kismet.
  • ImSlightlyBored
    Offline / Send Message
    ImSlightlyBored polycounter lvl 13
    I've done this before for smoke, etc.
    It's good... but fairly heavy to do it through kismet unforunately :( Good for proof of concept though
  • ambershee
    Offline / Send Message
    ambershee polycounter lvl 17
    passerby wrote: »
    in uscript you could write a custom player pawn, which could easily pass the location onto the material as a vector 3, since there is a method to get player location in uscript and uscript isnt limited to olny dealing with constants like kismet.

    This x1000. All you have to do is use a vector parameter and set the value of it from UnrealScript. It's much more efficient than deriving it like this, and it's very easy!
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    also don't need to recreate a ton of kismet for every new scene, and ot use hte efefct just set a gametype as default that uses your new pawntype.
  • ozzmeister00
    Like I said, this is hacky, and easy for artists who have no intention of coding to set up. I'll be looking into uScript options a bit later down the road and post what I come up with for sure!
  • Slainean
    Offline / Send Message
    Slainean polycounter lvl 18
    Thanks a lot for sharing this - definitely useful.


    I'm pretty new to UnrealScript, but I gave this one a shot. The trick was to create a MaterialInstance in the UDK editor first, then reference it in UnrealScript.

    I also tried putting it in a Pawn class other than the player, and that works, too. The only catch is that you can only use the location of one pawn as things are.

    worldpospawn.jpg


    I used your exact Material setup, but I changed the X/Y/Z ScalarParameter names to XPos, YPos, and ZPos.

    Here's the code for the Pawn, but you could just as easily put this in the PlayerController class with a couple simple edits. You can see the material is located at "MyPackage.material.mat_test_worldpos_INST" - MyPackage is the package, Material is the group, and Mat_Test_WorldPos_INST is the MaterialInstanceName.

    Hope this helps someone!

    class WorldPawn extends UTPawn;
    
    
    var MaterialInstanceConstant WorldPos;
    
    
    function Tick( float DeltaTime )
    {
    	local float X;
    	local float Y;
    	local float Z;
    	
    	X = Location.X;
    	Y = Location.Y;
    	Z = Location.Z;
    	
    	super.Tick(DeltaTime);
    	
    	WorldPos.SetScalarParameterValue('Radius', 50);
    	WorldPos.SetScalarParameterValue('XPos', X);
    	WorldPos.SetScalarParameterValue('YPos', Y);
    	WorldPos.SetScalarParameterValue('ZPos', Z);
    }
    
    defaultproperties
    {
    	WorldPos=MaterialInstanceConstant'MyPackage.material.mat_test_worldpos_INST'
    	Name="Default__WorldPawn"
    }
    
  • batmahn
    great stuff! i'm experimenting with this technique though i'm just using the cameraworldposition inside the material itself as i'm keeping it first person :) thanks!
  • ozzmeister00
    That's awesome, Slainean! I've got a similar thread going on the UDK forums, would you mind posting your code there, too?

    http://forums.epicgames.com/threads/899690-Player-Position-based-Material
  • ambershee
    Offline / Send Message
    ambershee polycounter lvl 17
    Slainean wrote: »
    I also tried putting it in a Pawn class other than the player, and that works, too. The only catch is that you can only use the location of one pawn as things are.

    You'd need a unique mask for each player in the shader - then you'd need appropriate math to sort them out properly. It's not fun, and rapidly gets expensive ;)
  • PointlessReboot
    You could also just use the ObjectWorldPosition material node, which will give you the position of the actor using the material.

    Also look at ObjectRadius etc.
  • Slainean
    Offline / Send Message
    Slainean polycounter lvl 18
    That's awesome, Slainean! I've got a similar thread going on the UDK forums, would you mind posting your code there, too?

    Done!

    You could also just use the ObjectWorldPosition material node, which will give you the position of the actor using the material.

    Also look at ObjectRadius etc.

    I had a look at this node, and I couldn't figure out how you could use it to recreate this effect. As far as I know, it gives the world position of the actor that it's applied to, whereas this effect feeds the player's position to the material instance.

    ambershee wrote: »
    You'd need a unique mask for each player in the shader - then you'd need appropriate math to sort them out properly. It's not fun, and rapidly gets expensive ;)

    Yeah, I wouldn't want to deal with all that. I think this would be a great visual effect for a boss type character - so it's better to keep it unique.
  • passerby
    Offline / Send Message
    passerby polycounter lvl 12
    ambershee wrote: »
    You'd need a unique mask for each player in the shader - then you'd need appropriate math to sort them out properly. It's not fun, and rapidly gets expensive ;)

    ya i remember doing a forcefield shader, where i was using the hitlocation for a effect on it, and i pretty much gave up trying to multiple hits working in one material and ended up just spawning a new mesh, doing the effect on that mesh than killing hte mesh to get multiple hits.
  • ambershee
    Offline / Send Message
    ambershee polycounter lvl 17
    I can do it for any number of masks - but I had real issues setting it up to also drawn an outline around the masked areas (i.e not an outline around each mask, but around the area that is masked).
    You could also just use the ObjectWorldPosition material node, which will give you the position of the actor using the material.

    Also look at ObjectRadius etc.

    That's not that useful really, since you want to affect actors in the world other than the one you're using (also, IIRC those nodes are vertex shader only?).
  • ozzmeister00
    Slainean wrote: »
    Done!

    I had a look at this node, and I couldn't figure out how you could use it to recreate this effect. As far as I know, it gives the world position of the actor that it's applied to, whereas this effect feeds the player's position to the material instance.

    Correct! Which is why this thread exists in the first place. It's great for creating interesting effects as an object moves through the world. I've got another tutorial coming down the pipe for something to help break up modular kits.
  • MooseCommander
    I've been trying to figure out how to get this working for a landscape material, thank you very much!
  • tuxmask75
    Offline / Send Message
    tuxmask75 polycounter lvl 10
    Anyone know how to trail the effect behind the player ?
Sign In or Register to comment.