2D pixelated grass waving shader

What do you mean by this?

Tint value can mess up the alpha channel, do you have it set? Try removing tint from the shader.

Removed, still transparent :confounded:

I mean, that the model with the texture is transparent and you can see sprites and tiles behind it, as on the gif above.

Check the image alpha channel?

Do you mean e.g. the .png file? I tried with different images, but the effect is the same for each :frowning: In the gif above, there is a static version of just a sprite with the same image and it’s not as transparent as that on the model.

Does the tint of the sprite have an alpha of less than 1? Try copying the sprite shader and remove the tint and see if it works better. If not, output the texture alpha as color from the shader and see if it’s not full white: i.e something like gl_FragColor = vec4(color_sample.aaa,1.0);

1 Like

My waving.fp (fp of the model with the texture - grass.png) is just like that:

varying highp vec4 var_position;
varying mediump vec3 var_normal;
varying mediump vec2 var_texcoord0;
varying mediump vec4 var_light;

uniform lowp sampler2D tex0;

void main()
{
    vec4 color = texture2D(tex0, var_texcoord0.xy); //* tint_pm;
    gl_FragColor = vec4(color.xyz,1.0); //color //vec4(color.rgb*diff_light,1.0);
}

As you can see I tried with just the xyz from the collor and a constant alpha, but the result is even worse (black pixels + transparent color pixels) :slight_smile:
image

So it must be drawn on something with another fp, maybe?

Is it maybe possible without model, but on a sprite? (I’m not sure about vp)

Maybe it’s not the model that is translucent, but the image behind it? And grass is actually under the sprite? Do you have special blending mode for the sprites?

I’m getting back to this, I have another issue - the waving speed is dependent on what is happening on the screen :confused: I mean, e.g. when I jump it starts to wave faster, when the camera moves it starts to wave faster :confused: @sergey.lerg I’ve noticed that you are passing time to the vp from render script, but it is update in camera library (self.time.x = camera.time) while I have just a script that seems to have significantly variable dt:

function init(self)
	self.time = 0
end

function update(self, dt)
	self.time = self.time + dt
	model.set_constant("#model", "time", vmath.vector4(self.time, 0,0,0))
end

What can I do to avoid such changes in waving?

1 Like

What do you have in project settings regarding variable dt an vsync?

And its better to pass time in render script using constants in draw().

1 Like

I tried with vsync turned on and off - no difference. I checked also changing Frame Cap as provided here. All of the combinations didn’t changed anything

Hm, I don’t have a variable dt setting in game.project. As I saw in the documentation it’s deprecated.

Huh. Try printing dt in render script and in game object script? See any pattern maybe.

1 Like

Yeah! I found the bug! :smiley: The dt is constant. That was looking suspect, so I got back again to the vertex program and found out that I bounded y position with waving, so in case when I was jumping and the camera was moving along Y axis it was modyfing the waving frequency! :disappointed_relieved:

1 Like

That can be fixed with local space vertex coordinates in the material settings. You also have to use a different matrix in the vp.

wave.vp

attribute mediump vec4 position;
attribute mediump vec2 texcoord0;

uniform mediump mat4 mtx_view;
uniform mediump mat4 mtx_proj;
uniform mediump mat4 mtx_worldview;

uniform mediump vec4 time;

varying mediump vec2 var_texcoord0;
varying mediump vec4 var_position;

void main() {
	var_position = position;
	var_texcoord0 = texcoord0;
	vec4 p = position;
	p.y = p.y + 0.2 * sin(5.0 * time.x + p.x);
	gl_Position = mtx_proj * mtx_worldview * p;
}
4 Likes

Hi @Pawel, just to clarify, is this an fx applied to pixel art or is pixelation the result of some cool pixel shader?

Hello @SamsTheGreatest!
If you want to further pixelate the effect, I advise you to draw it on some render predicate and then use that data to pixelate it in a separate shader pass :slight_smile:
The above was about trying to do it on a single sprite (yes, it was pixel art before), with it’s vertex and fragment programs. Later on, during development of my game, I realized it is tedious and too much waste to wave every single sprite.

You can achieve it by cheating a bit - all the grass you can draw into separate predicate - then you add another pass with “wind” - air particles visualisation, that is not visible to player, but you have a data for shader using this to wave grass. At the end you can pixelate the result, to be pixel perfect, but for my game, where camera is moving it was a pain to make it right, without any stuttering so I resigned for now :wink:

I wish I had got in earlier on this conversation as I spent quite a lot of time looking into this recently.

I use a tile source to create many long thin slices and then some code animating tint and Y position. If you’re doing pixel art, you could very easily do this with hardly any slices at all.

3 Likes

In this case the bust is cut into slices and x and y scale and position are all animated. This bust is actually only cut up into 33 slices, so it’s really not intense at all for the processor.

3 Likes

@88.josh interesting! And I wonder if you could explain to me what exactly do you mean by “cutting into slices”?

Picture speaks a thousand words:

I was surprised by how effective this technique can be with so few slices. I can get this highly detailed image waving around with that psychedelic effect with just 33 separate tiles. If you’re doing something with pixel art, where definition is much lower (in terms of both number of pixels and colour/shading), it would be super simple to do without having to do shaders.

3 Likes