• 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 Making vertex buffers pixelated

Bingdom

Googledom
Hello GMC,

So from my understanding, vertex buffers/ primitives are shot straight to the GPU. Ignoring all game resolutions and only using your monitor's display resolution.

I know to get texture coords, it's v_vTexcoord. I'd like to know an equivalent or similar way to this. The problem I'm having is whenever I try to draw stuff using gms' draw functions, they draw relative to the display (as I mentioned earlier).
Since I'm upscaling the game, sprites in the game have room to move by "sub-pixels". I need to take account of that for the trails. I'm beginning to think I might need to rethink about this approach, as to there's no way that the trail is going to both have the correct offsets and keep the structure of the pixelization consistent.

Here's an image to show my problem. Look at the trail from the projectiles. I'm trying to make the projectile trail as pixelated as the rest of the game
upload_2018-3-3_19-10-17.png

I don't want to use separate surfaces nor do I want to make a fullscreen surface. There's going to be a lot of these bullets and the surface will have to vary in sizes. I figured a shader would be much faster in this case.

In the fragment part of the shader, I've done this:
Code:
gl_FragColor = v_vColour * texture2D( gm_BaseTexture, floor(v_vTexcoord*res)/res).a;
As suspected, it did nothing.

Then for the vertex part, I changed this:
Code:
vec4 object_space_pos = vec4( floor(in_Position.xy/resScale)*resScale, in_Position.z, 1.0);
This is close, however, it looks like it only adjusts the vertices of the vertex buffer, and not modify the rest of how it's drawn. It also wouldn't have the "sub-pixels", but I think that's an error on my part.

Thanks for reading.
 
Last edited:

Bingdom

Googledom
No?
The manual said:
When you create a vertex buffer you are creating the lowest level of graphics data, so when you draw all that happens is we send your buffer directly to the graphics card
I tried resizing the application surface down before drawing, then moving it back to normal after drawing. Nothing changed.

It seems dependant on the final window/application/surface size if that's what you mean. Yeah, I could've worded it better. I was making the game in fullscreen and forgot about windows and stuff.
 
Okay, a number of different things seem to be going on here. What are you doing exactly? If you want something to have large "pixels", you usually draw it on a small surface, and then draw the surface stretched out.
 

Bingdom

Googledom
Yes, that is one solution.

However, if I target the mobile platform (where surfaces are a big killer), I would want to take the fastest solution for more mobile coverage.

Having a shader that only adjust where the pixel is drawn sounds a lot faster than a whole surface that serves a small purpose.
 
You cannot adjust where an individual pixel is drawn.

You might be able to snap texture coordinates to a nearest grid point though. That'd be done in the fragment shader though.

How are you determining the basic shape of the trail?
 
Last edited:

Bingdom

Googledom
That's not what I meant, but yes, you're correct.

I've already tried that.
In the fragment part of the shader, I've done this:
Code:
gl_FragColor = v_vColour * texture2D( gm_BaseTexture, floor(v_vTexcoord*res)/res).a;
As suspected, it did nothing.

Then for the vertex part, I changed this:
Code:
vec4 object_space_pos = vec4( floor(in_Position.xy/resScale)*resScale, in_Position.z, 1.0);
This is close, however, it looks like it only adjusts the vertices of the vertex buffer, and not modify the rest of how it's drawn.
Edit: I'm using a vertex buffer for the trail.
 
Last edited:
I've been thinking some more about this. I just don't think you will be able to get good results with that approach. So mobile has problems even with small surfaces?
 

Bingdom

Googledom
I'm currently running 3 surfaces and it works perfectly fine on my phone. However, obviously this doesn't apply to all phones. Maybe I've already limited a range of phones and another small surface may not make a difference. I'm not sure. *shrugs*

If there's really no way via a shader, then I guess I'd have to go for the surface route. :(
 
I

icuurd12b42

Guest
how about simply resizing the application_surface really...
 

Bingdom

Googledom
how about simply resizing the application_surface really...
Unfortunately, that is not what I have in mind in terms of game design. The native resolution is too small. It would be a jittery mess.

Unless you're talking about resizing it back to normal after drawing - In case you've missed it:
I tried resizing the application surface down before drawing, then moving it back to normal after drawing. Nothing changed.
EDIT: Oh, I think I realised a mistake.

EDIT2: Nope, still works as described

EDIT3: In case you're curious about how I implemented it, here it is.
Code:
    surface_resize(application_surface,view_wview,view_hview);
    surface_set_target(application_surface);
        //Move relative to view coordinates
        d3d_transform_add_translation(-view_xview,-view_yview,0);
        //Had to upscale the coordinates/size, otherwise they'll appear top-left of screen.
        d3d_transform_add_scaling(_s,_s,1);
        with(oBullet) {
            vertex_submit(vBuff, pr_trianglestrip, -1);
        }
        with(oBulletDeath) {
            vertex_submit(vBuff, pr_trianglestrip, -1);
        }
        d3d_transform_set_identity();
    surface_resize(application_surface,view_wport,view_hport);
    surface_reset_target();
view_w/hview carries the view size in room.
view_w/hport is pretty much display_get_width/height()

I also tried drawing without surface_set_target(application surface).
Same result.
 
Last edited:

Mike

nobody important
GMC Elder
You should only have to set the application surface once at the start. If your game is (say) 320x200 and you window 1024x768, then setting the app surface to 320x200 at the start would fix the issues and result in no scaling.

You also don't need to set it, as it's always created and set before the game renders (in the draw event).

So resize it on a create event - once, then just draw normally.
 

Bingdom

Googledom
Yes, I'm aware of this and it isn't the problem. I'm resizing the app surf again because I want the final resolution of the game to deal with "sub-pixels" E.g. Having a smooth rotation with the gun (look at the screenshot). Thanks though.

I mentioned it because it gave out a different result (I had to use transformations). I said afterwards I did it without setting it.

At this point, I'm beginning to think I'm going for an impractical idea (or a limitation with GLSL ES or GMS).

Edit: Oh, and for the rest of you who are trying to help, thank you too.
 
Last edited:

sylvain_l

Member
If there's really no way via a shader, then I guess I'd have to go for the surface route
At this point, I'm beginning to think I'm going for an impractical idea (or a limitation with GLSL ES or GMS).
I'm not a shader guru, so; it's more my intuition then my expertise:
All you need to do is just resampling the the sprite on a 4x4 grid for example, no ? (of cause without resizing it x4)
 

Bingdom

Googledom
All you need to do is just resampling the the sprite on a 4x4 grid for example, no ? (of cause without resizing it x4)
I don't have the answer on the top of my head, If it was a sprite it would be one of the 2 first code blocks I've shown (or both could work).

I'm trying to apply this to a vertex buffer, not to a sprite.
 
Top