• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Is a Green Screen effect possible?

T

TheSecondGame

Guest
I was wondering if it was possible to implement a green screen effect on the transparent parts of a sprite.
Any help would be greatly appreciated.
:)

EDIT:
To clear up some confusion, I forgot to mention that I want the transparent parts to show a different background then the one directly under it.
What I'm going for is an unmoving plaid effect, like in this gif.

Chowderfinish.gif
 
Last edited by a moderator:
T

TheSecondGame

Guest
Do you mean drawing green where there is transparency?
Not exactly.
In films and TV, it's when a green background is used so that moving subjects are filmed. This allows a separately filmed background to be added to the final image.
It's what weather reporters use to show the weather behind them.
 

Mick

Member
Not exactly.
In films and TV, it's when a green background is used so that moving subjects are filmed. This allows a separately filmed background to be added to the final image.
It's what weather reporters use to show the weather behind them.
Yep, I know, so would you like to show video behind the sprites? Transparency otherwise in GMS works like you want it to, it isn't drawn at all.
 

Bingdom

Googledom
Here's a simple shader I wrote. ;)

Code:
// Simple passthrough fragment shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 Base =  v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = vec4( Base.r, 0.0, Base.b, Base.a*(1.0-Base.g));
}
Apply it to a sprite and it will make any green value transparent.

Edit:
This might give more accurate results.
Code:
// Simple passthrough fragment shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 Base = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    float _t = Base.r + Base.g + Base.b; //Total
    //float _r = Base.r / _t;
    float _g = Base.g / _t;
    //float _b = Base.b / _t;
    gl_FragColor = vec4( Base.r, 0.0, Base.b, Base.a*(1.0-_g));
}
 
Last edited:

NeoShade

Member
Your question doesn't really make any sense in relation to sprites.

In film and television, it's not possible to film something without also filming whatever it is that the thing is in front of, so we film things in front of a green screen that we can later delete.

In computer graphics, it IS possible to create a sprite without a background behind it, so there's literally no need to have a "green screen effect" because of the sprite has been made witha transparent background then there should be nothing to delete.
 
You mean just change the background behind the sprites? That's easy enough I will assume you didn't mean that.

Did you mean a green screen behind each sprite? Like a different one per sprite? Use draw > step and have something like:

Code:
draw_sprite_ext(green_screen, green_screen_index, x, y, image_xsclae, image_yscale, image_angle, green_screen_blend, green_screen_alpha)
draw_sprite_ext(sprite_index, image_index, x, y, image_xsclae, image_yscale, image_angle, image_blend, image_alpha)
 
T

TheSecondGame

Guest
Your question doesn't really make any sense in relation to sprites.

In film and television, it's not possible to film something without also filming whatever it is that the thing is in front of, so we film things in front of a green screen that we can later delete.

In computer graphics, it IS possible to create a sprite without a background behind it, so there's literally no need to have a "green screen effect" because of the sprite has been made witha transparent background then there should be nothing to delete.
Sorry, my question wasn't clear enough.
I forgot to mention that I want certain transparent parts of a sprite to show a different background then the one directly under it.
 
T

TheSecondGame

Guest
Yep, I know, so would you like to show video behind the sprites? Transparency otherwise in GMS works like you want it to, it isn't drawn at all.
My apologies, my question wasn't clear enough.
I forgot to mention that I want certain transparent parts of a sprite to show a different background then the one directly under it.
 
T

TheSecondGame

Guest
Here's a simple shader I wrote. ;)

Code:
// Simple passthrough fragment shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 Base =  v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor = vec4( Base.r, 0.0, Base.b, Base.a*(1.0-Base.g));
}
Apply it to a sprite and it will make any green value transparent.

Edit:
This might give more accurate results.
Code:
// Simple passthrough fragment shader
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 Base = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    float _t = Base.r + Base.g + Base.b; //Total
    //float _r = Base.r / _t;
    float _g = Base.g / _t;
    //float _b = Base.b / _t;
    gl_FragColor = vec4( Base.r, 0.0, Base.b, Base.a*(1.0-_g));
}
Thanks for this, but I'm afraid that I wasn't clear enough when I posted my question.
I forgot to mention that I want certain transparent parts of a sprite to show a different background then the one directly under it.
 
T

TheSecondGame

