|
scaling low-res screens |
Peter Hull
Member #1,136
March 2001
|
I am looking at making a 'retro' thing with pixel graphics - the base resolution is 160x120 pixels. Obviously some scaling will be needed - this is smaller than some icons on modern screens!
|
Chris Katko
Member #1,881
January 2002
|
Render normal then scale up using a selection of pixel filters. Pixel-perfect (can't remember exact term, just repeat the same source pixel, no blending) That's the usual stuff people offer. If it's 4:3, add black borders or add side artwork (but definitely give option for black borders). -> Consider picking a proper widescreen "low res" mode (or supporting it as an option). In 99% of cases, there's no need to leave dead areas in people's monitors. 4:3 isn't some magical ratio, and people will likely "feel" the retro just fine in 16:9--and worse, if you show black bars or artwork it INSTANTLY brings your eyes attention to the fact that it's 4:3, which means they're focusing on the bars and not the game experience! (Usually) the last thing you want in entertainment is to remind everyone that they're sitting in a chair and staring at a screen instead of "in the world". -----sig: |
dthompson
Member #5,749
April 2005
|
I've got an (albeit rather convoluted) setup for this in my game. The main draw code writes to the backbuffer (such that we can get antialiased primitives etc.), then the backbuffer is copied to a buffer bitmap, which is the same size as your 'retro' resolution, which is itself scaled over the backbuffer. 1// eg.
2#define RETRO_W 640
3#define RETRO_H 480
4
5ALLEGRO_BITMAP* buf;
6float x, y, w, h;
7
8void setup_scale()
9{
10 int factor_x, factor_y, factor;
11
12 buf = al_create_bitmap(RETRO_W, RETRO_H);
13
14 factor_x = al_get_display_width(disp) / RETRO_W;
15 factor_y = al_get_display_height(disp) / RETRO_H;
16 factor =
17 (factor_y < factor_x)
18 ? factor_y
19 : factor_x
20 ;
21
22 w = RETRO_W * factor;
23 h = RETRO_H * factor;
24 x = (al_get_display_width(disp) / 2) - (w/2);
25 y = (al_get_display_height(disp) / 2) - (h/2);
26}
27
28// call this in place of al_flip_display():
29void scale_and_flip()
30{
31 al_set_target_bitmap(buf);
32 al_draw_bitmap(al_get_backbuffer(disp), 0, 0, 0);
33 al_set_target_backbuffer(disp);
34 al_clear_to_color(al_map_rgb(0,0,0));
35 al_draw_scaled_bitmap(buf, 0, 0, RETRO_W, RETRO_H, x, y, w, h, 0);
36 al_flip_display();
37}
______________________________________________________ |
Edgar Reynaldo
Major Reynaldo
May 2007
|
dthompson said: I've got an (albeit rather convoluted) setup for this in my game. The main draw code writes to the backbuffer (such that we can get antialiased primitives etc.) You can enable anti-aliasing and multi-sampling on other bitmaps. There's no need to draw the backbuffer onto another buffer to draw back to the backbuffer... https://liballeg.org/a5docs/trunk/graphics.html#al_set_new_bitmap_samples Oh, well I guess that's part of the UNSTABLE api and only works on OpenGL. Peter Hull said:
Draw everything onto an off-screen bitmap and then stretch it to fill the window? Render everything normal size to the smaller buffer, then transform it or shader it onto the screen. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Peter Hull
Member #1,136
March 2001
|
Thanks all. Nice to have asked a programming question for once!
|
dthompson
Member #5,749
April 2005
|
Edgar Reynaldo said: Oh, well I guess that's part of the UNSTABLE api and only works on OpenGL. Yeah, compatibility was my main gripe with al_set_new_bitmap_samples. Would definitely use that once it's stabilised (and D3D-capable), but the back-and-forth method seems fast enough for now ______________________________________________________ |
Peter Hull
Member #1,136
March 2001
|
Has anyone got any code using CRT shaders (as mentioned by Chris Katko)? I've googled some shader code but not sure how to set it up in Allegro - is it as simple as al_use_shader and then blitting a bitmap?
|
Edgar Reynaldo
Major Reynaldo
May 2007
|
I've got a simple shader demo lying around somewhere - let me dig it up. It's pretty straight forward - you build and compile the shader, then you use it whenever you want to draw a bitmap using your shader. If you hold the left mouse button, it makes the texture all wavy. Very simple demo. I still don't understand it much myself which is why I haven't done more complicated things with it. But the basics of it is here : 1ALLEGRO_SHADER* create_shader(const char* fileNameVert, const char* fileNameFrag )
2{
3 ALLEGRO_SHADER* shader = al_create_shader(ALLEGRO_SHADER_GLSL);
4// if(!al_attach_shader_source(shader,
5// ALLEGRO_VERTEX_SHADER,
6// al_get_default_shader_source(ALLEGRO_SHADER_GLSL, ALLEGRO_VERTEX_SHADER)))
7 if(!al_attach_shader_source_file(shader, ALLEGRO_VERTEX_SHADER, fileNameVert))
8 {
9 printf("%s\n", al_get_shader_log(shader));
10 return NULL;
11 }
12 if(!al_attach_shader_source_file(shader, ALLEGRO_PIXEL_SHADER, fileNameFrag))
13 {
14 printf("%s\n", al_get_shader_log(shader));
15 return NULL;
16 }
17 if(!al_build_shader(shader))
18 {
19 printf("%s\n", al_get_shader_log(shader));
20 return NULL;
21 }
22 std::cout << " >>> "<< al_get_shader_log(shader) << " \n";
23
24 return shader;
25}
The vertex shader is stupid and just passes on data. void main(void) { gl_Position = ftransform(); gl_TexCoord[0] = gl_MultiTexCoord0; gl_FrontColor = gl_Color; } The fragment (pixel) shader just messes with the uv coordinates of the source. 1#version 110
2
3uniform sampler2D tex; // 0
4uniform float time; // effect elapsed time
5
6void main()
7{
8 float width = 1.0/4.0;/// In texels
9 float factor = 0.05;/// Factors from 0.01 to 0.1 seem okay
10 factor = factor*(1.0 + sin(time))/2.0;
11 vec2 uv = gl_TexCoord[0].xy;
12
13 float power = 1.0;
14
15 float xfact = (1.0 + sin((2.0*3.14159265*uv.x/width) + time))/2.0;/// [0,1.0)
16 xfact = pow(xfact , power);
17
18 float yfact = (1.0 + cos((2.0*3.14159265*uv.y/width) + time))/2.0;/// [0,1.0)
19 yfact = pow(yfact , power);
20
21 /// Modify x value by sin(2PI*x/50.0) and y value by sin(2PI*y/50.0)
22 uv = vec2(uv.x + factor*yfact , uv.y + factor*xfact);
23 gl_FragColor = texture2D(tex, uv);
24}
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|