• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Question - Code Copying from the application_surface (is this a bug?)

Drenathor

Member
What I'm trying to achieve:

I want to make a waterfall object which applies a shader to everything appearing under it so that tiles, assets and objects occluded (even partially) would have a distortion applied.

What I'm Doing:

I'm creating a new surface for the waterfall, copying the area directly behind it from the application_surface and then applying the shader to that surface.

My Issues:

However I have 2 issues, first is that when my viewport height and width are not the same as my camera height and width the data copied from the application surface is 2x the size I would expect causing it to appear zoomed in. - edit this is solved now

The second and this appears to be specific to game maker studio 2 is that my application surface appears to be mirrored. I've run some test code in both Studio 1 and Studio 2 to show the difference:

Studio 1 (notice how the reflection is facing the same direction)


Studio 2 (notice how the reflection is backwards)


The Creation Code:
Code:
globalvar water_surface;
water_surface = surface_create( sprite_get_width(sprite_index), sprite_get_height(sprite_index));
The Draw End Code:
Code:
// 2x what I want it to be in both Studio 1 & 2 and reversed in Studio 2
surface_copy_part( water_surface, 0, 0, application_surface, x, y, 81, 81 );

// this is wrapped in my shader code
draw_surface( water_surface, x, y );

// I've got an empty draw statement to prevent this from being drawn 2x.
draw_sprite( spr_waterfall, 0, x, y );
Any help would be really appreciated :)

P.S. My Camera is 480x270 and my viewport is 960x540
 
Last edited:

Drenathor

Member
UPDATE: I've got the scaling sorted now. Since the application_surface layer was being scaled by a factor of 2 due to my camera and viewport settings I'm now adjusting the x and y values of where I want to copy from and then scaling down the surface when I draw it.

However the problem still remains, my application layer is flipped for some inexplicable reason in Game Maker 2. Anyone have any ideas as to why?
 

kburkhart84

