Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behaviour with shaders #19

Open
mikael-ros opened this issue Dec 30, 2024 · 15 comments
Open

Strange behaviour with shaders #19

mikael-ros opened this issue Dec 30, 2024 · 15 comments
Labels
bug Something isn't working

Comments

@mikael-ros
Copy link
Contributor

mikael-ros commented Dec 30, 2024

Hello! Love this project, great work :)

I have been trying to use jess::codes overlay shader on TileMapDual, but I've been struggling to make it work properly. Their shader works perfectly on everything but TileMapDual, and over the past couple weeks (when I've had time), I've been trying to make it work on TileMapDual without success.

When the shader is applied, it paints the entire tile even where transparent. I have tested it, and even if you simply just set the color to be whatever it sampled, it somehow manages to paint colors that aren't there. In the screenshot below, the mask color is a shade of gray. There should be transparency on certain pixels (compare with non-shaded texture).

image

Same area without shader applied:

image

Another example

image

Such is the case with any texture and any mask colors. The overlay in question is 128 x 128, and the tile size for the tilemap is 32 x 32 (128 x 128 for the whole tileset).

Unfortunately, I lack the shader knowledge required to fully understand why it is the way it is, so I figured I'd open an issue and see if there's a known workaround, or if this is related to another issue. The effect reminds me slightly of #11.

My shader is slightly modified, mainly to test things out. It has been slightly expanded from the jess::codes example, to allow for arbitrary filtering colors.

// Based on jess::codes https://www.youtube.com/watch?v=eYlBociPwdw and https://www.youtube.com/watch?v=QB2o5Dys6Tc

shader_type canvas_item;

uniform sampler2D overlay: repeat_enable, filter_nearest;
uniform vec4 fg_color : source_color;
uniform vec4 bg_color : source_color;
uniform float tolerance : hint_range(0,1);

uniform float scale = 0.0078125; // calculated by 1/texture size e.g. 1/128
uniform float tile_size = 32.0;
varying vec2 world_position;

void vertex(){
    world_position = (MODEL_MATRIX * vec4(VERTEX, 0.0, tile_size)).xy;
}

void fragment() {
    vec4 curr_color = texture(TEXTURE, UV);
    float dist_bg = distance(curr_color.rgb, bg_color.rgb);

    if (dist_bg < tolerance) {
        discard;
    }

    vec2 local_position = mod(world_position, tile_size);

    vec4 overlay_color = texture(overlay, fract(local_position * scale));

    float dist_fg = distance(curr_color.rgb, fg_color.rgb);

    if (dist_fg < tolerance) {
        COLOR = overlay_color;
    }
}

Using Godot 4.3 Mono, on Arch Linux.

Minimal test setup:

  1. Create pixel-art according to the tile guide given. Leave some area within the used tile area transparent. Replace desired areas with mask colors (ex. red)
  2. Create a project
  3. Add a TileMapDual node, add tileset
  4. TileSet -> Select -> Select all tiles -> Set Material to "new ShaderMaterial" -> create "new Shader" -> Edit -> Paste code from above
  5. In Shader properties, set foreground filter (if any, you can leave transparent too) and background filter, as well as the texture, scale, e.t.c.

I apologize if this is a noob question / issue, and if it is unrelated to this project :o

The reason I believe it to be relevant is that the shader works just fine on any other node I've tried.

pablogila added a commit that referenced this issue Dec 31, 2024
@pablogila
Copy link
Owner

Hey there!
Thanks for the detailed report! :D

I suspect this is because materials apply to TileMapDual itself. But during execution TileMapDual hides itself, and what we see is TileMapDual.display_tilemap, which is essentially a displaced TileMapLayer with a copy of TileMapDual's tile_set.

I have uploaded a quick fix as tag v4.0.2-dev1. You can see there that it applies an exported material to display_tilemap in the _set_display_tilemap() function (line 120 of addons/TileMapDual/TileMapDual.gd). Please test it and check if it works for you.

Unfortunately my experience in shaders is none at all. If you have any other suggestion, I am all ears.

Cheers!

@mikael-ros
Copy link
Contributor Author

Thank you for the quick turnaround! :)

It fixed the issue, at least in runtime, which works well enough for me. See image:

image

Windows are slightly transparent due to my Linux compositor settings, so don't worry about that!

What I did:

  • Installed the new version by closing Godot, then removing the old folder and replacing it with the new version with the same folder name. This meant I didn't need to re-enable the plugin.
  • Removed the shader material from the tiles in the tileset
  • Added the shader to the TileMapDual with the material properties you added
  • Launched the game

