• 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 Need help with MRT shader in GLSL (not ES)

Status
Not open for further replies.
Hi

I need help with a MRT (Multiple Render Targets) shader in GMS 2.

But first credits to the assets artist:
Michele "Buch" Bucelli: https://opengameart.org/users/buch

Test situation:
The view is smaller than the room and follows the player object.

I want to draw everything in the game (every object, every layer) to the application surface and a second surface at the same time using an MRT shader.
The first render target is the application surface. For testing, the shader just tints everything green.
The second render target is srf_2. For testing, the shader just tints everything red.


So I set up a test object:
In Create event of the test object I just set up the second surface and turn off the automatic drawing of the application surface:
Code:
srf_2 = -1;
application_surface_draw_enable(false);

In Draw Begin I set the two render targets and the shader:
Code:
if (!surface_exists(srf_2))
    srf_2 = surface_create(obj_camera.app_w, obj_camera.app_h); // app_w = gui_w/4;

surface_set_target_ext(0, application_surface);
surface_set_target_ext(1, srf_2);

shader_set(shader);

With this, GMS should draw everything to those two targets.

In Post-Draw I reset the render targets and the shader and then draw either surface to the screen depending on a toggle key:
Code:
shader_reset();
surface_reset_target();

if (keyboard_check(vk_space))
    draw_surface_stretched(application_surface, 0, 0, obj_camera.game_w, obj_camera.game_h);
else
    draw_surface_stretched(srf_2, 0, 0, obj_camera.game_w, obj_camera.game_h);

First question
is about something I solved, don't understand why it worked but would really like to understand though.

The result was not what I expected: The view follows the player, but on the screen it looks like the view is frozen and all I can see there is some kind of clipping or updating error:
https://www.dropbox.com/s/kif2z8nyxx9labg/hlsl_draw_begin_bug.gif?dl=0

Just so by accident I found the solution of this first problem: when setting the 2 render targets and the shader in pre-draw event instead of draw begin event, everything looks as expected (on windows with HLSL11):
https://www.dropbox.com/s/8glz6qwq38xmg8w/hlsl_pre_draw_fixed.gif?dl=0

So I would like to know: what changes between pre-draw and draw begin to make that difference?


Second question:
Then I translated the shader to GLSL and tested on Ubuntu.

If I set the two render targets in draw begin there, the same clipping error occurs.

If I set the two render targets in pre-draw - which fixed the problem on Windows/HLSL - then the second surface stays black with an alpha of 0:
https://www.dropbox.com/s/v1172tbvzhvrlna/glsl_pre_draw_bug.gif?dl=0

If I clear the second surface i.e. green with alpha 1 before setting the shader, the second surface just stays green with alpha 1. So apparently the second render target is not being written to.

Here's the fragment shader:
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main() {
    vec4 base_col = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );

    gl_FragData[0]        = base_col * vec4(0.5, 1.0, 0.5, 1.0);
    gl_FragData[1]        = base_col * vec4(1.0, 0.5, 0.5, 1.0);
}

So how can I make this MRT shader work on Ubuntu?
What's the resaon the GLSL shader is not writing to the second surface?
(yes, I diuble checked the shader type. It's st to GLSL, not GLSL ES :) )


And if anyone wants/is willing to check the test project (light-weight and documented) here's a download link:
https://www.dropbox.com/s/a3n1gbsbilhumif/MRT_test.yyz?dl=0
 
Last edited:
Status
Not open for further replies.
Top