Guest
You mean just change the background behind the sprites? That's easy enough I will assume you didn't mean that.

Did you mean a green screen behind each sprite? Like a different one per sprite? Use draw > step and have something like:

Code:
draw_sprite_ext(green_screen, green_screen_index, x, y, image_xsclae, image_yscale, image_angle, green_screen_blend, green_screen_alpha)
draw_sprite_ext(sprite_index, image_index, x, y, image_xsclae, image_yscale, image_angle, image_blend, image_alpha)
I'm sorry, I wasn't clear enough when I posted my question.
I forgot to mention that I want certain transparent parts of a sprite to show a different background then the one directly under it.
Do you think I'd still be able to do that with draw>step?
 

Bingdom

Googledom
If I understand correctly, you want that texture to be in a fixed position. This can easily be done with shaders. :D

There's a lot going on though, so I've done a project example instead.
Screenshot
upload_2017-8-16_13-39-20.png

What you'll have to do draw a sprite that you want to be affected, then draw the outline to go with it.

If you want just the transparent areas, then you'll get the texture outside your character.

Unless if you really want just the transparent areas, then just draw the s_texture with the shader under the character and draw the character without the shader on top. If that's the case, then use this shader instead (You no longer pass in a texture):
Code:
void main()
{
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, vec2(mod(v_vTexcoord.x + offset.x, 1.0),mod(v_vTexcoord.y + offset.y, 1.0)) );
}

Download
 
Last edited:
If I understand correctly, you want that texture to be in a fixed position. This can easily be done with shaders. :D

There's a lot going on though, so I've done a project example instead.
Screenshot
View attachment 11874

What you'll have to do draw a sprite that you want to be affected, then draw the outline to go with it.

If you want just the transparent areas, then you'll get the texture outside your character.

Unless if you really want just the transparent areas, then just draw the s_texture with the shader under the character and draw the character without the shader on top. If that's the case, then use this shader instead (You no longer pass in a texture):
Code:
void main()
{
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, vec2(mod(v_vTexcoord.x + offset.x, 1.0),mod(v_vTexcoord.y + offset.y, 1.0)) );
}

Download
Nice, Bingdom! Thanks! =D
 

Mick

Member
Interesting. If you just want to replace a specific colour in the sprite with the texture, then modify the main() method of the fragment shader to this:

Code:
void main()
{
    vec4 green_screen_colour = vec4(0.0, 1.0, 0.0, 1.0); // Set green screen colour to 100% green
    vec4 Base = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    vec4 Tex = texture2D( texture, vec2(mod(v_vTexcoord.x + offset.x, 1.0),mod(v_vTexcoord.y + offset.y, 1.0)));
    if(Base == green_screen_colour) // If colour on sprite is 100% green than replace with texture
      gl_FragColor = vec4( Tex.rgb, Base.a );
    else // otherwise use sprite colour
      gl_FragColor = Base;
}
All pixels of the sprite that has an rgb value of 0,255,0 (100% green) will be replaced by the texture.
 
Last edited:
Interesting. If you just want to replace a specific colour in the sprite with the texture, then modify the fragment shader to this:

Code:
void main()
{
    vec4 green_screen_colour = vec4(0.0, 1.0, 0.0, 1.0); // Set green screen colour to 100% green
    vec4 Base = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    vec4 Tex = texture2D( texture, vec2(mod(v_vTexcoord.x + offset.x, 1.0),mod(v_vTexcoord.y + offset.y, 1.0)));
    if(Base == green_screen_colour) // If colour on sprite is 100% green than replace with texture
      gl_FragColor = vec4( Tex.rgb, Base.a );
    else // otherwise use sprite colour
      gl_FragColor = Base;
}
Yesss. You guys are 💩💩💩💩ing awesome! =D
 
W

Wraithious

Guest
@Mick and @Bingdom nice examples, I had some fun with your example project and used both shader versions you guys gave and added a third way which was to just adjust the alpha on the sprite itself with no shader, this is the result, keep pressing space to cycle through the 3 examples
 
J

Jeffin8or

Guest
Hey guys! Not sure if I'll have any luck on a 3 year old thread, but I've been trying to recreate this effect with a couple tweaks - I want the immovable texture to match the room background (so that if the object in question is in front of another object, the "green screen" portion will appear transparent, but reference the background and not display the object underneath). I've made some adjustments that mostly work, but the background doesn't quite match up - and I'm getting an ugly border around green areas where there's other colors starting to dilute the purity of the green.

Is there anyone who could help me:
a.) Get the immovable texture of the object to match the background and
b.) Get the shader to treat areas that are green, but not 100% green, as partially transparent, instead of just ignoring them?

Pic so you can see what I'm talking about:

reference.PNG
 

Yal

🐧 *penguin noises*
GMC Elder
Hey guys! Not sure if I'll have any luck on a 3 year old thread, but I've been trying to recreate this effect with a couple tweaks - I want the immovable texture to match the room background (so that if the object in question is in front of another object, the "green screen" portion will appear transparent, but reference the background and not display the object underneath). I've made some adjustments that mostly work, but the background doesn't quite match up - and I'm getting an ugly border around green areas where there's other colors starting to dilute the purity of the green.

Is there anyone who could help me:
a.) Get the immovable texture of the object to match the background and
b.) Get the shader to treat areas that are green, but not 100% green, as partially transparent, instead of just ignoring them?

Pic so you can see what I'm talking about:

View attachment 38160
Draw it while under the influence of a shader which has some logic like this:
  • Start off with the default passthrough shader
  • Add a new line after gl_FragColor is computed: gl_FragColor.a *= (1.0 - gl_FragColor.g);
I.e., we overwrite the alpha with 1 - the green component, so if the green component is 1 (100%, or 255 green in GM's color notation) we have 0 alpha (full transparency) and if it's 0 we have no transparency.
 
J

Jeffin8or

Guest
There's definitely something to the (1.0 - gl_FragColor.g) thing that could be helpful, but I'm not sure how to implement it with this project. The shader I'm using (based off Bingdom's code and Mick's modifications, above) sets a specific color that the shader later checks for in an if statement.

Is there maybe a way to create a range of colors that we could use in that same if statement?

The complete fragment shader code is:

Code:
// Created by Bingdom
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 offset;
uniform sampler2D texture;

void main()
{
    vec4 green_screen_colour = vec4(0.0, 1.0, 0.0, 1.0); // Set green screen colour to 100% green
    vec4 Base = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    vec4 Tex = texture2D( texture, vec2(mod(v_vTexcoord.x + offset.x, 1.0),mod(v_vTexcoord.y + offset.y, 1.0)));
    if(Base == green_screen_colour) // If colour on sprite is 100% green than replace with texture
      gl_FragColor = vec4( Tex.rgb, Base.a );
    else // otherwise use sprite colour
      gl_FragColor = Base;
}
I've tried vec4 green_screen_colour = vec4(0.0, 1.0 - gl_FragColor.g, 0.0, 1.0);, but that doesn't seem to change anything.
 

Bingdom

Googledom
a.) Get the immovable texture of the object to match the background and
The code I provided assumed that the size between the 2 textures are 1:1.

If the background sprite is 64x64, and your weapon is 32x32, then you will run into issues like this.
You just have to find the scale between the different resolutions and use the product with that combined with the offset.

b.) Get the shader to treat areas that are green, but not 100% green, as partially transparent, instead of just ignoring them?
You will want to find delta, i.e. The difference between the current colour value and target colour value. You will want to apply a threshold for how much green you want to actually make transparent and apply the texture.
 

Yal

🐧 *penguin noises*
GMC Elder
There's definitely something to the (1.0 - gl_FragColor.g) thing that could be helpful, but I'm not sure how to implement it with this project. The shader I'm using (based off Bingdom's code and Mick's modifications, above) sets a specific color that the shader later checks for in an if statement.

Is there maybe a way to create a range of colors that we could use in that same if statement?
The key thing here is that I make things transparent by reducing the alpha (opacity) based on how green things are. The 1 - other thing bit only makes sense for the alpha channel so that's why you're not seeing any results.

If you want this to work for arbitrary colors... you could get a "similarity factor" by taking the dot product of the current gl_FragColor and the desired greenscreen color, then use 1 - SimilarityFactor as the alpha component of the final color? Or if you want the effect to have less spillover on other colors, use the quad/cube of similarity factor to have a sharper falloff:

gl_FragColor.a = 1.0 - (SimilarityFactor*SimilarityFactor);
 
Top