Set sprite as one solid colour (without shaders)

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

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.

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

jgodfrey | 2020-05-29 16:43

:bust_in_silhouette: Reply From: njamster

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)

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?

Ron0Studios | 2020-05-29 12:26

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

njamster | 2020-05-29 12:48

:bust_in_silhouette: Reply From: whiteshampoo

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…

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));

whiteshampoo | 2020-05-29 17:34