Firehammer Games
Well, just a thought(I'm not a shader expert though). Isn't there something you can use in a fragment shader that grabs the current value on said fragment? If I'm right, you may be able to do something with that. This of course wouldn't fix the problem as you have it now but could be a viable workaround and possibly a better way to do it.
 

Drenathor

Member
Well, just a thought(I'm not a shader expert though). Isn't there something you can use in a fragment shader that grabs the current value on said fragment? If I'm right, you may be able to do something with that. This of course wouldn't fix the problem as you have it now but could be a viable workaround and possibly a better way to do it.
I'm not either, but my understanding is that shaders only apply themselves to the thing they are attached to. Since I want to essentially apply it to only the parts of every object, tile and sprite located directly under my waterfall object the only way I know of to achieve this is to copy everything below it to a new surface and apply the shader to that surface. The problem is that before I even get the chance to apply the shader, the image being copied is being corrupted by Game Maker Studio 2. This exact code works flawlessly in Studio 1 so I'm thinking that it's either a bug or the result of some new change and there is some simple function that I need to learn to make it work. (hopefully the latter) ;)
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
This sounds like a bug, so you should probably file it as one, especially if you are getting the mirroring without using the shader and when simply drawing the surface. Please supply a link to an example project that shows the issue if you can.
 

Drenathor

Member
Hi @Nocturne, What's the proper way to submit a bug report these days? (sorry the last time I submitted a bug report was back when GM 4 was launched).

That is correct, copying from the application surface is broken in Studio 2 (as far as I can tell) even if the shader is removed entirely from the project.

In Studio 1, using the following:
Code:
surface_copy_part( water_surface, 0, 0, application_surface, sx, sy, 81 * ratio, 81 * ratio );
produces this result:


To see for yourself, here is the file:
https://www.dropbox.com/s/s5uq65sdq09sjx0/Waterfall Shader Test.gmez?dl=0

However that code produces this result out of the box in Studio 2...



Wrapping the surface_copy_part() code in surface_set_target and surface_target_reset brings me closer to studio 1's behavior...



Notice how horrifically the surface is being copied... This also highlights another issue that I've been scratching my head over. You see those gaps that randomly appear? I've been noticing that in the actual game that I'm making too. Objects placed on the floor for floor tiles are randomly spaced wrong in some builds. One time I play it will be 100% fine and the next time there will be thousands of little lines through the level between each floor/wall object. EDIT - This appears to be fixed in version 2.0.3.56

Anyways, to see this file in action you can download it at:
https://www.dropbox.com/s/9trdixey3kx8xd2/Waterfall Studio 2 Test.yyz?dl=0
Any help would be appreciated, and if you could tell me how to file a bug for studio 2 that would be great as well. figured I'd post this here though as someone may realize this isn't really a bug but something I'm doing wrong with the new camera / layers system or something?

Anyways, thanks for everyone's time :)
 
Last edited:

psyke

Member
There is definitely something weird about surfaces in Game Maker Studio 2. I found something very strange: if I create two surfaces with the size of the screen using the code below:
Code:
/// @desc Draw Reflections
if(surface_exists(MaskSurface))
{
}
else
MaskSurface = surface_create(427, 240);

if(surface_exists(MirrorSurface))
{
}
else
MirrorSurface = surface_create(427, 240);
The screen starts shaking when the camera moves (this only happens on some parts of my level and only happens on GMS 2). Which is weird because I'm not even drawing the surface into the screen, I'm just creating them.
 

Drenathor

Member
Quick update, I tried installing the update that Game Maker told me about just now (2.0.3.56) and it's taken care of the weird splitting of boxes as I move around! So that's a great start. I'll keep an eye out for those odd intermittent breaks between objects in my other projects. However, at this point I'm still getting a completely useless image from copy_surface_part().



@psyke considering this last update fixed that odd jitter for me when my objects were moving around the screen you might want to see if it fixed your issue as well.
 

psyke

Member
Quick update, I tried installing the update that Game Maker told me about just now (2.0.3.56) and it's taken care of the weird splitting of boxes as I move around! So that's a great start. I'll keep an eye out for those odd intermittent breaks between objects in my other projects. However, at this point I'm still getting a completely useless image from copy_surface_part().
@psyke considering this last update fixed that odd jitter for me when my objects were moving around the screen you might want to see if it fixed your issue as well.
I tried the new update, but it's still the same =(
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Hi @Nocturne, What's the proper way to submit a bug report these days? (sorry the last time I submitted a bug report was back when GM 4 was launched).
You go to the "Help" menu and select "Report A Bug". If you could link to this topic, as well as provide a link to the file that's giving the issue as an example, then that would be great too. :)
 

Drenathor

Member
You go to the "Help" menu and select "Report A Bug". If you could link to this topic, as well as provide a link to the file that's giving the issue as an example, then that would be great too. :)
LOL, didn't even notice that in there. Thanks for pointing that out.

Ok, I've submitted a bug with a link to this thread and a link to the Studio 2 sample project (which is also posted here as well as the working studio 1 version). I didn't see it appear in the list on http://www.yoyogames.com/bug2 so I guess at this point I just have to assume that you guys got it.

Hope it can get fixed soon :) Guess in the mean time I'll work on something else and stop trying to get this to work for now. Is there any way I can follow the status this bug report? Or should I just try re-running my sample code every time I see an update?
 

Mike

nobody important
GMC Elder
For now... rather than copying, how about just switching off blending and drawing it to a new surface of the same size?
 

Mike

nobody important
GMC Elder
This should be what happens internally anyway.... (and I say...SHOULD...)
 

Drenathor

Member
For now... rather than copying, how about just switching off blending and drawing it to a new surface of the same size?
Unfortunately I think my being new to using surfaces is not helping here... How exactly should I do this? In Game Maker Studio 1 I can't get the application surface to draw at all... But in Studio 2 I can, however I have a whole different set of issues. The function I was trying to use is this:

Code:
draw_surface_part_ext( application_surface, 0, 0, sprite_width * ratio, sprite_height * ratio, sx, sy, 1/ratio, 1/ratio, c_white, 1 );
If I leave this function out I see nothing since the waterfall's draw event is empty. However as soon as I add this function into the draw or draw_end event I suddenly see the sprite for my waterfall again despite not having the draw_self() function. Does drawing the application_surface also trigger draw_self()?

Additionally, I noticed when copying code back and forth between studio 1 and studio 2 that view_xview no longer triggers and error but is simply initialized with a 0. Needless to say this is actually rather undesirable behavior as the compiler gave 0 indications that I shouldn't be using this anymore and I had no help in debugging to figure out why my positioning was wrong.

But in any case, I can't seem to get this to work. So any help would be appreciated.
 
Last edited:
N

Never Mind

Guest
This may not be the best way to do it, but hopefully it helps to get you thinking in the right direction :)
surface_set_target( water_surface );
draw_surface( application_surface, -x,-y );
surface_reset_target();

// this is wrapped in your shader code
draw_surface_ext( water_surface, x + surface_get_width(water_surface) ,y, -1,1, 0, c_white, 1);
 
Last edited by a moderator:

Mike

nobody important
GMC Elder
you also need to disable the alpha blending so that alpha+colour is "copied" not blended etc,


