PDA

View Full Version : Make swinging 2D grass with shaders



DuffCola
01-14-2015, 11:01 AM
Hello,
I am pretty new to shaders thats why I am don't know how to begin making such a shader.
First of all the situation.
I have this small(In this example only 2 x 2) tile map, where each tile/quad has his own vertices, with a 2-dimensional position and uv coordinates.
1592
(The red rectangles marks the vertices, that have in real the same position, I only draw it on the picture side by side to demonstrate, that the tiles/quads don't use the same vertex)

I want that the yellow vertices are slowly move a little bit to the right than back and the same to the other direction so the texture is stretched and for example a grass texture would look like it's swinging.
The green vertices should not move, they simply should stay where they are.
Now I am wondering me how I know in the vertex shader that the current vertex should move or not?
Must I give every vertex a additional attribut so I could read in the shader whether the vertex should move or not ?

Can someone help me, or is that a wrong approach/is there a better way ?

GClements
01-14-2015, 05:26 PM
Now I am wondering me how I know in the vertex shader that the current vertex should move or not?
Must I give every vertex a additional attribut so I could read in the shader whether the vertex should move or not ?

The vertex shader only sees individual vertices, not the primitive of which they are a part or the vertex' relation to it (it's common for a single vertex to be part of multiple primitives).

In some cases, you may be able to use gl_VertexID to infer additional details about the vertex being processed. Otherwise, you'll need to use an attribute.

JuanChopmon
01-25-2015, 03:05 PM
One very cheap way I achieve grass animation is by making some assumption about the alignment of the texture.

This may not be the same in your case however you can adjust values appropriately.

Assuming that the grass texture is created in such a way that the base of the grass texture is along the bottom edge of the texture. Using this assumption, we can take the vertex information we have for that vertex's Texture coordinate and use that as a ratio between transformed animated offset and original position.

In this case, if we assume the base UV coordinate is v=1.0, we can first generate a random offset vector to modify our models position (This can either be done in model space of world space, it doesn't necessarily matter.)

example:

if we have these 3 uniform variables:



// Input variables
uniform float time; // A constantly increasing/changing time value which we can use to create difference over time.
uniform float random; // a random value in case you want to change the "start point" of the animation for different objects.
uniform Intensity; // wind strength essentially



We can then generate an offset value using some simple trigonometrical functions:



vec3 offset = vec3( Intensity * (cos( time/1.5 ) * (1.0 - TextureCoord.y)) * sin( in_Position.x + random ),
0.25 * sin( 1.5*in_Position.x + 2.0*in_Position.z )* (1.0 - in_TextureCoord.y),
Intensity * (cos( time/2.0 ) * (1.0 - TextureCoord.y)) * sin( in_Position.z + 2.0*random),
);


Modifying the up-component of the data is optional, by default this can be 0, however having some basic random function can be used to improve the visuals of the grass by adding modifications to the height. This will need to be adjusted to the scale of your game if you do use it.

Finally, you simply add the offset onto the position:



vec4 object_space_pos = vec4( in_Position.x + offset.x, in_Position.y + offset.y, in_Position.z + offset.z + offset.x/5.0 + offset.y/2.0, 1.0);


( I also added the offset x and y to the z to create a little more variation in animation. )

The important part of code here is the fact that the offset is multiplied by 1.0-TextureCoord.y. What this does is it makes the offset fully effective at the point where the v coordinate is 0, (i.e at the top of grass), but makes it ineffective at the base of grass where TextureCoord.y = 1.0. This is a really nice way of creating quick and easy grass animation off simple data.

Trig functions are used to make a somewhat natural looking oscillation. The current model space position is used as an offset (realistically, you would probably want to use a world-space offset here then add this onto the world space coordinate after it has been calculated.) As the time value increases inside your program, the grass will oscillate.

In its current form, this will create a relatively simple form of animation. You can make the animation more complex by introducing additional trig functions, and perhaps rotating the offset such to apply it in the direction of the wind, however this is a little trickier. This works very nicely for basic grass animation in light breezes.