Hopefully you can get it to work in the editor later, but for now I'm perfectly happy. Thank you!

Happy new year! You can close this issue if you feel satisfied with it only being in runtime

@mikael-ros
Copy link
Contributor Author

mikael-ros commented Dec 31, 2024

Actually, works in the editor now. Not sure why it wasn't before.

image

@mikael-ros
Copy link
Contributor Author

Another note. If Self Modulate is not made transparent, the shader still won't work. This seems to be a fairly common thing with color replacement shaders like mine however, but I figured I'd note that down were anyone to come across this in the future! :)

image

@pablogila
Copy link
Owner

Great! Please let me know how does the last commit work for you. If it works properly, I will probably delete the exported variables, so that shaders can be used as usual. Cheers!

@mikael-ros
Copy link
Contributor Author

What do you mean? I might be a little confused :o

My shader only works when using the exported variable at the moment (even with the current main branch from just 5 min ago). Setting the material in the usual material slot for the node doesn't work, nor does using the tilemap select :(

Tilemap select I'm referring to:
image

The usual slot:
image

Where I currently have the shader, the exported variables:
image

@mikael-ros
Copy link
Contributor Author

With the changes on the main branch, it is at least no longer necessary to set Self Modulate manually, so that's something :)

I also noticed that having self.material = null doesn't do anything, as far as I can gather?

# ...

# Make TileMapDual invisible without disabling it
#if not self.material:  # Let's remove the IF to try to solve #19
###self.material = null  # Apply comment HERE, line 125
self.self_modulate.a = 0.0
# Add the display TileMapLayer

# ...

pablogila added a commit that referenced this issue Jan 1, 2025
@pablogila
Copy link
Owner

First of all, happy new year!

Please let me know if the last commit works for you. I removed the exported variables, but in return the display tilemap should inherit all properties from DualTileMap directly, except for the alpha and the position of the tileset.

Cheers!

@mikael-ros
Copy link
Contributor Author

Happy new year :)

Thank you. I'll take a look tonight I think :)

@pablogila pablogila added the bug Something isn't working label Jan 2, 2025
mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 2, 2025
…ate = null. Cleanup of old comments

This should fix the issue in a minimal way. Hopefully it does not break other functionality.
@mikael-ros
Copy link
Contributor Author

mikael-ros commented Jan 2, 2025

It is now possible to load it in the material slot, but the bug has reappeared:
image

The transparancy on the window itself is still my Linux settings :O

After comparing commits, I found that it comes down to self.material no longer being set to null. This fixes the problem for me again. What I assume is happening is that both have the shader applied, so unless the "hidden" one isn't unrendered, the "hidden" tilemap is displayed below the displayed one. Any fix that properly prevents the "hidden" one from rendering will fix the issue, but I suspect simply setting self.material = null suffices unless it breaks other functionality I'm not aware of.

I have submitted a pull request with this fix, in addition to cleaning up some of the leftover comments from prior fixes to this section. I hope setting it to null doesn't break anything.

Thank you for the quick turnaround as always, man :)

image

@mikael-ros
Copy link
Contributor Author

Actually, this creates a new bug, where the material is unset after closing Godot. I'll try to see if there are other ways to prevent the rendering

mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 2, 2025
@mikael-ros
Copy link
Contributor Author

I have now attempted to address the new bug I ended up introducing. Read the PR for more details :)

mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 2, 2025
…ial = null. Cleanup of old comments

This should fix the issue in a minimal way. Hopefully it does not break other functionality.
mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 3, 2025
mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 4, 2025
mikael-ros added a commit to mikael-ros/TileMapDual that referenced this issue Jan 5, 2025
pablogila added a commit that referenced this issue Jan 5, 2025
Possible fix reimplementation for #19, by setting self.material = null
raffimolero added a commit that referenced this issue Jan 7, 2025
@raffimolero
Copy link
Collaborator

likely reintroduced in v5.0.0-dev: 289536a

I'm going to try and reproduce the issue first on my end before doing anything else though.

If the problem was in fact reintroduced, then we'd have to copy all relevant properties of the parent TileMapDual just like before.

@raffimolero raffimolero reopened this Jan 8, 2025
@mikael-ros
Copy link
Contributor Author

mikael-ros commented Jan 8, 2025

Everywhere I go, it haunts me

No, but just let me know if you need me to give any input 😅

@pablogila
Copy link
Owner

I would expect that copypasting the previous implementation of an exported material should work.

Sadly my laptop is still under maintenance, this is getting annoying at this point :/
I could try with Godot for Android but then I have no way of git'tin it...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants