• 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!

How do you combine sprites

Chara

Member
I'm trying to make a dynamic shader system, but nothing I do seems to work. How would I get the intersection of the shadows to appear to be same object?

Here's the code I'm using:

draw_set_alpha(0.7490196078);
draw_sprite(spr_shadow, 0, x, y);
draw_sprite(spr_boxshadow, 0, obj_box.x, obj_box.y);
draw_sprite(spr_box, 0, obj_box.x, obj_box.y);
draw_set_alpha(1);
 

Attachments

Kahrabaa

Member
Yes create a surface thats only for shadows, draw all shadows on that surface with opacity of 1 and then draw that surface below everything with a lower opacity like this:

You need a parent object that you give to anything that casts shadows for example: "objShadowParent".
And this code goes into an object that controls drawing the shadows "objShadowControl"

Code:
//DRAW EVENT
surface_set_target( shadowSurf ); //Draw to surface
with( objShadowParent ){
draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
}
surface_reset_target(); //Return to normal drawing

if(surface_exists(shawdowSurf)=0){
shadowSurf = surface_create( view_wview[0], view_hview[0] );
}
else{
draw_surface_ext( shadowSurf, view_xview[0], view_yview[0], 1,1, c_black, 0.5 ); //0.5 here decides shadow opacity
}

and then you need to free the surface using surface_free( shadowSurf ); at a room end event or instance_destroy to prevent memory problems.
 

Chara

Member
Yes create a surface thats only for shadows, draw all shadows on that surface with opacity of 1 and then draw that surface below everything with a lower opacity like this:

You need a parent object that you give to anything that casts shadows for example: "objShadowParent".
And this code goes into an object that controls drawing the shadows "objShadowControl"

Code:
//DRAW EVENT
surface_set_target( shadowSurf ); //Draw to surface
with( objShadowParent ){
draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
}
surface_reset_target(); //Return to normal drawing

if(surface_exists(shawdowSurf)=0){
shadowSurf = surface_create( view_wview[0], view_hview[0] );
}
else{
draw_surface_ext( shadowSurf, view_xview[0], view_yview[0], 1,1, c_black, 0.5 ); //0.5 here decides shadow opacity
}

and then you need to free the surface using surface_free( shadowSurf ); at a room end event or instance_destroy to prevent memory problems.
I set this up and renamed the objects and came up with this error:

___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object objShadowControl:

Variable objShadowControl.shadowSurf(100002, -2147483648) not set before reading it.
at gml_Object_objShadowControl_DrawEvent_1 (line 11) - surface_set_target( shadowSurf ); //Draw to surface
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_objShadowControl_DrawEvent_1 (line 11)
 

Chara

Member
Oh, I forgot, It needs to be initialised, just put shadowSurf=-1; in the create event.
I wasn't sure which object I was supposed to put it in, so I tried both.

When it was in objShadowParent:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object objShadowControl:

Variable objShadowControl.shadowSurf(100002, -2147483648) not set before reading it.
at gml_Object_objShadowControl_DrawEvent_1 (line 11) - surface_set_target( shadowSurf ); //Draw to surface
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_objShadowControl_DrawEvent_1 (line 11)


When it was in objShadowControl:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object objShadowControl:

Variable objShadowControl.shawdowSurf(100003, -2147483648) not set before reading it.
at gml_Object_objShadowControl_DrawEvent_1 (line 17) - if(surface_exists(shawdowSurf)=0){
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_objShadowControl_DrawEvent_1 (line 17)










EDIT: Turns out there was a typo, but I now have a new problem
(The shadow stays after objShadowParent moves)
 

Attachments

Last edited:

Kahrabaa

Member
Yeah, sorry I was in a hurry when I wrote that. Here I tested this before this time, should work:

Code:
var _opacity=.5;
var _xoffset=8;
var _yoffset=8;

//DRAW EVENT
surface_set_target( shadowSurf ); //Draw to surface
    draw_clear_alpha(0,0); //This line was missing, that clears the surface each frame
    with( objShadowParent ){
    draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
    }
surface_reset_target(); //Return to normal drawing

if(surface_exists(shadowSurf)=0){
shadowSurf = surface_create( view_wview[0], view_hview[0] );
}
else{
draw_surface_ext( shadowSurf, view_xview[0]+_xoffset, view_yview[0]+_yoffset, 1,1,0, c_black, _opacity );
}
Yes, the shadowSurf=-1; goes into objShadowControl's create event.
Of course objShadowParent has to be the parent of every object that cast shadow.
Hope this solved it.
 

Chara

Member
Yeah, sorry I was in a hurry when I wrote that. Here I tested this before this time, should work:

Code:
var _opacity=.5;
var _xoffset=8;
var _yoffset=8;

//DRAW EVENT
surface_set_target( shadowSurf ); //Draw to surface
    draw_clear_alpha(0,0); //This line was missing, that clears the surface each frame
    with( objShadowParent ){
    draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
    }
surface_reset_target(); //Return to normal drawing

if(surface_exists(shadowSurf)=0){
shadowSurf = surface_create( view_wview[0], view_hview[0] );
}
else{
draw_surface_ext( shadowSurf, view_xview[0]+_xoffset, view_yview[0]+_yoffset, 1,1,0, c_black, _opacity );
}
Yes, the shadowSurf=-1; goes into objShadowControl's create event.
Of course objShadowParent has to be the parent of every object that cast shadow.
Hope this solved it.
I'm supposed to have objShadowParent and the object casting the shadow be separate?

EDIT: Yes, that seems to have worked, thank you!
 

Kahrabaa

Member
Yes, you need only one objShadowParent and you dont need to place it in the level. Just place objects that castshadow normally in the room and make sure that the they have objShadowParent as the object parent like this:

Edit: Nice
 

Chara

Member
Yes, you need only one objShadowParent and you dont need to place it in the level. Just place objects that castshadow normally in the room and make sure that the they have objShadowParent as the object parent like this:

Edit: Nice
One last question: how would I flip the shadow? (as in horizontally and vertically)
 

Kahrabaa

Member
Code:
with( objShadowParent ){
    draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, -image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
    }
This code here when you draw each specific objShadowParent, you can change how they are drawn. So for example inverting it vertically you just put -image_yscale. Then depending on the sprite origin you might want to reposition it aswell or not.
 

Chara

Member
Code:
with( objShadowParent ){
    draw_sprite_ext( sprite_index, image_index, x-view_xview[0], y-view_yview[0], image_xscale, -image_yscale, image_angle, c_black, 1); //Draw all shadows with full opacity
    }
This code here when you draw each specific objShadowParent, you can change how they are drawn. So for example inverting it vertically you just put -image_yscale. Then depending on the sprite origin you might want to reposition it aswell or not.
Thank you! It works perfectly now!
 

TheouAegis

Member
Just an idea, even though this was already solved: Use dithered shadows! lol
If you draw a dot every other pixel, staggered relative to the position in room or on screen, then there would be no unwanted pixel density!
 
Top