GMLscripts.com

Discuss and collaborate on GML scripts

You are not logged in.

#1 2009-10-26 12:35:20

xot
Registered: 2007-08-18
Posts: 1,201

UV Hijinks - Smoke and Mirrors

Vertex Warping vs UV Warping

Image warping with UV coordinates is often described as drawing a textured grid with the vertices displaced in such a way as to stretch and distort the image.

I don't personally like this approach. I think it has a lot of drawbacks. Unstable geometry can bend in weird ways, can overlap itself, can cause vertices to go out of frame, can fail to fully cover the intended area, can create seams due to affine texture mapping, and can result in large areas with very sparse texture sampling.

I prefer to leave the geometry where it is and apply the distortion to the UV coordinates. Doing so helps eliminate all of the above problems. Almost any vertex distortion can be mimicked by using the inverse distortion to warp the UV coordinates of a regular lattice of vertices.

The distorted blue lattice shows standard vertex warping. The yellow arrows show the same distortion but represented as a regular lattice of vertices with warped UV coordinates. Areas of low distortion have arrows so small that they cannot be easily seen but rest assured they are there. These arrows are in fact a vector field with the vectors pointing to a relative position in a texture. Notice that where the grid appears to bulge outward, the vectors point inward. Notice that the bulging areas have an even distribution of vectors. Contrast that to the blue grid where a small amount of geometry is forced to cover a large bulge, meaning the sampling density is lowest where it is needed the most. The checkerboard image shows many artifacts caused by this form of vertex warping.

Non-grid Warps and Compound Effects

This style of "Warp Wave" effect has been seen before, but now it is ridiculously fast because the filter has been built as a pair of models, one to shift columns up and down and another to shift rows right and left. This "old school" scanline effect is reproduced here using UV mapped line primitives. The first model warps the input texture with an axis-aligned sinusoid (wave). The output from that is then fed into the second model for warping along the other axis.

By varying the phase of the waves over time, an animated roiling effect can be created. Normally a dynamic phase change would mean the inability to use models and a lot of extra calculation each frame. One can get the same effect by shifting the texture images left/right or up/down before drawing the models. The models must be drawn counter-shifted to maintain the proper texture position. This is not demonstrated. This effect at this quality would be totally prohibitive using typical vertex warping tricks. Compound UV warping is what makes it fast and high-quality.

Image Feedback and Flow Fields

Now an interesting thing happens to a vector field when you allow it to feedback upon itself. It becomes a flow field. Imagine a vector field where all of the arrows are pointing a small distance to the right. When it draws its texture, the resulting image will appear a little to the left of where it normally would be. This is because, as the arrows indicate, the vertices are UV mapped a small distance to the right of their normal position. If we use this new image as our texture and repeat the drawing, the image will shift again the left. Continually repeating this process will cause the image to completely scroll away to the left. By using carefully designed vector fields one can use this technique to cause images to flow like liquid, or smoke, or in almost any way desired. The "Apparition" demo (below) is a great example of this. When you run it, be sure to hold the "S" key to reveal the flow field. This technique could also be used make an interesting death-by-vaporization effect. Delete all of the apparitions and then tap "A" and "D" in quick succession to see what I mean.

Apparition

Tile Painter

Environment Maps

With creative use of UV warps and dynamic textures, real-time environmental effects become possible as well.

Mirror Balls

Here are a handful of examples for your examination. You'll find most of them to be very similar in structure yet the range of possible effects is quite diverse. These examples were selected from the results of a couple of days of experimenting. I apologize for the scant comments. Have fun!

Similar Topics
I used these same techniques to create a prototype of a raster-based shadow engine.
http://www.gmlscripts.com/forums/viewtopic.php?id=1657

Last edited by xot (2011-05-20 05:42:54)

Abusing forum power since 1986.

Offline

#2 2009-10-27 12:21:05

Joseph
Member
Registered: 2009-09-04
Posts: 14

Re: UV Hijinks - Smoke and Mirrors

