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

how to interpret a vertex_format_add_custom

Edgamer63

Member
Hello all :D !

I was wondering how to interpret a vertex_format_add_custom(vertex_type_colour,vertex_usage_position) in a shader, that because i want to use only 8 bytes for each vertex (for example 24 bytes for a triangle instead of 48 bytes). That for a better performance, and use less RAM.

The vertex format is:
vertex_format_begin();
vertex_format_add_custom(vertex_type_colour,vertex_usage_position);
vertex_format_add_color();
format=vertex_format_end();


Any working solution for this? I've searched and found nothing here for now.

I've tryed of course something, but as far i couldn't do it yet that can work.
GML:
//Vertex Shader
attribute vec4 in_Position;                  // (x,y,z)
//attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 pos = vec4( in_Position.r, in_Position.g, in_Position.b, 1.0)
    pos.r*=32.;
    pos.g*=32.;
    pos.b*=32.;
    
    vec4 col = vec4(in_Colour.rgba);
    
    col.r=255.;
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * pos;
    
    v_vColour = col;
    v_vTexcoord = in_TextureCoord;
}
GML:
//Fragment
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    gl_FragColor = v_vColour;
}
But this actually gives me errors.

I need a hero :) .
 

Bart

WiseBart
There's a semicolon missing at the end of this line:
C:
vec4 pos = vec4( in_Position.r, in_Position.g, in_Position.b, 1.0);
In GML such syntax is allowed, in shaders you have to use them.

You should also be able to use this format instead:
GML:
vertex_format_begin();
vertex_format_add_color();
vertex_format_add_color();
format=vertex_format_end();
In the shader you can then use in_Colour1 and in_Colour2, if I'm not mistaken.
The indices can be 0 and 1 as well, though can't test at the moment.

Hope this helps a bit :)
 

Joe Ellis

Member
Last time I checked, I realized only vertex_usage_color and vertex_usage_texcoord work in the custom format thing.
But both of those work fine with any number, doesn't have to be 0-1 like color normally is.
But I don't think there's any way to make the vertices take up less bytes, each attribute value takes up 4 per axis.
I'm not sure there's any way to get around that
 

Bart

WiseBart
But I don't think there's any way to make the vertices take up less bytes, each attribute value takes up 4 per axis.
I'm not sure there's any way to get around that
It can be done by using color attributes.

For example, here's something you can do that works:
GML:
vertex_format_begin();
vertex_format_add_color();    // x, y, z, u
vertex_format_add_color();    // x, y, z, v
vertex_format_add_color();    // nx, ny, nz, color_index
format=vertex_format_end();
Use 2 bytes for each of x, y and z, store the high bytes in the first attribute , low bytes in the second attribute and restore the actual values inside the shader. u and v go in the fourth (i.e. alpha) component of each attribute, each using 1 byte.
Normals each take 1 byte and the vertex color can be done with a lookup table so you just need to store the index.
12 bytes for what'd normally take 36 bytes with still a decent precision for at least the position.

For the precision inside the shader you could try changing it to mediump or lowp. Not sure if that actually does anything in GM's shaders, though.
 

Joe Ellis

Member
Ah maybe it does use 8 bits per component with the color attributes, although, I don't think it does cus if you make a custom format and add a color with vertex_usage_color you can set it to anything you want, far more than 255 and with decimals. Do you think it knows whether you've used "vertex_format_add_color" or "vertex_format_add_custom(vertex_type_float4, vertex_usage_color)"?
It might do, but I'm guessing that the shader always takes in every attribute component as 32 bit, cus you're able to submit any vertex buffer to it regardless of the format, and if in_color exists it takes it whether it's 4269.2465787(not possible with 8 bits) or 0.13725490196078431372549019607843 (35 / 255)
 

Bart

WiseBart
That's indeed what it looks like, although the precision qualifier may (?) affect that.
Colour attributes do use 8 bits per component inside a buffer.
But if you look at the shader code it can be misleading because they are linked to it in a way that they end up there as vec4's, so 4 floats, or 32 bits per component (at mediump precision).
 
Last edited:

Joe Ellis

Member
Hmm, yeah I think with the process that converts a buffer to a vertex buffer, they are 8 bit in the buffer but get written to a vertex buffer in 32 bit. (I don't know for certain) It could be that they're 8 bits in the vertex buffer, but when sent to the vram they're 32 bit.
I know that they're handled in 32 bit in the shader, so when the values are sent to the vram they'll get converted to 32 bit if they are 8 bit.
Unless, maybe if you set the lowp in the shader, I think that's the part that makes the difference, but I've never actually experimented with that.
The thing I was saying was that concerning ram, the attributes in vram are always 32bit by default, so making a custom vertex format won't change the byte usage
 

Edgamer63

Member
Oh no :c , this thing seem to be impossible yet, even trying with this code:
GML:
//attribute lowp vec4 NORMAL;                  // (x,y,z)
attribute lowp vec4 in_Position;                  // (x,y,z)
attribute vec4 in_Colour;                    // (r,g,b,a)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    //vec4 pos = vec4( NORMAL.r, NORMAL.g, NORMAL.b, 1.0);
    vec4 pos = vec4( in_Position.r, in_Position.g, in_Position.b, 1.0);
    //vec4 pos = vec4( in_Colour2.r, in_Colour2.g, in_Colour2.b, 1.0);
   
    /*
    pos.r*=32.;
    pos.g*=32.;
    pos.b*=32.;
    */
   
    vec4 col = vec4(in_Colour.rgba);
   
    col.r=255.;
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * pos;
   
    v_vColour = col;
    //v_vTexcoord = in_TextureCoord;
   
}
And also this:

