Water reflection effect of multiple sprites with area 3D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Andrea

Hi everybody,
I’m trying to create a water reflection effect of a character that is composed by a bunch of sprites, i tried different options but i’m currently stuck. I need some ideas on how to solve this

1- being composed of many sprites that move relatively to each other, i cannot use a simple y-flipped sprite to achieve the effect.
2- for the same reason, i dont have a single texture to use for a shader
3- i tried using Viewport texture, but this requires the entire character to be in a viewport, which is not feasible as some sprite also have area2D as child (sword attack)
4- there are some tutorial online to achieve water reflection with shader, but they use the entire screen view as starting picture to mirror, while i need to mirror the character alone (it’s a top down RPG, not a side scralling game, i cant mirror the environment)

:bust_in_silhouette: Reply From: Drawsi

Try to use the Viewport texture only inside the character. That’s honestly my best idea, otherwise you would have to write a new shader from scratch

what do you mean?
my character scene is currently like this:

< Character (kinematic body)
<< CollisionShape
<< SpriteGroup(node2D)
<<< Body sprites
<<< Weapon sprites+area2D

where would you place the viewport?

by the way, i’m ok with writing a new shader, but from what i understood the shader require a starting point (being the texture of a sprite uising TEXTURE, or the viewport, using SCREEN_TEXTURE) that i dont know how to get.
Basically, i need somehow to get the pixel image of the sprite group alone, separated from the background/environment (this is why i tried to use viewport)

Andrea | 2021-03-09 21:00

Nodes have a property:
If you apply the shader on the character’s parent node and activate that property on all child nodes, the shader should work.
I did a little test, I have in the scene a node 2d with a child sprite, create a material shader in node 2d:

shader_type canvas_item;
void fragment () {
vec4 tex = texture (TEXTURE, UV);
tex.b = 0.0;
COLOR = tex;

And in the child sprite check use_parent_material. It works.

estebanmolca | 2021-03-09 22:49

Ok as I saw that my comment does not solve your problem, the configuration would have to be more or less like this:

┃ ┖╴Viewport
┃ ┠╴Sprite2
┃ ┖╴Sprite
The viewport would go in the position and size of your character psj, with transparent_bg set to on. As you can see, the viewport does not take the image of sprite3, in this sprite the texture of the viewport would go with the shader with the desired effect, and the position of sprite 3 would go under the character to simulate the reflection. The image is already inverted by default.

estebanmolca | 2021-03-09 23:48

(just to confirm, sprite 1 and 2 are children of the viewport, not siblings, right?)
Yeah this configuration is what I was referring to in point 3 of my original post.
I’m not sure it will work because area2d as child of the viewport will loose effect on the world (or this is what I think it would happen)
To use this configuration I should separate sprites from effect areas

Andrea | 2021-03-10 06:56

Yes, they are children. (I used print_tree_pretty () to print the tree but when I paste it here it doesn’t format well.)
I can’t tell you about the area2d. If you can explain a little better why areas2d would not work, I would appreciate it.
According to the documentation:

By default, newly created Viewports do not contain a World but use the same as their parent Viewport (the root Viewport always contains a World, which is the one objects are rendered to by default)

But I’m not sure if that’s what you mean.

estebanmolca | 2021-03-10 07:32

sorry, with “world” i meant the world physic state (position and shape of area 2D/collision body needed for physics and area detection). the “world” you mentioned from the doc is the one relative to WorldEnvironment node (lights, fog, sky, etcc)

for example: if you put a kinematic body inside a viewport, it will not interact with the physic bodies outside of the viewport, but it will interact with the other bodies in the viewport (tried right now)
effectively, each viewport create a parallel physic world

Andrea | 2021-03-10 13:18

Thanks for the explanation, after reading the documentation a bit I could see that the viewports have different word_2d (I’m talking about physical worlds):

print (get_viewport (). world_2d)
print ($ ViewportContainer / Viewport.world_2d)

I wanted to assign the one from the main scene to the custom but I came across this:
Viewport: Unable to use parent world as world_2d · Issue #31856 · godotengine/godot · GitHub

It seems that for now it is not the right way, if I find something useful I will let you know. I read something out there that a canvas layer could be used to separate the physical objects of the viewport but I didn’t really understand how to implement it.

estebanmolca | 2021-03-10 15:15