wow dude, this stuff is awesome!  if only they were expandable...or at least if I could expand on them.
I thought I knew surfaces, but this is way too complicated for me.  hopefully I'll learn something from it.

I got really food speed on most of them, but always over 60 fps.
you know how crappy my computer is, so that's awesome.

my favorite one was either the environment mapping or apparition.  but everything has a really cool effect.
I wish I knew how to use them better.  Little Big Planet uses the apparition effect on point bubbles and clouds of gas...
but I don't see yours working on a regular background unless it's just a simple edit that I'm too blazed to notice right now.

anyway, great job on everything.  I'm always looking for awesome effects.
maybe you could turn this stuff into water physics?  it seems like it'd work well as long as you can get the collisions right.

Offline

#3 2009-10-28 03:47:41

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Little Big Planet uses the apparition effect on point bubbles and clouds of gas...
but I don't see yours working on a regular background unless it's just a simple edit that I'm too blazed to notice right now.

I guess that's where I've seen the effect before, I couldn't remember. It would need a lot of modification for general use, but I have been thinking about how to make it simple to use with an extension.

I've got the ground work laid for a really easy to use extensible effects system. You assign effects to instances and they will be drawn using that effect until it is disabled. What's cool about it is it doesn't usually require any changes to your game, it's just a function call. Whatever is already in the instance's Draw Event will be used as an input to the effect. Where it really starts get interesting is the way you can apply effects in series. For instance, I can apply an effect to make an instance change color randomly. Then add another effect to cause it to warp its shape. Then add another effect to make it blurry. All of the effects are automatically compounded. The apparition effect was the original inspiration for this effects system, although I haven't yet produced that specific effect with it. I've been distracted with other things since then, but I think the system has potential.

maybe you could turn this stuff into water physics?  it seems like it'd work well as long as you can get the collisions right.

I don't think that's possible. Water is non-compressible and there is no way to maintain displacement with these simple feedback effects. You could certainly make some nice looking flowing water effects using these techniques, like a stream or a waterfall, but they wouldn't be physical or very interactive. You could block flow or get things to flow around other things but it would probably require some amount of actual CFD to make it appear realistic.

Abusing forum power since 1986.

Offline

#4 2009-10-30 20:01:21

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: UV Hijinks - Smoke and Mirrors

This is much smarter than that wind/flow example you helped me with a long time ago. Took me a while to figure it out. Thanks

Offline

#5 2009-10-31 07:26:39

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Not sure if this qualifies as UV Warping, but it certainly qualifies as "mirrors". It's a UV kaleidoscope. Thanks to icuurd12b42 for posting the symmetry talk which reminded me I had this in my collection.

Last edited by xot (2011-05-20 05:44:05)

Abusing forum power since 1986.

Offline

#6 2009-11-01 10:56:28

IamCalle
Member
Registered: 2007-10-20
Posts: 23

Re: UV Hijinks - Smoke and Mirrors

Truly some beautiful effects, xot, I am amazed.

Offline

#7 2009-11-03 09:13:50

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Thanks! They were a lot of fun to make.

Here's another effect that has some passing similarities to these others. I made this about 2.5 years ago. It's a scanline-style effect. Four points move around a texture at random forming a quadrilateral. The quad is remapped to fit the rectangular screen with much texture warping goodness. By remapping on a scanline-by-scanline basis, affine transform artifacts are eliminated. This is sort of like how Quake and other early 3D games solved similar texture mapping problems. It's not all that fast but it's occasionally mind altering. I've thought about turning it into a screensaver, although I don't use screensavers myself.

Last edited by xot (2011-05-20 05:44:32)

Abusing forum power since 1986.

Offline

#8 2009-11-05 00:25:13

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: UV Hijinks - Smoke and Mirrors

In order to understand this I decided to implement it my way.

I was thinking of a method to define models and their uv in order to create effects in game... You would load your sprite and define the flow of the image using splines.

Click to add splines, right click when done with current spline (adds the last point), click to add more.
Backspace to delete last split point.
Hit space to reset the image.
You can select a spline by clicking on the arrow head if you are not currently building a new spline.
Enter to show/hide the cells and the vectors.

