Setting a low resolution to mimic older games.
BlitzMax Forums/OpenGL Module/Setting a low resolution to mimic older games.
| ||
Hello, Recently I have wanted to mimic lower resolution games using OpenGL. I need to set the OpenGL display window to run in a very low resolution. I've been kindly helped but I'm not quite advanced enough in C++ to know what is going on in this code. I was told that making a low resolution screen in OpenGL involved writting the buffer into a texture then making a quad that takes the texture and blows it up to the screen resolution, be it 640x480 or whatever else. I would really appreciate some help if possible. I'm on a very tight timeline to finish this small project. I can't use the native graphics commands in Bmax because vector drawing remains at the screen resoultion. Here is some of the code in C |
| ||
One way to do it is the way you mentioned, where you draw a smaller-than-screen-size version of your game either onto the backbuffer or onto a texture, and then either you draw that texture full-screen size or you grab that portion of the backbuffer into a texture and draw it full-screen. However, that really is involving steps that you don't need to take. What you need to do is correctly define your viewing Frustum ie your projection matrix, with which in a single call it's possible to set up a scaled display. If you define the viewing area for a 800x600 screen as 0,0 through 400,300, for example, anything you draw in the top left 400x300 area of your screen will fill the whole screen with 2x2-sized `pixels`. Similarly if you said your projection covers coordinates 0,0 through 200,150 then you'll get 4x4-sized pixels. see the glFrustum, glPerspective or glOrtho2D commands. With this method you don't need to play with textures at all and you don't have the extra overhead of redrawing them. |
| ||
Yes but won't vector based drawing commands still appear as single pixel drawings? I don't think that the vector based drawing commands will scale will they? The raster based images on quads will probably size correctly but lines and polygons will still be a single pixel thick. |
| ||
Yes they will. If you scale the projection matrix you are telling it to scale how it SEES the game world, and anything you `draw` you are drawing as geometry within the game world, so it will all be interpreted and scaled by the matrix. |
| ||
If possible, would you mind showing a quick bit of code? It would help me immensely to see it done correctly first. |
| ||
See the documentation for glOrtho or gluOrtho2D: http://www.talisman.org/opengl-1.1/Reference/glOrtho.html It's something like.. glMatrixMode GL_PROJECTION glLoadIdentity() glOrtho 0,400,0,300 glMatrixMode GL_MODELVIEW which would give you a 2x2 pixel size on an 800x600 screen. You might need to call glViewport or SetViewport (BlitzMax) afterwards e.g. SetViewport 0,0,400,300 - not sure. Give it a try. |
| ||
I've done as you said, the lines and vector based drawing commands still draw in the original screen resolution.SuperStrict Framework brl.GLGraphics GLGraphics 640, 480 glMatrixMode GL_PROJECTION glLoadIdentity() glOrtho 0, 160, 0, 140, 0, 1 glMatrixMode GL_MODELVIEW glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT glBegin(GL_LINE_LOOP) glColor3f(.75, .25, .75) glVertex3f(0, 0, 0) glVertex3f(0, 32, 0) glVertex3f(32, 32, 0) glVertex3f(32, 0, 0) glEnd() glViewport(0, 0, 160, 120) Flip WaitKey() |
| ||
Ahh. Oh well. I thought it would work but apparently not. It does scale the coordinate system correctly but the actual drawing operations are not scaled. You'd need to maybe try changing the line thickness. It would work fine with textures/images. Maybe write your own line routine which instead of drawing using GL_LINE_LOOP draws using GL_QUADS with image data - then the image of the line piece will scale. |
| ||
Yes, as you notice that is why everything was first rendered to a texture. Vector based drawing commands that have no mapping will maintain the window resolution. The initial code renders all vector objects and other drawing commands to a raster texture then expands the texture into a quad. Now, is anyone willing to try to get this working from C code? |
| ||
retrorender.bmx Basically, import this into your program and call 'RenderRetro(width,height)', passing the resolution you wish. The rest is taken care of via hooks. |
| ||
OK, I see a flash of the screen in the correct resolution. When should I call the function? I think I have it in the wrong place perhaps. Thanks for all your help here. It is sort of an unique task that I ask for assistance with.Strict Framework brl.GLGraphics GLGraphics 640, 480 Include "retro_render.bmx" glMatrixMode (GL_PROJECTION) glOrtho(0, 640, 480, 0, - 1000, 1000) glMatrixMode(GL_MODELVIEW) While Not KeyDown(KEY_ESCAPE) glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT RenderRetro(160, 120) glBegin(GL_LINE_LOOP) For Local i:Float = 0 To 10 glColor3f(i / 10, 0.0, 1.0) glVertex3f(80 + Cos(i * 36) * 40, 60 + Cos(i * 36) * 30, 0) Next glEnd() Flip Wend |
| ||
Yep, just call it once after GLGraphics. Sorry about that. By the way, you may as well just Import it instead of including it. It'll speed up compile time. |
| ||
I seriously suggest getting rid of the ReadPixels and reuploading of the texture, and instead use glCopyTexImage2D or glCopyTexSubImage2D directly from the backbuffer to an existing texture. It is MUCH faster than using pixmaps. |
| ||
ImaginaryHUman, could you provide an example of how this is done? I'm not trying to be a pain but I'm still struggeling a bit. |
| ||
Look at the documentation for glCopyTexSubImage2D() in the standard OpenGL reference online. You create a dummy texture with glTexImage2D like you already do in your code, but you don't pass any data to it (set the pixels pointer to Null). Then you just call glCopyTexSubImage2D() with the appropriate rectangle to copy it into the currently bound texture. |