This has now been fixed internally.
 

Drenathor

Member
@Never Mind, Thanks for the code. I was able to get the effect working based on it! Here's what I have currently:

Code:
// since our camera and viewport are different sizes get our offsets and scale corrections
ratio = view_get_hport( 0 ) / camera_get_view_height( view_camera[0] );
sx = ( x - camera_get_view_x( view_camera[0] ) ) * ratio;
sy = ( y - camera_get_view_y( view_camera[0] ) ) * ratio;

gpu_set_blendenable( false );

   // draw the application surface (unflipped) to our water surface
   surface_set_target( water_surface );
       draw_surface( application_surface, -sx, -sy );
   surface_reset_target();

   // draw the water_surface and apply the shader
   shader_set( shdr_waterfall );
       shader_set_uniform_f( uTime, current_time / 1000 );
       draw_surface_ext( water_surface, x, y, 1/ratio, 1/ratio, 0, c_white, 1);
   shader_reset();

gpu_set_blendenable( true );

// draw the water on top of the surface
draw_self();
My question is, how does this compare performance wise to just copying parts of the surface if I have dozens of these objects in the game? Is it better to draw the application_surface a second time to my water surface or to copy a part of it to the water surface (seems like this should be the same under the hood...)? Also, instead of using draw_surface( application_surface, -sx, -sy ), would it be better to use draw_surface_part()? I tried using it but everything broke so I must not understand the parameters...

@Mike That's great news! I have a few follow up question though... What is the ETA on the next update? Will it affect the code above (since it is flipping the application_surface to make it work correctly)? And finally, once copy_surface is working are you recommending I stick with the above code instead of switching to it for performance reasons?

Thanks so much for everyone's help!
 
N

Never Mind

Guest
@Drenathor
The answer to your question: "it be better to use draw_surface_part()?" is yes! ( at least I assume it is better performance wise )

But again
"This may not be the best way to do it, but hopefully it helps to get you thinking in the right direction :)" ~ me

I highly suggest expanding your understanding of surfaces. Your hang up seems to be transitioning between room coordinates, and surface coordinates.


If you read the page in the manual Surfaces http://docs.yoyogames.com/source/dadiospice/002_reference/surfaces/
The fourth bullet down says
  • "when drawing to a surface manually, the surface is always at the position of (0,0). This means that you may need to convert absolute coordinates into local coordinates for the surface. For example, if you have a view-sized surface and wish to draw something that is currently in view to that surface, you should subtract the view x and y coordinates from the actual x and y coordinates to get a relative position to the surface (0,0) position. So, the code would look something like this: <snip>
 
Last edited by a moderator:

Drenathor

Member
@Drenathor
The answer to your question: "it be better to use draw_surface_part()?" is yes! ( at least I assume it is better performance wise )

But again
"This may not be the best way to do it, but hopefully it helps to get you thinking in the right direction :)" ~ me

I highly suggest expanding your understanding of surfaces. Your hang up seems to be transitioning between room coordinates, and surface coordinates.


If you read the page in the manual Surfaces http://docs.yoyogames.com/source/dadiospice/002_reference/surfaces/
The fourth bullet down says
  • "when drawing to a surface manually, the surface is always at the position of (0,0). This means that you may need to convert absolute coordinates into local coordinates for the surface. For example, if you have a view-sized surface and wish to draw something that is currently in view to that surface, you should subtract the view x and y coordinates from the actual x and y coordinates to get a relative position to the surface (0,0) position. So, the code would look something like this: <snip>
Haha, Yeah that's kind of what I assumed given some of the earlier comments from @Mike and @Juju but I just wanted to verify since I'd have thought that surface_copy_part would use surface_draw_part under the hood but I guess not. Anyways, I guess at this point I'll have to wait for the update. Since the code I have now corrects for the backwards surface layer it will probably break when things are fixed.

Thanks for the link BTW!. Yeah I've learned all sorts of things about surfaces in the last 48 hours. Today I learned that you can't reliably access the application surface in the draw event as that's when it's currently open and being populated (which probably should have been obvious). I think I have the positioning of the surfaces down however as I had everything working in Studio 1 originally with no issues, my main hangups seem to have come from the surface layer being backwards and not knowing how to flip it and trying to access it at the wrong times to draw from it to another surface.

It would still be nice to know if I should continue to use draw_surface or draw_surface_part. I don't know how optimized draw surface is under the hood and if it will only draw what it needs to in order to fill the new surface or if it wastes lots of resources. Guess I can play around with it some more after things are fixed.
 
Top