Can you tell me why I have to draw the model at -.5,-.5?

It's a little blocky. I guess you can increase the h and w count in the grid controller.

When data changes, it triggers the MakeModel code... But before, it loops through the splines and defines the dx dy of each points in the grid. A spline line may affect multiple grid points, but the effect is tapered by distance. (Double check this code too)

User Event 0...

I would like if you guys can make suggestions on making this smoother.... And inspect the code a little...

Last edited by icuurd12b42 (2009-11-05 00:36:14)

Offline

#9 2009-11-05 08:41:34

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

That's really cool! The code was a little hard for me to follow at first (too much x, xx, xxx, xxxx for me). It seems to work pretty well already, although computing the field is quite slow at higher field densities. I like what is possible when md (max distance) is increased. Something I would certainly explore is using an inverse square drop off instead of the linear one you are using. That combined with "if (d<md)" are what make it discontinuous and blocky.

Can you tell me why I have to draw the model at -.5,-.5?

I don't know but it is the right thing to do. When I visualize my vector fields for those demos I posted, I can see that they aren't working quite as they should. When I draw the model at (-.5,-.5) like you have, the vectors match the flow correctly. I vaguely remember encountering this before. You can see in "Slippery Steps" where I've tried to compensate for it with "-size/2" in the field generator.

As for the reason, I'm pretty sure it has something to do with raster nature of the display memory and the vector nature of the GPU. Is a pixel centered on (0,0) or is that the pixel corner? I think there may be disagreement between different GPU operations.

A possibly related "problem" in GM6 may be with draw_rectangle. If not related, it at least illustrates some ambiguity in the way the GPU addresses pixels. In GM6 a rectangle will appear to have different dimensions depending on if it is drawn as an outline or not. When solid, the apparent dimensions decrease by one on both axes. This was changed in GM7 to more closely match the behavior of GM5, but I think the render problem of GM6 was expected behavior for GPUs. I've read a mathematical explanation as to why it works that way, but I don't remember the details or where I read it. I think lines and points are drawn using a nearest neighbor pixel selection, while solid shapes are draw up to, but excluding, bounding pixels to the right and below. For instance, a solid rectangle drawn from (0,0) to (10,10) would only fill pixels 0 through 9 on both axes. An outlined rectangle would draw pixels in rows 0 and 10 and columns 0 and 10.

Abusing forum power since 1986.

Offline

#10 2009-11-05 12:15:55

RaiSoleil
Member
Registered: 2009-08-02
Posts: 16

Re: UV Hijinks - Smoke and Mirrors

I noticed that "problem" too with triangles, but I think it's meant to do that, so that shapes will all mesh correctly. Otherwise, if you drew 2 triangles/rectangles that share a side and give them an alpha value, there would be one line between them that gets drawn over twice, which would look pretty wack. And then people would be even more confused.

Offline

#11 2009-11-05 17:59:11

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

I'm sure that's exactly the reasoning. It makes amazing tricks like this possible.

Abusing forum power since 1986.

Offline

#12 2009-11-05 19:00:08

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: UV Hijinks - Smoke and Mirrors

xot wrote:

That's really cool! The code was a little hard for me to follow at first (too much x, xx, xxx, xxxx for me). It seems to work pretty well already, although computing the field is quite slow at higher field densities. I like what is possible when md (max distance) is increased. Something I would certainly explore is using an inverse square drop off instead of the linear one you are using. That combined with "if (d<md)" are what make it discontinuous and blocky.

Yeah, sorry, I got a little anxious there, adding and adding variables until I got it to work. The if helps speed things up in the generation, to exclude model points too far from the spline points. Yes, I would like to use a log type method, but the distance covered my this method is rather large even though the effect is minimal at a distance. That means the if would be amost useless as the max distance would be very far away and every point of the cels would be involved in the generating of the dx dy. Slowing everything down in the editor. But I can give it a shot.

Can you suggest a proper method? For the math?

Offline

#13 2009-11-05 19:48:44

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

