Legacy GM Affecting the Background with a Shader via a Surface

Odolwa

Member
I have come across a shockwave shader tutorial by Reverend Greg which makes use of surfaces and affects everything on screen, however, I wanted to know if it's possible to create a surface which would only apply to the background and allow the shockwave effect to happen behind the player, rather than ahead of them.
 
You pretty much solved it already. Create a surface, draw the background to it, start the shader, draw the surface, end the shader, draw the rest.
 
What BAttleRifle BR55 said. You might need to subtract the views position when drawing the background to another surface than the application surface. Not sure, but you'll find out qucikly if it's needed or not :)
 

Odolwa

Member
Thank you for responding. I just have one or two questions. If I'm creating the surface via the 'surface_create' function, which takes arguments of width and height, should I still be using 'view_wview[0]' and 'view_hview[0]' if I'm only concerned with the background, and if not should I use the dimensions of the room that only include the background?
 

Odolwa

Member
In your tutorial, you set the arguments for 'surface_create' via the 'camera_get_view_width/height' function multiplied against a scaling factor. At the moment, I'm using GMS1.4, so I wasn't able to use that but 'view_w(h)view[0]' did the job just fine. If I were to try and do this in GMS2, would I still be using the 'view_camera[0]' arguments?
 

NightFrost

Member
Camera is a GMS2 thing, so you could use those commands when coding on that platform, but it still supports GMS1 methodology so you wouldn't need to change any code if you didn't want to.
 

Odolwa

Member
Thanks for responding, NightFrost. What I'm still not clear on is how to define the surface dimensions such that the shader only factors in the background, or I am looking at this all wrong? Should I just leave them as they originally were, i.e. encompassing the entire view/camera, or should I set them relative to the dimensions of the background space?
 

NightFrost

Member
You're on 1.4 so there's no layers and layer scripts which would be the most convenient way to do this. So your draw flow would be like:
  1. Create surface for constructing backround if one does not already exist.
  2. Set surface as target and clear it.
  3. Construct your background (will be drawn to surface)
  4. Reset target.
  5. Set up shader.
  6. Draw surface (goes to default target, which is the application surface).
  7. Reset shader.
If your intent is to apply the effect to everything on screen but the player, it might be simpler to use the fullscreen method and postpone drawing the player until after the effect has been applied.
 

Odolwa

Member
Ok, I'm going to show the code and highlight the relevant parts based on the advice:

Draw GUI Begin:

Code:
//1. Create Surface
if (!surface_exists(srf_waves))
{
    srf_waves = surface_create(view_w * srf_waves_scale, view_h * srf_waves_scale);
    tex_waves = surface_get_texture(srf_waves);
}

//2. Set Surface and Clear It
surface_set_target(srf_waves);
   draw_clear_alpha($FF7F7F, 1);
   draw_set_blend_mode_ext(bm_dest_color, bm_src_color);
    
   //3. Construct the Background (This is the line I added)
   draw_background_ext(bgr_Fort,view_xview[0],view_yview[0],1,1,0,c_white,1);
    
    //(This shader has 2 parts.  Here, in the surface where normals are added, and the second below which uses this to make the shockwave.  I assume this might be where the problem is occurring?)
    shader_set(shd_addNormals);
        var w, this_wave;
        for (w = 0; w < wave_list_size; w++)
        {
             his_wave = list_of_waves[|w];
            
            draw_sprite_ext(sprite, subimage, (this_wave[|waveparam.xx] - view_xview[0]) * srf_waves_scale, (this_wave[|waveparam.yy] - view_yview[0]) * srf_waves_scale, this_wave[|waveparam.scale] * srf_waves_scale, this_wave[|waveparam.scale] * srf_waves_scale, 0, c_white, this_wave[|waveparam.alpha]);
        }
      shader_reset();
    
      draw_set_blend_mode(bm_normal)

  //4. Reset Target
  surface_reset_target();
 
  //5. Set Up Shader
  shader_set(shader);
      shader_set_uniform_f(u_fx_strength, fx_strength);
      shader_set_uniform_f(u_aspect, aspect);
      shader_set_uniform_f(u_aberration, aberration);
      texture_set_stage(u_tex_waves, tex_waves);

      //6. Draw Surface
      draw_surface(application_surface, 0, 0);

  //7. Reset Shader
  shader_reset(); [code]
[B][/B]
The shock wave still appears in front of the player though, so I'm not sure where I'm going wrong.
 
Where's the part where you draw the player after the shock wave? If you're still drawing the player to the application surface and then affecting that surface with the shock wave shader, then you're not going to see any differences because you're intentionally doing exactly what you're trying to avoid.
 

Odolwa

Member
In regards to drawing the player after the shockwave, am I supposed to stop the player object from drawing itself and set the 'draw_self()' function inside the surface? Or do you mean a Draw End event? I've tried both and I've also tried creating a second surface to draw the player to, which I set before and then after the shader, but still nothing. I can't figure out where the error is.
 

Odolwa

Member
Ok, apologies for the delay, I was trying a few things out and realised that the issue relates to the Draw GUI Begin event. Specifically, if I set 'draw_sprite_ext' at the end of the code as you suggested the sprite will be drawn, but its position and scale are being set relative to the 'View in room' options in the Room Editor, i.e. if the 'Port on screen' options are W: 1024 H: 768 and the 'View in room' is set to W: 640 H: 480 then the difference in scale will be 1.6 times smaller than that of the player sprite (1024/640 = 1.6).

While the scale can be easily corrected by multiplying the 'x/y_scale' arguments of 'draw_sprite_ext' by 1.6, keeping the sprite tracking the player, however, is more complex. As the player moves left to right, or up and down, across the screen, the sprite will initially follow the player, but will start to fly away from them at the halfway mark of the screen until eventually slowing down again. I cannot yet figure out how to manipulate the 'x/y' coordinates of the 'draw_sprite_ext' function to account for this.

It's worth pointing out that these issues of scaling and tracking do not occur when the sprite is drawn in the standard Draw event, so it is clear that what is going on definitely relates to how the Draw GUI Begin event functions. Can anyone help? Thank you.
 
Top