This has been puzzling me for a while now.
A "2D Vector Field" or "Flow Map" is a user-created texture that determines the direction of which a material moves - most commonly used with water shaders to give the impression of the liquid flowing round objects such as in this video:
[ame="
http://www.youtube.com/watch?v=2X1vFVGAlwk"]UDK - Water with Flow Map - YouTube[/ame]
Now, I have found a few smatterings of information on the 'net, mainly
on this very forum and the
Graphics Runner Blogspot, but none of them go into the theory of how the texture information is read or, more importantly, how to create it yourself.
I know that a Flow Map has more than a passing resemblance to the 'TextureCoordinate' and 'Panner' expressions in the Material Editor, so presumably the engine uses this texture in exactly the same way.
In Summary:
- How do you create a "2D Vector Field" or "Flow Map"?
- How do you use this in UDK's Material Editor?
Thanks for your time
Replies
I´m already using them in my proyect, Understanding them is the most important.
You must know that a flow map is in fact a Motion vector field.
Your flow maps must tell the txture panners in what direction the texture should move.
So The best way to make the flow maps is painting them in PS, you could use also Houdini, but painted Flows are grat also!
[FONT="]
Alex Vlachos[/FONT] has papers on this features, he has used them in Portal2 and Left 4 death 2.
The shader, .. read first Kyle hayward blog becouse everithing you need is there (http://graphicsrunner.blogspot.com/2010/08/water-using-flow-maps.html).
By the way, .. How can I upload a picture just to show you my flowmaps working in my level.??
You can upload a picture to http://imageshack.us/ and copy the forum link here
That page still doesn't entirely mention how to create flow maps for use with UDK though. Or am I just being really dense and am going to have to use Unreal script?
You paint on gradients that indicate the direction you want the map to sit.
I have done this using vertex colour. Where the vertex colour replaced the UVs.
Similarly, a pixel that is half red and half green would create a vector moving diagonally.
Is this right?
As well as that, how would I create a pixel that has a vector '-1' (pointing backwards)?
Again, apologies for being quite dumb in this regard, but how would I tell UDK to use this information?
Presumably, just plugging in this information into a Texture's UV channel would distort the image but still be static. How would I get it to actually animate, following the coordinates that I have created?
Edit: Perhaps plugging in my custom flow map into a Panner's Coordinate node?
Just multiply a time factor (representing how fast the flow is going) by the R and G channels of your flow map, then add that multiplied 2 vector to a texcoords node, then plug that into the uv's of your texture.
and for what its worth I'm getting some really harsh artifacting from the texture interpolation.
further edit: Artifacting seems to be remedied by keeping the time variable from going to high values. Either with a frac, or fmod.
You get negative displacement the same way you do in a normal map. 0 value in a channel is -1, 255 value in a channel is +1 127 is 0. You can specify this in UDK's texture properties with UnpackMin and UnpackMax, or do it manually in the shader.
My material has the Flow maps multiplied by Text coord, and the result is conected to panner as coords, but remember that you need to remove the blue channel from your maps with a channel mask becouse in coord only R and G channels are acepted.
I used them this way so I can multiply Time by Scalar parameter to control the velocity of the movement, and flwMaps as coordinates for the panners.
I did some more changes to shader to have the posibility to set up more things, and to have more control, But is essentially this Theory.
I´ve to say that is the heviest shader I´ve done, in meaning of material instructions, Flow maps for water like materials are expensive for GPUs.
(That's Ignoto's image)
That's really helpful.
I'll have a go tonight at making a Flow-Map in Photoshop by having the image base colour of '127,127,0[RGB]' and painting in paths with varying degrees of Red and Green.
... I may draw myself a graph-based diagram to help me visualise the vectors better too
Then I'll import it into UDK to have a look at using both your methods in a Material.
Edit: That is a really sweet-looking effect in Ignoto's image
@SirCalalot: I believe Valve used Houdini to get their maps rather than drawing them. Might have to go back and find the presentation.
I just found the prsentation here. So I'll read through that now.
I´m good with 3D but I get lost using forums, and web features.
SirCalalot - This PDF is what I were talking about, when I refered to "Alex Vlachos paper".
Is this the way which you created your Flow Maps?
I'm thinking that if I wanted my water to flow round an object, I could create a black and white height map putting a peak where the object is.
Then I might be able to convert this to a normal map using NVIDIA's Photoshop plugin and excluding the Blue values.
For the flow maps, I literally took a screenshot, adjusted it to the intended resolution of the flow map and painted over the top of them by hand. It's just vector fields, so all you really need is a smoothly gradiated radial brush and you'll get reasonable results.
You can paint and try it in Maya or directly in UDK, to see you paint them correctly.
That's exactly what I wanted to know
Thanks for entertaining my ignorance on the matter (there is seriously bugger-all information on Flow Maps in UDK on the 'net).
haiddasalami: It would be so awesome if you did that, although I figure it would be pretty hard.
Ignoto: That's actually pretty cool! Mind if I ask what your Flow Map looks like?
http://www.valvesoftware.com/publications/2011/gdc_2011_grimes_nonstandard_textures.pdf
oooohhh, show me!
Part of the reason for lack of info is this is a specific topic, and its also more of a composite term for what's going on. All you're doing here is using a per pixel vector offset to texture coordinates. You're just doing it over time to create the "flow"
The basic nature of the map in question is essentialy the same as anisotropic directional control, normal mapping, paralax mapping, etc. Its just a different application of the data/method
Just read through that and it's very insightful. I'd urge people to check it out
That said, I'm sure that some effective flow maps could be made by creating a height map, with slopes denoting what direction the water should travel. For example, a spiral starting as white and gradually going to black should, in theory make a normal map that can be used as a flow map where water follows the spiral.
than bake that plane down to a basic Lowpoly one in xnormal or transfer maps, and remove the blue channel in Photoshop.
in theory that should be a easy way to author a flow map.
would prolly want to find a way to use soft selection with that tool, and maybe blur the end result to give better transitions. im sure someone with a better understanding of flow maps and maya vertex normal edit tool could prolly write a nice little mel script for maya for creating flow maps.
I tried pluging it in this way, but both the green channel and red channel only makes it go in one direction or not at all, how do I make it go in either?
A- Write your own formula so you determine what gradient does what (if you want to bypass the traditional limitations of colors).
B- Use a plugin to 'comb' the mesh in the direction you want it to go in (a la Anistropic map type).
Passerby's solutions sounds the cheapest and easiest hack out of the box, but you have to manually edit your vertices (maybe in soft selection mode), at least, that's what I believe, since I don't think Max, Maya, XSI or even Houdini has the ability to comb normals/vertices weight with a brush (Valve and ND had to create their own custom solution plugin).
As to how to make it go in either...what exactly do you mean? As in left/right distortions? Why not use the Depth node and overlay 2 normal maps in two opposite pans?
Red is X, green is Y. Plug only one channel in, you only get one direction.
so i think a really intuitive way to edit them for this purpose would be to make a script, that points all the vertex normals in a soft radius away from, or towards dummy objects that can be set and moved by the user. which would be how valve did vortices in Houdini.
im not much of a coder/scripter, but i could look at the reference for mel and maybe at-least figure out the basic logic needed, and try to make a basic proto-type.
I'm a Max user myself, but I may have to make the jump to Maya if you get it going well
it will prolly take me a good bit of time, since i got no experience with mel or python script, and just some basic php knowledge so i will be learning as i go, the concept, and logic seem simple enough, but the math, to get the right vertex's around the object, and to get the soft selection on it will be harder.
not being a max user im not sure what maxscript is cabale of, but im absulty sure the same data would be modifiable via maxscript.
also Houdini does have a free license for personal use, which could be a good starting point for someone to figure this out with out needed code.
once this is figured out, it should be fairly easy to implement in UDK, since in udk it is very easy to export out your whole map or sections as OBJ, so you can build your water plane to fit the geo, and use the geo as reference on how to make the flow map, than after that it is just a matter of adding a panner to the texture coordinate, and add it by this map, and hooking it into your UV's of your textures.
also in cases where you just need some general UV distortion, it is quite easy to do in UDK already, such as cases of the fizzer fields in portal 2.
i find that works well for just general distortion in the UV's, my texture, is just clouds generated separately into all the colour channels.
but for things like water and the effects you see in portal2 and l4d2, something like what i explained in maya, or some kinda brush in maya or PS would be needed.
also you could steal the basic elements of the flow map from existing ones, and copy and past in things like the vortices.
also found this http://www.valvesoftware.com/publications/2010/siggraph2010_vlachos_waterflow.pdf a bit more info on what l4d2 did
Edit: Although I did find this.
"Re: brush behaviour: direction-based colour possible?
No, because you can't create tool plugins in Photoshop.
Please read the SDK to see what plugins can and cannot do in Photoshop."
... Lame.
also would be interesting to generate these gradient right in udk, maybe using a sphere mask with the "World Position" node and a vector3 defining the world position of the distortion.
I only get positive y and positive x. it doesn't go negative.
That's because you've set up your material to only work that way. Doing something like subtracting 1 from a colour channel will give you a range of -0.5 to 0.5, which gives you bidirectional panning if you need it. Makes your flow maps harder to author though.
It can be. I've seen a lot of people us vector field tools for this kind of thing - but that only really works if your geometry can be imported wholesale into a 3d map easily.
If you want to generate it in UDK, you can just mesh paint it on directly quite effectively.
How would you do it in UDK effectively that doesn't weigh a ton in terms of instruction and allows for the less then capable technical artist in getting interesting effects (say an outer rim for maelstrom kind of effects to avoid harsh cuts) in a way that's very malleable?
Remember, the entire point of Flow Maps is being artist friendly, and having low memory footprint (a 512px Flow Map hidden in the Normal Maps blue channel), doing it on a plane that is wildly limited to vertices and instruction is all fine and dandy upto a certain point.
Plus, vertex blends are there for a reason, several smaller scaled flow maps can be applied manually if needed in a carefree way later on alongside the mother flow map, but for best results, I do believe a flow map is in order.
A "flow map" like you guys are calling it, needs 2 channels, no more no less. (It can have an empty blue channel of course).
I don't think you guys fully understand how a "flow map" works.
These are the unaltered texture coordinates of a TextureSample:
If you were to "shift" the pixels in this picture in any way, it would shift the pixels in the TextureSample as well. If you tile this image you will tile the TextureSample as well, and so on. One crappy and fast way of altering your "flow map" would be to use "Liquify" in Photoshop. I say crappy because the mesh that Photoshop uses in order to distort the picture is not subdivided enough (internally), and you won't be getting smooth results. In order to be able to "preview" your distortion better you can distort your texture with liquify and save the mesh, then open the above image in photoshop, load the mesh and apply the distortion.
If you want to make it properly, then I suggest you get your hands dirty with an actual mesh in 3dsmax, subdividing, re-baking and so on.
One of the script that is definitely in my to do list is a primitive version of what Valve did with Houdini but for 3dsmax.
I hope this helps you out!
EDIT:
Pro tip: You can lerp between a regular TextureCoordinate and a "flow map"
Also notice the artifacts in the texture when the camera get's close. This will only happen if the distortion is too big. Remember it's just a 8-bit image, not a 16-bit one. So it's just doing what it can. There are probably ways to improve the artifacts. As I said, haven't had much time to play around with this since I first tried it a year ago.
[ame="http://www.youtube.com/watch?v=SYvOfRkPcaI"]http://www.youtube.com/watch?v=SYvOfRkPcaI[/ame]
EDIT2:
Couldn't wait so I tried to find a way of reducing the artifacts caused due to the low bit-depth of the textures. And I found a solution!
You can split a 16-bit "flow map" into 2 8-bit ones, and then combine them back together in Unreal. As you can see a lot of the artifacts are gone. Some are still there, in this case we would perhaps need another 8-bit image.
Also, are you Appending the maps through channels, or are they two separate texture calls?
No worries...
Almost. It is imported as an uncompressed normal map.
My preferred method, as I mentioned above, is to create the "flow maps" in 3dsmax. You take a plane with a regular top-down mapping and you start moving verts around, rotating, whatever.
Then I created a script that automatically bakes the deformation down to a "regular" plane. The output is a 16-bit png with all the nice gradients.
I guess you are referring to the 2x 8-bit "flow maps". These are in fact 2 different uncompressed normal maps. The original size should be 512x512, since after setting it to uncompressed the size will be scaled down to 256x256. I tried to put them in a RGBA texture, but unfortunately you can't have an uncompressed texture with alpha in UDK. And I really need the flow map to be as untouched as possible.
As I'm writing this I had yet another idea... Perhaps I can make it all fit in a single uncompressed normal map after all... I'll give it a shot tomorrow...
From a tech stand point, I'm confused as to why it looks like the UV distortion is sampled in Nearest format as opposed to Linear. Hmm.
The reason for that is perhaps a bit difficult to explain for me in english, let me try! Sorry if I repeat stuff I already mentioned in previous post, it never hurts.
So basically you have this image:
It's an 8-bit image. In other words... the gradients between 100% black and 100% white have 256 values and won't have more. Those are all the pixels you can "play" with. There is no point in making a vectormap bigger in resolution than 256x256. A 512x512 8-bit vector map, will still just have 256 values per channel. If you make a horizontal gradient in photoshop in a 512x512 canvas and zoom in, you will realize that it will repeat each color twice in order to fill the 512x512 canvas. So you'll have two pixels with a 255/255/255 value, the next two pixels will have a 254/254/254 value and so on.
Now, let's keep in mind that this bitmap represents the UV coordinates of a texture.
I think this describes it best:
I bet you can already tell what one of the problems is going to be. You will only be able to "distort" 16x16 pixel chunks in a 1024x1024 texture. Because one pixel in that 8-bit 256x256 vector map is assigned to 16x16 pixels in the 1024x1024 texture.
(Note: You can move the black pixel, duplicate, even replace it completely with another color and the same things will happen to the diffuse texture.)
Not only that but... if you distort a vectormap a lot, you won't have enough different colored pixels to represent that distortion perfectly since you are constrained to a 0 to 255 value. Here is where a 16-bit vectormap makes sense, it has 0 to 511 values.
Keep in mind that a vector map is an attempt to represent a geometric distortion in 2D. The more values you have the more accurate it will be.
This actually reminds me that I did use a 16-bit vector map in a previous post but it was still 256x256. D'oh! I should probably try it again but with a 512x512 resolution.
All that being said... I still think the valve did something with the sampling that smoothed out the vector map somehow. Either that or I'm missing something here...
this is the map im using, i tried to get something similar to your example.
EDIT: also, what sort of filetype is the 16bit image you used before? with unreal, only targas will work properly for textures, and if you have a 16 or 32 bit image, you cant have a targa.
and this is my result.