I do math like you do programming: adding and adding variables until I get it to work. I don't have the necessary education to advise. The way you are doing it is straight-forward and probably the way I would do it.

You might also want to experiment with template based deformation. It works kind of like a rubber stamp. The template might be a small disc of vectors indicating flow in a direction and fading off toward the edges. You iterate down the spline and stamp the template, which serves as a small local vector field, onto the main field using vector addition.  As you work you way down the spline, you select (or create) a template with vectors pointing in the correct direction and add it to the main field (and centered about the current point on the spline). These templates can be precomputed for a number of different angles.

To implement for speed, use grid data structures. You need a U and a V grid for each of your templates and the main field. Use ds_grid_add_grid_region() to add a templates to the main field. The advantage of the grid functions is doing the all of the math in only one function call per axis per template. You can use that and other ds_grid functions to create a lerp-like function to blend two templates together, perhaps to approximate an angle that hasn't been precomputed.

Abusing forum power since 1986.

Offline

#14 2009-11-05 22:15:37

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Here's an example that uses ds_grid math in a similar way. I use it here to make the pixels of a sprite explode (or implode). If the chunk size is kept large (3+ pixels), the effect is pretty fast.

A nice way to augment the explosion for a plume-like effect with gravity is to create the random vectors like this:

//  replace dx and dy code in sprite_plode_start
dx = lengthdir_x(random(argument1),random(90)+45);
dy = lengthdir_y(random(argument1),random(90)+45);

... and for gravity execute this each step:

//  add to end of sprite_plode_step
var grav; grav = 0.05; // gravity for effect
ds_grid_add_region(idvy,0,0,w-1,h-1,grav);

You don't strictly need the gravity code. You could make the instance fall using GM's built-in physics to achieve the same effect.

Abusing forum power since 1986.

Offline

#15 2009-11-07 00:38:22

~Dannyboy~
~hoqhuue(|~
From: Melbourne, Australia
Registered: 2009-10-02
Posts: 21
Website

Re: UV Hijinks - Smoke and Mirrors

Wow! Some truly marvellous effects! There's much to be learnt from this, I'll study it some more after exams Thanks for sharing

Offline

#16 2009-11-21 17:40:59

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: UV Hijinks - Smoke and Mirrors

Here is a flowing river, it's not a texture feedback method, it makes a series of models.

http://gmc.yoyogames.com/index.php?showtopic=454499

that textrue_set_repeat is a pretty nifty trick. I think it should be on on default. I went to so much extreme in GMModelEx.dll to fix UV that repeated.... Still dont have it right. When all along the feature was right in there.

Last edited by icuurd12b42 (2009-11-21 17:41:50)

Offline

#17 2009-11-22 17:14:23

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Awesome effect! That looks like it could be really useful for a lot of people. Great work with the presentation, too. Beautiful stuff.

Abusing forum power since 1986.

Offline

#18 2009-11-22 19:15:42

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: UV Hijinks - Smoke and Mirrors

This is some great stuff you guys have here. Too much for me though. I really cannot handle all this stuff haha. Well good job, this is all I can say.

Offline

#19 2009-11-23 03:31:15

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: UV Hijinks - Smoke and Mirrors

xot wrote:

Awesome effect! That looks like it could be really useful for a lot of people. Great work with the presentation, too. Beautiful stuff.

Check the update!! Top down and platform water added as well as model saving. I love this method. I even figured how to make wave form generator and have then cause interference on the water.

Offline

#20 2009-11-23 05:51:25

xot
Registered: 2007-08-18
Posts: 1,201

Re: UV Hijinks - Smoke and Mirrors

Wow, great updates! The transparency trick for the platform version is pretty clever and looks good. You just have to be careful with multiple wave sources since certain interference patterns cause globs of water to leap from the surface. I think a useful feature would be to be able to define waves with amplitude and frequency. I can see that frequency differences could be a problem since to loop correctly everything has to change phase at the same rate. That said, frequencies that are integer multiples of each other could work together. Amplitude control is my main desire as I write this.

Abusing forum power since 1986.

Offline