Shaders draw pixel array with shader?

S

Shadowblitz16

Guest
can someone tell me how to draw a pixel array with a shader?

this is what I have been trying to do.
Code:
/// shd_draw

uniform int   tilesize;
uniform int   tileset[4]; 
uniform int   palette[2];
uniform int   tile;
uniform int   dx;
uniform int   dy;

int RGBA;

vec4  drawColor;
vec2  drawPos;

void main()
{
    // yo and xo stand for y and x offset
    for (int yo=0; yo<tilesize; yo++)
    for (int xo=0; xo<tilesize; xo++)
    {
        RGBA = palette[tileset[tile][xo+yo*tilesize]]; //Might want to make consider alpha in front
       
        //Convert RRGGBBAA to vec4 of floats ranging from 0.0 to 1.0
        drawColor = vec4(float((RGBA >> 32) & 0xFF) / 255.0, float((RGBA >> 16) & 0xFF) / 255.0, float((RGBA >> 8) & 0xFF) / 255.0, float((RGBA >> 0) & 0xFF) / 255.0);
       
        //Convert pos and loop offset to vec2 of floats ranging from 0.0 to 1.0 
        drawPos   = vec2(float((dx+xo) / tilesize),  float((dy+yo) / tilesize)
       
        //Set pos and color
        gl_Position  = drawPos;
        gl_FragColor = drawColor;
    }
}
but it gives me this error
Code:
Fragment Shader: shd_draw at line 23 : 'expression'
Fragment Shader: shd_draw at line 26 : ''
at this point I'm not even sure if it will draw pixels in world space instead of surface space
 
S

Shadowblitz16

Guest
what do you mean? fragment shaders can draw more then 1 pixel
 
C

Crazy Star

Guest
I mean that you run the shader once for each pixel to be drawn. What you're trying to do is draw multiple places at one time, but you're only setting
gl_FragColor to something new. You'd need instead to test if each drawn pixel is included in an array and only draw it then. But this isn't how shaders are meant to be used. You should just pass it a sampler.
 
S

Shadowblitz16

Guest
I don't understand. can you post some example code?

I am trying to draw this pixel array as fast as possible that's why I wanted to do this all in a shader

EDIT: here is the new code (fixed some errors)
Code:
/// shd_draw

uniform int   tilesize;
uniform int   tileset[4]; 
uniform int   palette[2];
uniform int   tile;
uniform int   dx;
uniform int   dy;

int RGBA;

vec4  drawColor;
vec2  drawPos;

void main()
{
    // yo and xo stand for y and x offset
    for (int yo=0; yo<tilesize; yo++)
    for (int xo=0; xo<tilesize; xo++)
    {
        RGBA = palette[tileset[tile]]; //Might want to make consider alpha in front
       
        //Convert RRGGBBAA to vec4 of floats ranging from 0.0 to 1.0
        drawColor = vec4(float((RGBA[xo+yo*tilesize] >> 32) & 0xFF) / 255.0, float((RGBA[xo+yo*tilesize] >> 16) & 0xFF) / 255.0, float((RGBA[xo+yo*tilesize] >> 8) & 0xFF) / 255.0, float((RGBA[xo+yo*tilesize] >> 0) & 0xFF) / 255.0);
       
        //Convert pos and loop offset to vec2 of floats ranging from 0.0 to 1.0 
        drawPos   = vec2(float((dx+xo) / tilesize),  float((dy+yo) / tilesize));
       
        //Set pos and color
        gl_Position  = drawPos;
        gl_FragColor = drawColor;
    }
}
 
Last edited by a moderator:
C

Crazy Star

Guest
The short version is that you haven't been studying how to use shaders or what they are before you're trying to do this. I suggest trying some basic stuff first like trying to change the color and position of what you draw.
Drawing things fast is not reason enough on it's own to use shaders. They're meant to create visual effects like blur, blends etc.

I looked in the manual and I couldn't find a way to pass in a sampler other than the one used by default so sorry about that.

Edit: Oh apparently you use texture_set_stage for that..
 
Last edited by a moderator:

Binsk

Member
Okay, not sure what you are trying to do but here's some info on shaders that you seem to need.

When you render something it is composed out of triangles which are composed of vertices. When you draw a sprite it is actually two triangles (six vertices) with a texture stretched over them.

These points are passed to the vertex shader where you can modify and create vertex related data. ALL the code in your vertex shader is performed on each vertex separate from each other and in parallel.

Math is done, the system finds which pixels need to render and then the entire fragment shader is called for every RENDERED pixel separate from each other and in parallel. The fragment shader is where you determine the COLOR of the pixel to draw.

This happens for EVERYTHING you draw, even if you don't specify a shader (GM still uses a default one).

Trying to draw all your pixels at once is, first not possible and even if it was it would be highly inefficient. GPUs are designed with hundreds sometimes thousands of cores which are automatically used in parallel. You are trying to limit everything to one core.

Better ways to speed things up is to avoid draw calls in GameMaker. Every time you change the alpha or color with draw calls the system has to send a new batch to the GPU.

Drawing more polygons (aka sprites) with a single call much faster than multiple calls with fewer polygons (as the later requires more batches to be sent to the GPU).

I know GM does stuff in the background to try and optimize this, but i would focus on this rather than the shader if you are this desperate for a speed boost.

Also, as a last note, if you are having speed issues are you sure they are GPU bound and not CPU bound?
 
Top