Shading sprites based on sprite Y

  • Can’t use UVs because they are not in local space but relative to the entire atlas texture
  • Sprites can’t use local vertex space only models can?
  • GLES version does not support the function required to turn world into local?

I want to make shaders which can impact sprites directionally without needing to isolate them in a power of 2 atlas / use a mesh instead of a normal sprite component.

3 Likes

I am not sure but:

  1. I see that in a material there is the choice for local / world vertex coordinates
  2. from local to world you just need to multiply by a matrix and GLES can of course do this
  3. To go from local space to screen space you need the world, view and projection matrix composed (multiplied) together. I think you have them as vertex constants (two of them already multiplied). I don’t remember exactly the order of multiplication (Perhaps view * proj * world * vertex ??? but I am not sure).

If you still need help I may try to write the shader in details. Just let me know.

Ciao!

1 Like

This only works for models it seems, not for sprites.

If you still need help I may try to write the shader in details.

Please try! Maybe there is a way.

1 Like
  1. No local vertex for sprite
  2. GLES2.0 cannot do matrix inverse, you need the inverse of the world_matrix to go from world to local
  3. The inverse of a 4x4 matrix is expensive to do per-vertex

BUT, if you are just doing 2D, I would say that the world matrix should be of this form

a b 0 u
c d 0 v
0 0 e w
0 0 0 1

where

  1. the 2x2 submatrix with a,b,c,d takes into account rotations and scaling for x,y and e is for z-scale
  2. u, v, w are the traslation.

If so then the inverse of this type of matrix may be reasonably computed. WARNING: I am not sure if we need this matrix of its transpose (I don’t remember and it depends if the system uses row-vectors or col-vectors).

Still interested in this poor-man 2D shader? :rofl:

1 Like

There is a big problem!

The engine is precomputing the world * vertex and is passing world = identity to the shader. This is useful for batching sprites… and prevents the computation I was outlining above…

I have to think about this, probably it is not possible.

1 Like

Is there any special condition in your use case? something we may assume about the sprite? Let me say something stupid: if you don’t need alpha then you may use the alpha channel to bake in the sprite the Y coordinate; then it is obvious to use it in the shader…

That would be neat to try for some effects but for general purpose shaders you want to be able to use alpha.

I don’t know of a real solution, but maybe we could get a new sprite component / a checkbox that gives more freedom with those sprites but doesn’t work in batching.

1 Like

Maybe you may use two sprites: one with the normal sprite and another one with just the alpha to draw the fill of the sprite and the Y coordinate baked in the red channel. Of course this costs you two sprites.

If your effect is some kind of add-a-color or multiply-by-a-color then this should work.

1 Like

That certainly would be useful for some types of effects.

What I’m wanting to make right now is a top down dissolve of a sprite.

1 Like

Of course the local uv coordinate in the material is the right solution. Maybe it is not hard to add it to the engine. (I would guess so)

1 Like

What you want is not possible with the 2-sprites solution… You really need the local uv-coordinates.

1 Like

Local uv-coordinates or, better, multitexture for sprite.

1 Like

Does your sprite rotate? If not then you may pass the center position as a user-data constant and compute the local uv. But this breaks the batching of the sprites…

I am sorry for the multiple answers, I am looking for some solution and writing as I think :slight_smile:

2 Likes

If not then you may pass the center position as a user-data constant and compute the local uv.

I don’t know if this is possible because of the way atlases are composed and the lack of access to that info at runtime?

No, I mean the central position of the sprite on screen, not the central uv.

If the sprite does NOT rotate then you may compute the local uv from the vertex position

1 Like

If you can, please share an example of doing that!

Tomorrow I will write the shader for sure. Now going to sleep… :slight_smile:

1 Like
  1. Hopefully, in the future we have the ability to let the user set the vertex formatfor sprites (and others), just like they can do with meshes.
    I don’t think we’ll add an extra set of uv’s as default though, since most users don’t need it.

  2. This was something we said “we’ll add it later if it’s needed”, when introducing the notion of local space coordinates. The reason for that is that it will break the batching and create a unique drawcall for each such sprite. Probably not what you want here either.

  3. Since iOS is supporting Metal now (via our VUlkan backend) and the number of OpenGLES2 on Android is down to 10% (link) we’re looking into updating to OpenGLES 3.
    This, for instance, would allow you to use e.g. gl_VertexID to figure out your local uvs (if you’ve turned off sprite trimming so each sprite is 4 vertices).

Between these, I’d say the #3 is pretty close on the horizon and we’ll start working on it this spring.

9 Likes

What would happen to the web target? I seem to remember that GLES3 works only with Webgl2, which doesn’t work too well in mobile browser especially.

It’s part of what needs to be decided in the design phase.
But in short, you cannot have both OpenGLES 2 and 3 features in the same shader and expect it to work. You will have to make an active choice of what platforms you support.
E.g. you could opt to support WebGL2, but then only a few browsers would support it.