Apply shader to group or layer of objects

About Monkey 2 Forums Monkey 2 Programming Help Apply shader to group or layer of objects

This topic contains 11 replies, has 4 voices, and was last updated by  Anatol 1 year, 5 months ago.

Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • #11306

    Anatol
    Participant

    Hi!

    I’m still getting my head around everything Monkey2, so I guess I’m just asking for some hints here.

    What I have in mind is to apply a custom shader to a group of objects, or more specifically I’d like to apply a mask as in this post to an entire Pyro2 layer. This is for a 2D project.

    I can see how to apply a shader to an image from the excellent post above, but looking into the mojo Image module I fail to see how it is applied. Or is this somehow where the magic happens? https://github.com/blitz-research/monkey2/blob/e37b2442fc24eb7babbd8739c9767cd486cc06c1/modules/mojo/graphics/image.monkey2#L547

    Also, it doesn’t have to be the Pyro2 Layer, if I can apply it to any group or somehow tell Monkey2 to start using shader now, and stop it after rendering a number of objects (images, shapes) that’d also work.

    I’m not even sure if what I have in mind is possible or if I’m on the right track with my thinking, so any pointers in the right direction would be much appreciated.

    #11309

    Mark Sibly
    Keymaster

    Hi,

    There’s no easy way to do this currently as an image’s shader cannot be overridden.

    An image’s shader is ‘applied’ via the DrawOp system in canvas. If you look at the code for DrawImage in canvas.monkey2, this line is where the ‘magic’ happens:

    It would not actually be hard to add something like a ‘ImageShader” property to Canvas which could be used to override this image.Shader shader if non-null. It could also override point, line,shape shaders too (so ImageShader may not be best name).

    This already kind of happens with Canvas.BlendMode which actually overrides Image.BlendMode if non-null.

    There would be no way to provide global shader params that would affect *all* drawn images, but if you can live with that I would be OK with adding some sort of ‘global’ shader override to Canvas.

    #11314

    Anatol
    Participant

    Hi Mark, thanks for your reply and insight.

    If this could be done relatively easily I’d appreciate a canvas shader override.

    I still need to fully understand how this all works, but this is a really helpful reply. I think with the override it can get me there with some trial end error.

    #11316

    abakobo
    Participant

    I would be OK with adding some sort of ‘global’ shader override to Canvas.

    For me everything that allows us to play nicely with custom glsl shaders is good to take!

    #11318

    Dima
    Participant

    Hi Mark,

    Am I misunderstanding your above message that shaders cannot be overridden?  Following code seems to work both ways.  TIA.

    #11319

    Mark Sibly
    Keymaster

    I *think* what Anatol is after is something like…

    …so if you set canvas.Shader to a non-null value, you can draw a bunch of stuff using a single shader regardless of each image’s Image.Shader. I can see this being useful for multipass techniques.

    This actually kind of mirrors the Canvas.Blend property which overrides Image.Blend if non-null.

    It also provides a way to set the shader used for points, lines, polys etc.

    Is this right Anatol?

    #11325

    Anatol
    Participant

    Hi Mark, yes, that’s about what I had in mind. So one shader that applies to multiple things. If the usage would be as you’ve shown in your sample code that’d be nice and easy to apply.

    Even better if, as you mentioned, it could be applied to drawn shapes, not just bitmaps.

    #11330

    Dima
    Participant

    Could you reimplement default behavior in custom shader, then control which effect via uniforms?  Or maybe use intermediate render targets per effect with default images?

    #11470

    Anatol
    Participant

    Sorry, I’m just coming back to this. So it appears that at the moment shaders can only be used for images, is that right? I tried to apply a shader by looping through all shapes that I’ve drawn, but they don’t have a Shader property. I just thought I can use something like that as a temporary solution until (fingers crossed) Mark’s suggestion above would be implemented. But maybe I need to put shaders aside until a later version of Monkey2.

    Mark, is it helpful to put this into Github as an “issue” (labelled as an enhancement)? Thank you!

    #11532

    Anatol
    Participant

    Just a brief update, I actually got this to work and could apply a shader (a mask in this case) to a number of drawn shapes. This was possible in the current Monkey2 with a combination of the following:

    • a glsl shader (sprite-masked) from this related thread (a mask glsl shader is linked there as part of the zip file)
    • a MaskedImage Image extension, however with slightly modified code to the one in the link above to take a pixmap instead of an image path
    • a new canvas that renders to that MaskedImage above (see also the rendertoimage banana)
    • a bunch of randomly generated shapes that are drawn onto that new canvas

    I can animate the shapes and the mask independently and it works very well. I’m not sure if this is very efficient performance wise but for now at least it works as intended.

    I’ll see if I can write an isolated sample code to share here. So far I still don’t understand this 100% and it’s surrounded by a bit of convoluted work in progress, but I’m glad I got it working. Thanks to everyone who gave me the hints to get there. I’ll follow up.

    Having said that, a way as suggested by Mark above would still be great.

    #11534

    Mark Sibly
    Keymaster

    I did have a look into this andit’s doable but a bit complicated to make ‘nice’.

    Just to clarify though, are you only wanting to apply a shader to a bunch of shapes? This is easier…

    #11553

    Anatol
    Participant

    Hi Mark. In this case I’m thinking of “layers” (conceptually). So I have a number of things (shapes, possibly bitmaps, etc.) in a “layer” (i.e. somehow grouped), and I want to apply a shader to this layer/group. I’ll eventually end up with probably 3–4 “layers” total that each have a different (yet very simple) shader applied. I need to test if this is too expensive performance-wise, and what’s the best way to do this to avoid drawing everything onto the layer each frame. But that’s a different issue.

    I think the way to just draw the shapes/bitmaps that I need to a canvas, render that canvas onto an image and apply a shader to that image is working well. It’s great to discover the flexibility that Monkey2 already provides.

    If it works in practice for my game remains to be seen, but I’m on the right track.

Viewing 12 posts - 1 through 12 (of 12 total)

You must be logged in to reply to this topic.