+1 vote

Hello There,
I have been working on a game project for quite a while now. There is a character that can dash (fast) in the game and I want to provide some player feedback upon dashing. So I followed (this) tutorial on creating a ghost effect when somebody dashes. So I modified the tutorial so you can have the "ghost" have a solid colour that tweens to alpha over time. Previously I have been using shaders to implement a solid colour. Here is the code:

shader_type canvas_item;

uniform vec4 colour : hint_color;
uniform bool active;
void fragment() {
    if(active == true) {

        vec4 curr_color = texture(TEXTURE,UV); // Get current color of pixel

        if (curr_color.a == 1.0f){
            COLOR.rgb = colour.rgb;//vec3(0.238, 0.118, 0.418);
        }else{
            COLOR = curr_color;
        }
    }
    else{
        COLOR = texture(TEXTURE,UV);
    }
}

This did the job well for a long time, but I noticed a performance issue. Upon the first dash, the player would get a very large lag spike, but afterwards, there was no lag from dashing at all. At first, I thought this was due to loading the resources, so I tried using preload() functions or instancing at different points, but nothing seemed to work. Later on, I found out that it was due to the fact that shaders were lazily compiled in-game, so when an object is instanced for the first time, there would be massive game lag. Are there any solutions to having a sprite with a solid colour fill in GDscript without using any materials or shaders?
Thanks,

PS. I don't think modulate or self modulate works. It doesn't give a solid fill colour.

asked May 29 in Projects by Ron0Studios (21 points)

Maybe I'm missing the point, but why not just provide a solid color version of the sprite for use in the dash feature?

2 Answers

0 votes

I don't think modulate or self modulate works. It doesn't give a solid fill colour.

You can modulate with raw color values above one, e.g.:

extends Sprite

func _ready():
    self.modulate = Color(0.0, 100.0, 0.0, 1.0)
answered May 29 by njamster (8,986 points)

this does not work sadly, since you can still differentiate between bright and dark colours. Perhaps I may need to test this with an absurdly higher value?

Yeah, you're right, it seems to only work well for certain textures. :(

0 votes

If-Else can cause performance-issues in shaders.
I simplified the shader a "little" bit.

shader_type canvas_item;

uniform vec4 color : hint_color;
uniform float mixture;

void fragment() 
{
    COLOR = texture(TEXTURE, UV);
    COLOR.rgb = mix(COLOR.rgb, color.rgb, mixture);
}

use mixture like active, but with floating values.
0.0 = texture
1.0 = solid color

please tell me if this works.

EDIT:
I simplified the "outline"-effect away. If you need it, i'm sure i find a way to implement this without if/else...

answered May 29 by whiteshampoo (976 points)
edited May 29 by whiteshampoo
shader_type canvas_item;

uniform vec4 color : hint_color;
uniform float mixture;

void fragment() 
{
    vec4 tex = texture(TEXTURE, UV);
    COLOR.a = tex.a;
    COLOR.rgb = mix(tex.rgb, color.rgb, mixture);
    COLOR.rgb = mix(tex.rgb, COLOR.rgb, floor(tex.a));
}

This should also do the "alpha-outline"

I don't know why it has a sharp egde at the "alpha-border".
I think it would look much better with:

COLOR.rgb = mix(tex.rgb, COLOR.rgb, tex.a);

or

COLOR.rgb = mix(tex.rgb, COLOR.rgb, smoothstep(tex.a));
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.