How to do a projective transformation/equivalent of CSS matrix3d?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
jackmcbarn
Newbie
Posts: 7
Joined: Wed Feb 24, 2016 3:56 pm
Github: jackmcbarn
Contact:

How to do a projective transformation/equivalent of CSS matrix3d?

#1 Post by jackmcbarn »

How do I do a projective transformation like this in Ren'Py? https://franklinta.com/2014/09/08/compu ... ransforms/ In words, I'm trying to squish a rectangle into an arbitrary quadrilateral. In CSS, it can be done by passing an appropriate matrix to the matrix3d transform. I looked through https://www.renpy.org/doc/html/atl.html ... properties but none of them looked relevant.

User avatar
gas
Miko-Class Veteran
Posts: 842
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#2 Post by gas »

(Today I'm Mister Not-at-all)

Hi, HTML5 offer 3d high level functions that are not part of PyGame, and renpy use PyGame. So, in a word, go search around how to skew images in pygame and create a CDD that skew the image (see docs).
If this sound aramaic to you, you're trying to do something way from your reach and, as long as you don't want to show thousands of pictures this way, you can simply draw them skewed already.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#3 Post by Remix »

In the coming Ren'Py 7.4 the pipeline has been rewritten to use GL2 and allows use of GLSL shaders (though they do require a lot of high level understanding) and mesh manipulation which would cover your needs.
At the moment though, most Ren'Py developers are not familiar with the system so there are no good examples of ways to approach this.
(there will be though, as the system is so powerful and the potential is endless)

Currently you could do non skewing stuff in ATL though using zoom and rotate (as detailed around here):
https://renpy.org/doc/html/atl.html#int ... -statement
Frameworks & Scriptlets:

jackmcbarn
Newbie
Posts: 7
Joined: Wed Feb 24, 2016 3:56 pm
Github: jackmcbarn
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#4 Post by jackmcbarn »

Remix wrote: Sun Dec 06, 2020 6:05 am In the coming Ren'Py 7.4 the pipeline has been rewritten to use GL2 and allows use of GLSL shaders (though they do require a lot of high level understanding) and mesh manipulation which would cover your needs.
At the moment though, most Ren'Py developers are not familiar with the system so there are no good examples of ways to approach this.
(there will be though, as the system is so powerful and the potential is endless)
This looks like almost exactly what I need. I made a vertex shader that just multiplied gl_Position by my matrix, and it rendered exactly the way I want. The only problem is that this doesn't affect mouse events, so to click buttons transformed with it, I need to click where they would have been drawn without the transformation, rather than where they actually are drawn. I think this is fixable with a creator-defined displayable that does the inverse transformation in event(). In the ideal world, though, Ren'Py would just use homogeneous coordinates for its existing transformations instead of Cartesian coordinates, and then this kind of matrix would "just work" without the game needing all this custom code.

(Side note: if I do get this working, I'll post a demo script file here.)

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#5 Post by Remix »

jackmcbarn wrote: Sun Dec 06, 2020 7:44 pm This looks like almost exactly what I need. I made a vertex shader that just multiplied gl_Position by my matrix, and it rendered exactly the way I want. The only problem is that this doesn't affect mouse events, so to click buttons transformed with it, I need to click where they would have been drawn without the transformation, rather than where they actually are drawn. I think this is fixable with a creator-defined displayable that does the inverse transformation in event(). In the ideal world, though, Ren'Py would just use homogeneous coordinates for its existing transformations instead of Cartesian coordinates, and then this kind of matrix would "just work" without the game needing all this custom code.

(Side note: if I do get this working, I'll post a demo script file here.)
The crux is that shaders only operate on the GPU so Ren'Py cannot read back the shaded image to use as an alpha mask... To Ren'Py the image is just an unshaded flat rectangle.

If you are okay calculating the click area with math and time you could set alpha_mask to be a Python function and only return True at positions where your math says the shaded image would be opaque.
Frameworks & Scriptlets:

jackmcbarn
Newbie
Posts: 7
Joined: Wed Feb 24, 2016 3:56 pm
Github: jackmcbarn
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#6 Post by jackmcbarn »

Remix wrote: Mon Dec 07, 2020 1:32 pm If you are okay calculating the click area with math and time you could set alpha_mask to be a Python function and only return True at positions where your math says the shaded image would be opaque.
Doesn't this only work if my projection draws the image in a subset of its original location? If the button gets drawn outside of its original bounds, won't alpha_mask not even get looked at?

User avatar
gas
Miko-Class Veteran
Posts: 842
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#7 Post by gas »

I think alpha mask should be intended as focus_mask.
https://www.renpy.org/doc/html/style_pr ... focus_mask

You should pass a displayable/self (but the GPU morphed the pixels later in the pipeline and so goodbye the original alpha channel as focus mask) or a function, to determine the sensible area.
If you want to debate on a reply I gave to your posts, please QUOTE ME or i'll not be notified about. << now red so probably you'll see it.

10 ? "RENPY"
20 GOTO 10

RUN

jackmcbarn
Newbie
Posts: 7
Joined: Wed Feb 24, 2016 3:56 pm
Github: jackmcbarn
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#8 Post by jackmcbarn »

gas wrote: Mon Dec 07, 2020 3:19 pm I think alpha mask should be intended as focus_mask.
https://www.renpy.org/doc/html/style_pr ... focus_mask

You should pass a displayable/self (but the GPU morphed the pixels later in the pipeline and so goodbye the original alpha channel as focus mask) or a function, to determine the sensible area.
Indeed, but now another issue comes up: This approach only works if I'm transforming the button directly. If I'm transforming a grid with a bunch of buttons in it, then it looks like I am back to needing a CDD to do it.

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: How to do a projective transformation/equivalent of CSS matrix3d?

#9 Post by Remix »

Yup, I meant focus_mask, oops.

If, when shaded, they go outside of the bounds of the original image areas, I think you would be looking at a CDD (or extend Container, from renpy/display/layout.py and tweak the event method there)
Frameworks & Scriptlets:

Post Reply

Who is online

Users browsing this forum: No registered users