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

Shaders Using two shaders at once

Vulcano

Member
I have found this thread but I cannot join my 2 shaders.

--------------------------------------------------
Shader 1
--------------------------------------------------

void main()
{
// Sample random high-frequency noise
vec4 randomHiFreq = whiteNoise(v_vTexcoord, randomValues.xy);

// Apply line offsets
vec2 offsetCoords = v_vTexcoord;
offsetCoords.x += ((((2.0 * randomValues.z) - 1.0) * shakiness * lineSpeed) + lineOffset(offsetCoords)) * lineShift * intensity;

// Apply jumbles
offsetCoords += jumble(offsetCoords) * intensity * intensity * 0.25;

// Channel split
vec2 shiftFactors = (channelShift + (randomHiFreq.rg * dispersion)) * intensity;
vec4 outColour;

// Free dynamic branch.
if (((channelShift + dispersion) * intensity) < DELTA) {
outColour = texture2D(gm_BaseTexture, mirror(offsetCoords));
} else {
outColour = extractRed(texture2D(gm_BaseTexture, mirror(offsetCoords + vec2(shiftFactors.r, 0.0)))) + extractBlue(texture2D(gm_BaseTexture, mirror(offsetCoords + vec2(-shiftFactors.g, 0.0)))) + extractGreen(texture2D(gm_BaseTexture, mirror(offsetCoords)));
}

// Add noise
outColour.rgb *= (vec3(.55, .5, .4) * randomHiFreq.gab * intensity * noiseLevel) + 1.0;

gl_FragColor = v_vColour * outColour;
}

--------------------------------------------------
Shader 2
--------------------------------------------------

varying vec2 v_texcoord;

uniform float time;
uniform vec2 mouse_pos;
uniform vec2 resolution;
uniform float radial_blur_offset;
uniform float radial_brightness;

const float blur_amount = 30.0;
void main()
{
vec2 uv = vec2(v_texcoord);
vec2 radial_size = vec2(1.0/resolution);
radial_size.x *= (resolution.x/resolution.y);
vec2 radial_origin = vec2(mouse_pos/resolution);
vec4 colour = vec4(0.0);

uv += radial_size * 0.5 - radial_origin;

for (float i = 0.0; i < blur_amount; i++)
{
float offset = 1.0 - radial_blur_offset * (i / (blur_amount - -300.0));
colour += texture2D(gm_BaseTexture, uv * offset + radial_origin);
}

gl_FragColor = colour / (blur_amount - 1.0) * radial_brightness;
}

Any idea? Thanks anyway.
 
Last edited by a moderator:

Fredrik

Member
I had the same problem, where I wanted to combine three shaders, so I ended up reading alot abount opengl and learned enough to combine all shaders. Wasn't really that hard 😁
 

Yal

🐧 *penguin noises*
GMC Elder
It would've helped if you'd explained what you were trying to achieve, there's plenty of ways you could combine shaders. Also, those are two half shaders, you need both the vertex + fragment shaders to make a complete shader. (If the other halves are placeholders, you should point that out)

Also, the first shader refers to a lot of nonstandard functions, you've left those out when copying the shader.

It looks like you have perlin noise + bloom/blur? The easiest way to combine them might be to draw the noise to a surface first, then draw that surface with the bloom/blur shader in effect - the blur samples points around the current fragment so it won't work properly unless the entire thing to draw is known already.
 

Vulcano

Member
I have prepared 1 demo. The first room has the blur shader activated and the second room has the TV effect shader.
My goal is to use the 2 shaders at the same time.
 
Last edited:

Yal

🐧 *penguin noises*
GMC Elder
I already gave you a suggestion...
The easiest way to combine them might be to draw the noise to a surface first, then draw that surface with the bloom/blur shader in effect
You can draw surfaces to surfaces (surface_set_target followed by draw_surface) so you can basically chain together as many different effects as you want this way, all you need is two surfaces (one source and one target) - you can reuse the same surfaces if you just ping-pong between them, too, saving memory.
 

Vulcano

Member
I'm trying but i dont know how i select source and target. And the surface_set_target is only for 1 of the shaders?
 
Last edited:

drandula

Member
By using two surfaces you can chain shaders as many as you want, you need to keep switching them. Bit like this:
GML:
surface_set_target(surf_ping);
shader_set(shd_1);
draw_surface(surf_pong,0,0);
surface_reset_target();
surface_set_target(surf_pong);
shader_set(shd_2);
draw_surface(surf_ping,0,0);
surface_reset_target();
surface_set_target(surf_ping);
shader_set(shd_3);
draw_surface(surf_pong,0,0);
surface_reset_target();
...
shader_reset();
(I am on phone so this might be not accurate, but it gives the idea)

And eventually you draw on screen the final surface, depends which you had as last target.

Earlier example assumed that surf_pong has something, like you have earlier drew application_surface to it.
Remember when working with surfaces, make sure they exist before you try using them.
 
Last edited:

Vulcano

Member
Then i draw 1 surface(shader 1), i chain the 2 shaders and then i draw the last surface(shader 2). Is correct?
 
Last edited:

Yal

🐧 *penguin noises*
GMC Elder
Then i draw 1 surface(shader 1), i chain the 2 shaders and then i draw the last surface(shader 2). Is correct?
Nonono
  1. Create two surfaces ALPHA and BETA with the same size
  2. Draw the stuff you want to apply the effect to onto the ALPHA surface(skip this step if you just want to draw the entire app surface)
  3. Set the first shader
  4. Set the target to the BETA surface
  5. Draw the ALPHA surface at 0,0
  6. Unset the surface target and shader
  7. Set the second shader
  8. Set the target to the ALPHA surface
  9. Draw the BETA surface at 0,0
  10. Unset the surface target and shader
  11. <Repeat until you have applied all shaders you want to use>
  12. Draw the last surface you drew things onto to the screen.
 
Top