O
OscarGrouch
Guest
Hi All, I'm pretty new to shaders, and relatively new to coding (this is my first game) so this may be really simple to solve.
Basically, I'm making a top down space combat game (think asteroids type movement), where one of the ships can produce a "Gravity Wave". I want this effect to be emitted from the front of the ship and push other objects away from it. I want the effect to be visible as a distortion to the background as if the waves are bending light as it passes through and the waves to propagate outwards from the ship, like ripples from a stone dropped in a pond, but only visible within the area of a cone projected from the front of the ship.
I found a nice magnification glass shader online somewhere which I have modified to give the effect I want, but this shader creates an entire circle centred on the ship, instead of the cone from the front that I want.
What I would like to do, is use the texture data of the surface created by the magnifying glass shader, and map that onto a cone shaped sprite that sticks out the front of the ship. I'd also like to modify the intensity of the effect by the alpha value of the cone sprite, but that's something for later.
The ship rotates onscreen, and so the gravity wave cone does too, but as long as I can map just the section of the magnifying effect that is in the same relative position as the cone sprite it should work ok.
The problem I'm having is that the magnifying shader that I found online, simply draws a section of the application surface using the shader which produces the magnifying effect. What I want to do is take this finished effect and then manipulate it more within a shader to produce the effect I want (mapping it onto the cone) but I don't know how to do that.
The code for producing the gravity waves follows.... most of it I didn't write myself - I've just modified it to produce propagating waves.
In the gravity cone object...
CREATE EVENT
DRAW END EVENT
GravWave shader
FRAGMENT SHADER
So, the above code produces a circle of propagating waves centred on the ship (same origin as the grav cone object).
I want to display just the section of this circle that intersects with the grav cone objects sprite. So its like a pizza slice of the circle in the direction the ship is facing.
I've tried to apply the shader to the cone sprite, but it completely changes the effect and I don't think that's the way to go.
I think the solution may be to produce the mag wave effect, and load the texture of that surface into a shader, then apply that texture to the grav cone sprite, but I don't know how to do that.
I am open to suggestions!!
Basically, I'm making a top down space combat game (think asteroids type movement), where one of the ships can produce a "Gravity Wave". I want this effect to be emitted from the front of the ship and push other objects away from it. I want the effect to be visible as a distortion to the background as if the waves are bending light as it passes through and the waves to propagate outwards from the ship, like ripples from a stone dropped in a pond, but only visible within the area of a cone projected from the front of the ship.
I found a nice magnification glass shader online somewhere which I have modified to give the effect I want, but this shader creates an entire circle centred on the ship, instead of the cone from the front that I want.
What I would like to do, is use the texture data of the surface created by the magnifying glass shader, and map that onto a cone shaped sprite that sticks out the front of the ship. I'd also like to modify the intensity of the effect by the alpha value of the cone sprite, but that's something for later.
The ship rotates onscreen, and so the gravity wave cone does too, but as long as I can map just the section of the magnifying effect that is in the same relative position as the cone sprite it should work ok.
The problem I'm having is that the magnifying shader that I found online, simply draws a section of the application surface using the shader which produces the magnifying effect. What I want to do is take this finished effect and then manipulate it more within a shader to produce the effect I want (mapping it onto the cone) but I don't know how to do that.
The code for producing the gravity waves follows.... most of it I didn't write myself - I've just modified it to produce propagating waves.
In the gravity cone object...
CREATE EVENT
GML:
//magnifying shader stuff
size = sprite_width * 2;
half_size = size * 0.5;
srf = -1;
zoom1 = 0.8;
zoom2 = 0.7;
radius = 0.9;
aberration = 0.02;
contrast = 1.7;
saturation = 0.75;
gamma = 1.4;
timer = 0.0;
shader = shd_gravWave;
u_timer = shader_get_uniform(shader, "timer"); //timer for sine wave function
u_zoom1 = shader_get_uniform(shader, "zoom1"); // Changes how the zoom effect looks
u_zoom2 = shader_get_uniform(shader, "zoom2"); // Changes how the zoom effect looks
u_radius = shader_get_uniform(shader, "radius"); // Changes how the zoom effect looks
u_aberration = shader_get_uniform(shader, "aberration"); // strength of the chromatic aberration
u_contrast = shader_get_uniform(shader, "contrast");
u_saturation = shader_get_uniform(shader, "saturation");
u_gamma = shader_get_uniform(shader, "gamma");
GML:
var left = x - half_size;
var top = y - half_size;
// CREATE THE MAGNIFYING SURFACE:
if !surface_exists(srf)
srf = surface_create(size, size);
surface_set_target(srf);
draw_surface_part(application_surface, left, top, size, size, 0, 0);
surface_reset_target();
// DRAW THE MAGNIFYING EFFECT:
shader_set(shader);
shader_set_uniform_f(u_timer, timer);
shader_set_uniform_f(u_zoom1, zoom1);
shader_set_uniform_f(u_zoom2, zoom2);
shader_set_uniform_f(u_radius, radius);
shader_set_uniform_f(u_aberration, aberration);
shader_set_uniform_f(u_contrast, contrast);
shader_set_uniform_f(u_saturation, saturation);
shader_set_uniform_f(u_gamma, gamma);
gpu_set_tex_filter(true);
draw_surface(srf, left, top);
gpu_set_tex_filter(false);
shader_reset();
FRAGMENT SHADER
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float timer;
uniform float zoom1;
uniform float zoom2;
uniform float radius;
uniform float aberration;
uniform float contrast;
uniform float saturation;
uniform float gamma;
void main() {
// GET MAGNIFY SAMPLE OFFSET FROM THE CENTRE:
float freq = 40.0; //frequency of waves
float dist = length(v_vTexcoord - 0.5); // distance to the center
float wave = (abs(sin((-timer + freq * dist)/2.0)) + 2.0)/3.0; //propogating sine wave effect //range -1 - 1 based on distance from centre
float angle = atan(v_vTexcoord.y - 0.5, v_vTexcoord.x - 0.5); // angle from the center
float zoomed_radius = wave * dist * ((zoom2 * dist / radius) + zoom1); // new radius to get the sample from
vec2 offset = vec2(cos(angle), sin(angle)) * zoomed_radius; // offset from the center
// MAGNIFY:
vec2 sample = 0.5 + offset;
vec4 base_col = texture2D(gm_BaseTexture, sample);
//CIRCULAR STENCIL:
base_col.a = mix(base_col.a, 0.0, step(0.5, dist)); // if outside the circle: alpha = 0
// CHROMATIC ABERRATION (optional, can be deleted without changing anything else):
vec2 abr_dist = (v_vTexcoord - 0.5) * (v_vTexcoord - 0.5) * aberration; // square curve so there's no aberration at the center
sample = abr_dist + 0.5 + offset;
vec3 col_magenta = texture2D(gm_BaseTexture, sample).rgb;
sample = -abr_dist + 0.5 + offset;
vec3 col_cyan = texture2D(gm_BaseTexture, sample).rgb;
base_col.rgb = vec3(0.5, 0.5, 0.33) * base_col.rgb + vec3(0.5, 0.0, 0.33) * col_magenta + vec3(0.0, 0.5, 0.33) * col_cyan;
// ADJUST COLOURS (optional, each of these adjustments can be removed without changing anything else):
// gamma:
base_col.rgb = base_col.rgb = pow(base_col.rgb, vec3(1.0 / gamma));
// contrast:
base_col.rgb = (base_col.rgb - 0.5) * contrast + 0.5;
// saturation:
float gray = dot(base_col.rgb, vec3(0.33,0.33,0.33));
base_col.rgb = mix(vec3(gray), base_col.rgb, saturation);
// OUTPUT:
gl_FragColor = base_col;
}
I want to display just the section of this circle that intersects with the grav cone objects sprite. So its like a pizza slice of the circle in the direction the ship is facing.
I've tried to apply the shader to the cone sprite, but it completely changes the effect and I don't think that's the way to go.
I think the solution may be to produce the mag wave effect, and load the texture of that surface into a shader, then apply that texture to the grav cone sprite, but I don't know how to do that.
I am open to suggestions!!
Last edited by a moderator: