2D pixelated grass waving shader

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

No disrespect intended to @Pawel @sergey.lerg who are of course the undisputed kings of shaders :face_with_hand_over_mouth:

4 Likes

I’m a king of shaders like BK is king of burgers :joy: very interesting idea however, amazing how seamless it is with this approach!

4 Likes

I have been trying to create a simple 2D swaying shader and I think I may have done it. Lol.
Git it a try. It might do the job…

– Vertex program

attribute mediump vec4 position;
attribute mediump vec2 texcoord0;

uniform mediump mat4 mtx_view;
uniform mediump mat4 mtx_proj;

uniform mediump vec4 time;
uniform mediump vec4 speed;
uniform mediump vec4 intensity;

varying mediump vec2 var_texcoord0;

void main() {
    var_texcoord0 = texcoord0;
    vec4 p = position;

    p.x += 10.0 * (sin(speed.x * time.x) + cos(speed.x * time.x)) * intensity.x * max(0.0, texcoord0.y);
    gl_Position = mtx_proj * mtx_view * p;
}    

– Script

go.property("speed", 1.0)
go.property("intensity", 1.6)

function init(self)
	-- Time variable
	self.time = 0
	-- Start the randomizer
	math.randomseed(os.time())

	-- Values to pass along to the VP shader
	self.intensity = (self.intensity == 0 and 1.0 or self.intensity)
	self.speed = (self.speed == 0 and 1.0 or self.speed)
	--
	sprite.set_constant("#sprite", "intensity", vmath.vector4(self.intensity))
	sprite.set_constant("#sprite", "speed", vmath.vector4(self.speed, 0, 0, 0))
end


function update(self, dt)

	self.time = self.time +  dt 
	print ("Time: ", self.time)

	-- Send time to the VP shader
	sprite.set_constant("#sprite", "time", vmath.vector4(self.time, 0, 0, 0))
end
3 Likes

Bah! It needs to be better! Working on it

What does it look like? Can you share a video?

Will put something up tomorrow. Saw this too late. :frowning:

This is one of the shaders I am working on and I cannot get the “crease” or the bend out from the center.

– flip.vp, sprite.fp

attribute mediump vec4 position;
attribute mediump vec2 texcoord0;

uniform mediump mat4 view_proj;
uniform mediump vec4 time;

varying mediump vec2 var_texcoord0;

lowp float speed = 4;

void main() {
    var_texcoord0 = texcoord0;
    vec4 p = position;
    vec2 uv = texcoord0;
    float y = time.x;

    // SOOOOO CLOSE, I think :(
    gl_Position = view_proj * p * vec4(cos(y), 1.0 - (uv.y) * uv.x * (sin(y) *.5) , 1.0, 1.0);

}    

2 Likes

Howdy!

I have gotten my shader to a decent state, but now I am stuck with z positioning issues in the GUI. :frowning: I am posting the source here in case anyone wants to see if they can fix it or come up with a better way. Until then, I cannot attach child nodes properly…


GUI_ShaderTest.zip (328.0 KB)

Why shader and not rendering them with a perspective projection and simply rotating the game object?

2 Likes

I actually have in my game a perspective camera for this, but I was trying to learn how to do things in glsl. :grin:

1 Like

I was also trying to figure a way to create a perspective cam for GUI where the node positions are respected in 2D space just as the Orthographic cam does but still allow perspective. I really wanted to implement fisheye correction too, if possible. I used to have to do that with my old DOS raycaster engines.

1 Like