Code:
vertex_format_begin();
vertex_format_add_color();//x,y,z
vertex_format_add_color();
format=vertex_format_end();
Mhm ... seems to be not possible, at least not yet. However, it's still interesting for a challenge to who can possibly do it anyway hahahah xD. Kinda hard to go, maybe impossible, but anyway a good initiative to go out of boundaries of GML to be honest.

Maybe A Good dev will solve it some day.
 

Bart

WiseBart
It is possible. Here's a quick example with a vertex format that uses only 4 bytes, 3 of them to store the x, y and z components with 8 bits of precision and 1 to store a u value on a 1D texture:

Tiny Vertex Format

Not sure if the lowp actually does anything, though.

Subsequent color attributes that you define in the vertex format can be referred to in the shader as "in_Colour2", "in_Colour3", ...
So something like this works:
GML:
vertex_format_begin();

    vertex_format_add_color();
    vertex_format_add_color();
    vertex_format_add_color();

format = vertex_format_end();
C:
// Shader attributes
precision lowp float;        // this may do something?
attribute vec4 in_Colour;
attribute vec4 in_Colour2;
attribute vec4 in_Colour3;
The thing that isn't clear to me is how the vertex buffer is stored in VRAM.
Is it stored using the vertex format that you define in gml or is it stored using the attribute types that you use inside the shader, as also hinted at by @Joe Ellis.
The latter would make defining those tiny vertex formats largely useless since it'd actually increase the size instead of decrease it.
 
Last edited:

Edgamer63

Member
It is possible. Here's a quick example with a vertex format that uses only 4 bytes, 3 of them to store the x, y and z components with 8 bits of precision and 1 to store a u value on a 1D texture:

Tiny Vertex Format

Not sure if the lowp actually does anything, though.

Subsequent color attributes that you define in the vertex format can be referred to in the shader as "in_Colour2", "in_Colour3", ...
So something like this works:
GML:
vertex_format_begin();

    vertex_format_add_color();
    vertex_format_add_color();
    vertex_format_add_color();

format = vertex_format_end();
C:
// Shader attributes
precision lowp float;        // this may do something?
attribute vec4 in_Colour;
attribute vec4 in_Colour2;
attribute vec4 in_Colour3;
The thing that isn't clear to me is how the vertex buffer is stored in VRAM.
Is it stored using the vertex format that you define in gml or is it stored using the attribute types that you use inside the shader, as also hinted at by @Joe Ellis.
The latter would make defining those tiny vertex formats largely useless since it'd actually increase the size instead of decrease it.
This work pretty well, But i don't know how to add the normal colors after the 4byte containing x,y,z,u values, for getting a 8 byte format.
Help me please :( . I want it to work with something like this:
GML:
vertex_format_add_color();//x,y,z
vertex_format_add_color();//r,g,b,a
Also, the way it's stored in vram is the size in bytes of the vertex uploaded by vertex_submit.

But, only when using vertex_submit() , because when using d3d_* functions it uses CPU or even disk instead of RAM (i tested it out before).
The thing is that d3d_draw_model* is not very workable with buffer_poke(write) and buffer_peek(read) functions as vertex_submit (Yes, i dont use vertex_colour, i use buffer_poke and vertex_create_buffer_from_buffer() ).
 
Last edited:

Bart

WiseBart
What part isn't working when you use those 2 color attributes? Did you also add an attribute in_Colour2 to the shader?
Not sure if I understand where your current issue is at the moment. Could you explain in a bit more detail?

Also, the way it's stored in vram is the size in bytes of the vertex uploaded by vertex_submit.
That's incredibly interesting! So that means that some vertex formats could easily be reduced to just a fraction of the "normal" size in VRAM.
 

Edgamer63

Member
That's incredibly interesting! So that means that some vertex formats could easily be reduced to just a fraction of the "normal" size in VRAM.
Of course, that's why i opened this thread :) .

Also, it's solved, i added the color attribute, and everything works fine, now implementing it to my game. Is the double of efficient than before, so that means even more FPS.

Thank you Wise Bart or Bart :D .
 

Bart

WiseBart
Ah, nice to hear you got it working!
I'll be experimenting a bit more with this myself, too. All very interesting!
 
Top