Cord system and units? - opengl

How do I change default cord system and units in OpenGL?
Right now it's using the default, meaning it goes from -1.0 (left) to 1.0 (right) with 0 being the origin (same with Y, -1.0 being top, 1.0 being bottom).
Optimally I would 1) want to change units to roughly same number of pixels. For example, on an 800x600 display have it go from -400 to 400 (on x) and -300 to 300 (on y). Seems like it would be easier to work with than -1.0 to 1.0
2) Bonus points: how do I change the x/y? One game engine had I seen had it go from 0 to maxWidth and 0 to maxHeight.
That is, 0,0 was top left and 800,600 was bottom right. (0, 600 would be left bottom and 800,0 would be top right)
I think these both have to do with the viewpoint command, but don't know if I fully understand it.

First answering your last point: There is no "viewpo i nt" commant. There is glViewport which defines the mapping from so called clip space [-1,1]×[-1,1]×[-1,1] into window/screen space — important: glViewport doesn't set some clipping, so if your viewport only covers some smaller, middle part of your window, things that exceed the viewport in rendering may/will cause artifacts outside the viewport. Scissor testing (enabled and set with *glEnable(GL_SCISSOR_TEST)* and glScissor) does this kind of clipping, which also works within the viewport (nice for implementing selection rubber bands!).
Now to cover your first question: OpenGL's coordinate system is whatever you want it to be; in OpenGL-3.1 and OpenGL-4 there's no default coordinate system at all! In OpenGL-2 and below there are a number of so called transformation matrices, most importantly modelview and projection.
You can think projection to be some kind of a camera's lens (although it works entirely differently). What is does is, it transforms the world (or modelview) space into the aforementioned clip space. It is this projection matrix, that allows you map any affine coordinate system into clip space. OpenGL before version 3 provides you helper functions glFrustum and glOrtho for the most oftenly used projections: Perspective and Ortho.
Let's construct some projection ourself (it's an ortho, but I'd like to show how things work on the math side). Say you'd like to map x in [0; 200], y in [0; 100] to [-1; 1] (left to right), [-1,1] (top to bottom), and leave z as it is. Then
x_clip = -1 + x*(1-(-1))*(200-0) = -1 + x*2/200
y_clip = 1 + y*(-1 1 )*(100-0) = 1 + x*(-2)/100
z_clip = z
This translates into the following matrix:
2/200 0 0 -1
0 -2/100 0 1
0 0 1 0
0 0 0 1
You could now put this into the projection matrix using glLoadMatrix.
The modelview matrix is used for moving stuff around in the world space. It's also used to define the viewpoint: OpenGL has no camera. Instead we just move the whole world in an opposite way to how we'd moved a camera within the world to the desired viewpoint (this time …point, not …port!)

glOrtho():
#include <GL/glut.h>
unsigned int win_w = 0;
unsigned int win_h = 0;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, win_w, win_h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3ub(255,0,0);
glPushMatrix();
glScalef(50,50,50);
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(1,0);
glVertex2f(1,1);
glVertex2f(0,1);
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void reshape(int w, int h)
{
win_w = w;
win_h = h;
glViewport(0, 0, w, h);
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(800,600);
glutCreateWindow("Ortho);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}

Related

glFrustum isn't creating perspective

I'm trying to create a 3D manipulation program using C++ and openGL. I'm relatively new to openGL so I often have to look up the documentation to find the right function to do what I want. I thought I had a good understanding of orthogonal vs perspective projections (in that glOrtho creates an orthogonal projection where different z-values don't look different and glFrustum creates a perspective projection where z-values that are closer look bigger). However, when I swap out glOrtho and glFrustum in my program, I don't see any difference. I replicated a small program below that shows the effects. For reference, I'm using openGL with freeglut.
#include "GL/freeglut.h"
void initFunc()
{
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void displayFunc()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glColor3f(1.0f, 1.0f, 0.0f);
glLineWidth(1.0f);
glutWireTeapot(0.3);
glTranslatef(0, -0.5, -0.5);
glutWireTeapot(0.3);
glutSwapBuffers();
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitWindowSize(600, 600);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("Teapot Perspective");
initFunc();
glutDisplayFunc(displayFunc);
glutMainLoop();
}
I'm drawing two teapots slightly offset in both the y and z axes. From what I understand, the glOrtho should render the two teapots as identical with only a y offset, whereas the glFrustum should render one of them bigger than the other. However, both of them render the teapots identically.
Am I missing something here? Are there other steps I have to take to properly set up a perspective projection? Or am I misunderstanding how glFrustum works? I've also tried using gluPerspective instead of glFrustum but I can't seem to find the right values to use. I experimented with a FOV of 90, aspect of 1, and various z values but they all either produce no teapot, or a teapot distorted beyond recognition. Furthermore, the gluPerspective appears to have different behavior than a glFrustum call with corresponding parameters. I'm not sure what I'm missing here.
At Orthographic Projection the coordinates in the view space are linearly mapped to clip space coordinates and the clip space coordinates are equal to the normalized device coordinates, because the w component is 1 (for a cartesian input coordinate).
The values for left, right, bottom, top, near and far define a box. All the geometry which is inside the volume of the box is "visible" on the viewport.
The Orthographic Projection Matrix, defined by glOrtho is:
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2/(r-l) 0 0 0
y: 0 2/(t-b) 0 0
z: 0 0 -2/(f-n) 0
t: -(r+l)/(r-l) -(t+b)/(t-b) -(f+n)/(f-n) 1
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).
A perspective projection matrix can be defined by a frustum (glFrustum).
The distances left, right, bottom and top, are the distances from the center of the view to the side faces of the frustum, on the near plane. near and far specify the distances to the near and far plane on the frustum.
r = right, l = left, b = bottom, t = top, n = near, f = far
x: 2*n/(r-l) 0 0 0
y: 0 2*n/(t-b) 0 0
z: (r+l)/(r-l) (t+b)/(t-b) -(f+n)/(f-n) -1
t: 0 0 -2*f*n/(f-n) 0
A specification like this from you question:
glFrustum(-1, 1, -1, 1, -1, 1);
does not define a proper frustum, because the value for the near plane is negative and the value for the far plane is positive.
If you would check for OpenGL errors (by glGetError), then you would get an INVALID_OPERATION error.
OpenGL 4.6 API Compatibility Profile Specification; 12.1. FIXED-FUNCTION VERTEX TRANSFORMATIONS; page 501:
>
void Frustum( double l, double r, double b, double t, double n, double f );
the coordinates (l b −n)T and (r t −n)T specify the points on the near clipping plane that are mapped to the lower left and upper right corners of the window, respectively (assuming that the eye is located at (0 0 0)T). f gives the distance from the eye to the far clipping plane.
Errors
An INVALID_VALUE error is generated if n <= 0, f <= 0, l == r, b == t, or n == f.

OpenGL showing more/less of the world through resize

So a lot of questions online about resizing have been about maintaining the right ratios and avoid stretching etc. From what I understand, this would be done by setting the new ratio with gluOrtho2D.
However, I wasn't sure exactly how to go about showing MORE and LESS of the world upon resize. E.g. you have a plane that could travel from 0 to 100 along the x axis. Upon resizing, it should now (still same size) travel from 0 to 200.
EDIT: so what I mean is, I want everything in my game to stay the same size as before, but the "sky" if you will, should be bigger upon the resize, and my plane should be able to fly into that sky (since currently I have code that limits it to within the screen).
Similarly, if my screen is smaller, then the plane should no longer be able to fly to the section of the 'sky' that no longer exists
Initially, I'm setting up my program using the following lines, where everything about the game is stored in 'game', and XSize, YSize returns the size of the screen.
void init(void) {
glClearColor(0.0, 0.0, 0.3, 0.0); /* set background color to a dark blue */
glColor3f(1.0, 1.0, 1.0); /* set drawing color to white */
glMatrixMode(GL_PROJECTION);
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLoadIdentity();
gluOrtho2D(0, game.getXSize()*game.getAspect(), 0, game.getYSize() / game.getAspect()); /* defines world window */
}
int main(int argc, char *argv[]) {
game = GameManager(GAMENAME, 1000, 750, 60);
/*SETUP*/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(game.getXSize(), game.getYSize());
glutCreateWindow(GAMENAME);
/*Other GLUT main function lines here */
glutReshapeFunc(resize);
}
When I try to set up the gluOrtho2D in resize, however, the program sets up the background and stops drawing anything at all.
void resize(int w, int h){
game.setScreenSize(w,h);
glViewport(0,0,width,height)
const GLfloat aspectRatio = (GLfloat)game.getXSize() / (GLfloat)game.getYSize();
gluOrtho2D(0, game.getXSize()*game.getAspect(), 0, game.getYSize() / game.getAspect());
}
I have, of course, managed to just use glViewport(0,0,w,h) by itself, but that's pretty much the same as not doing anything at all (the graphics just stretch, and functions I'm using to move objects to the mouse position no longer work properly), since glViewport is called by default if I don't create a Reshape function.
The general way world coordinates get mapped to screen in OpenGL is:
world coordinates --> clip space coordinates --> device coordinates
The "world coordinates" are just whatever you feed to OpenGL as vertex data. They can be whatever you want, there are no rules.
The vertex shader (or matrix stack, if you are time traveling to the 1990s) is what transforms world coordinates to clip space coordinates.
The clip space coordinates go from –1…+1. So (–1,–1) is the lower-left corner of the window, (–1,+1) is the top left, (+1,+1) is the top right, etc. This is the same no matter what size your window is. So if your window gets larger, the picture will also get larger, unless you scale down the clip space coordinates at the same time.
So if you want to keep the same world coordinates and keep the same size in pixels, you have to change the way world coordinates are transformed to clip space. In general, this means that if your window gets twice as big, your clip space coordinates should get half as big, in order to keep everything the same size.
Typically, to achieve this, you'll end up multiplying in a matrix that looks something like this:
int windowWidth = ..., windowHeight = ...;
double matrix[2][2] = {
{ 1.0 / windowWidth, 0.0 },
{ 0.0, 1.0 / windowHeight },
};
That's if you're using a 2D matrix. Change this appropriately if you are using glOrtho or for your particular vertex shader. Or just read the manual for glOrtho.
By using:
gluOrtho2D(-1.0f, 1.0f, -1.0f, 1.0f);
Which would be the same as:
glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
Then I'm assuming your problem is that when you scale a scene like this, then it ends up looking like this:
As you say this can be fixed by taking the aspect ratio into account. Given the width and height of your screen. Then you can calculate the aspect ratio and set the proper orthographic projection:
const GLfloat aspectRatio = (GLfloat)width / (GLfloat)height;
gluOrtho2D(-aspectRatio, aspectRatio, -1.0f, 1.0f);
This now results in everything scaling in relation to the aspect ratio, and subsequently allowing you to see more.
Since the above is actually a sphere in 3D, setting the near and far values is also needed:
glOrtho(-aspectRatio, aspectRatio, -1.0f, 1.0f, 1.0f, 100.0f);

How to display shape and text on OpenGL screen simultaneously?

The below code works perfectly fine with no fatal error but, when i use arguments "w","h" in "gluortho2d" as gluortho2d(0,w,h,0) in reshape function I get text on screen whereas if I put these arguments "0,0" as gluortho2d(0,0,0,0) I get shape of box.
How can I get both of them(box and text) simultaneously on screen?
#include"glut.h"
void drawBitmapText(char *string, float x, float y, float z);
void reshape(int w, int h);
void display(void);
void drawBitmapText(char *string, float x, float y, float z)
{
char *c;
glRasterPos3f(x, y, z);//define position on the screen where to draw text.
for (c = string; *c != '\0'; c++)
{
glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, *c);
}
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void)
{
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("Usama OGL Window");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
By not following bad tutorials and placing calls to glViewport and projection matrix setup at the only place valid: The display function. Setting the viewport and projection matrix in the reshape handler is an anti-pattern. Don't do it.
Do this
void display(void)
{
int const w = glutGet(GLUT_WINDOW_WIDTH);
int const h = glutGet(GLUT_WINDOW_HEIGHT);
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(-1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBegin(GL_POLYGON);//1
glVertex2f(-0.2, 0.6 - 0.3);
glVertex2f(-0.1, 0.6 - 0.3);
glVertex2f(-0.1, 0.5 - 0.3);
glVertex2f(-0.2, 0.5 - 0.3);
glEnd();
/* viewport doesn't change in this
* application, but it's perfectly
* valid to set a different
* glViewport(...) here */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();//Resets to identity Matrix.
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(0, 1, 0);
drawBitmapText("Usama Ishfaq", 200, 400, 0);//drawBitmapText("Usama Ishfaq", x(how much right), y(how much down), z);
glutSwapBuffers();
}
Update (due to request in coments):
Why is it wrong to set the viewport and projection parameters in the reshape handler? Well, you just experienced the reason yourself: They are not "one size fits all" state and throughout rendering slightly more complex frames that go beyond just a mesh drawn, you're going to want to mix and match different viewports and projections throughout rendering. Here's a (incomplete) list of things that require to have different viewports and projections while rendering a single frame:
render-to-texture (FBO) – needs viewport withing the bounds of the texture, and usually also a different projection (important for shadow mapping, dynamic cubemaps and lots of other advanced, multipass rendering techniques)
minimaps / overview frames or similar in the corner (viewport covering just the corner)
text annotation overlays (different projection; usually a plain identity transform so to draw text rectangles directly in NDC space)
"magnifying glass" overlay
Since changing viewport and projection state happens multiple times in only slightly more complex OpenGL drawing, it makes
a) zero sense to set it in the reshape handler: whatever the handler sets will be set only at the beginning of the drawing of the first frame and thereafter the frame drawing code itself would have to reset to what the reshape handler sets. So why even bother doing it in the reshape handler at all?
b) placing viewport and projection setup code in the reshape handler a burden in the long run, because it might cause other parts of the program getting dependent on that. And if that happens, once you realize your mistake and try to move that viewport and projection setup code to where it belongs other parts of the program that relied on it being called from the reshape handler break and you have to fix those, too.
All in all, there are no reasons to place any drawing related calls (and glViewport and projection setup definitely are drawing related) in the reshape handler. Of course "one time" initialization is perfectly fine there, i.e. if you want to adjust the size of FBO render targets to match the window, or if you want to prepare an overlay image that later on gets applied repeatedly.
You can make this much simpler. For what you're doing, there's no need to bother with setting transformations at all.
It looks like, for the box, you're trying to use coordinates in the range [-1.0, 1.0] for both coordinate directions. This corresponds to the OpenGL NDC (Normalized Device Coordinates) coordinate system, which is the coordinate space vertices are in after both the modelview and projection transformations are applied. If you keep these at their default identity matrix, you can specify coordinates directly in NDC space. In other words, to use coordinates in the range [-1.0, 1.0], do... nothing at all, and just keep everything at its default.
The reason the box rendering works for you when you call:
gluOrtho2D(0.0, 0.0, 0.0, 0.0);
is that this call will result in an error, as documented on the man page:
GL_INVALID_VALUE is generated if left = right, or bottom = top, or near = far.
and will therefore keep the defaults untouched, which is exactly what you need.
Now, for the text, it looks like you want to specify the position in units of pixels. The problem you're having is that glRasterPos*() runs the specified coordinates through the transformation pipeline, meaning that, with the default identity modelview and projection transformations, it expects the input coordinates to be in the range [-1.0, 1.0] just like the coordinates you pass to glVertex2f().
Fortunately, there's a very easy way to avoid that. There's a very similar glWindowPos*() call, with the only difference that the coordinates passed to it are in window coordinates, which are in units of pixels.
So in summary:
Remove all glMatrixMode() calls.
Remove all glLoadIdentity() calls.
Remove all gluOrtho2D() calls.
In drawBitmapText(), replace the glRasterPos3f() call by:
glWindowPos2f(x, y);
The only thing to watch out for is that the origin of window coordinates is in the bottom left corner. So if your text position is given relative to the top left corner, you'll need something like:
glWindowPos2f(x, windowHeight - y);
To address some misleading information in another answer: It's perfectly fine to call glViewport() in the reshape() function, as long as you use the same viewport for all your rendering. In more complex applications, you will often need different viewports for different parts of the rendering (e.g. when you render to FBOs, or to only part of the window), so you will need to call glViewport() at the proper places during rendering. But for a simple example, where you do all your rendering to the entire window, there's nothing wrong with calling it in reshape().

opengl draw line height of window

I would like to know how to draw the length of a line with respect to the the dimensions of the enclosing window. Note that I am using the combination of GLUT and OpenGL.
For example, say I wanted to draw a line from the bottom center of the screen (I assume this would be at coordinate (WINDOW_LENGTH/2, 0) to the center of the window (WINDOW_LENGTH/2, WINDOW_HEIGHT/2)
How do I do this in OpenGL? Right now I have the following:
//Initializes 3D rendering
void initRendering() {
//Makes 3D drawing work when something is in front of something else
glEnable(GL_DEPTH_TEST);
}
//Called when the window is resized
void handleResize(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); //Switch to setting the camera perspective
//Set the camera perspective
glLoadIdentity(); //
gluPerspective(45.0, (double)w / (double)h, 1.0, 200.0);
}
//Draws the 3D scene
void drawScene() {
//Clear information from last draw
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
glLoadIdentity(); //Reset the drawing perspective
glTranslatef(0, 0, -1);
glBegin(GL_LINES);
//lines
glVertex2f(0, 0);
glVertex2f(0, .25);
glEnd();
glutSwapBuffers(); //Send the 3D scene to the screen
}
int main(int argc, char** argv) {
//Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400); //Set the window size
//Create the window
glutCreateWindow("Basic Shapes - videotutorialsrock.com");
initRendering(); //Initialize rendering
//Set handler functions for drawing, keypresses, and window resizes
glutDisplayFunc(drawScene);
//glutKeyboardFunc(handleKeypress);
glutReshapeFunc(handleResize);
cout << "GLUT_WINDOW_X: " << GLUT_WINDOW_X << endl;
cout << "GlUT_WINDOW_Y: " << GLUT_WINDOW_Y << endl;
glutMainLoop(); //Start the main loop. glutMainLoop doesn't return.
return 0; //This line is never reached
}
This gives me the following result:
What does not make sense to me is that my window has dimension 400 X 400 but the coordinates: glVertex2f(0, 0) and glVertex2f(0, .25). draw a line from about the center of the window to about 80% of the height of the window. I have a few speculations:
I know that my call to glTranslatef(0, 0, -1); sets the origin to the global coordinate (0, 0, -1) What is puzzling to me:
How does the -1 correspond to moving the image that far over?
Does the .25 in the second coordinate correspond to 25% of the height?
What would the code look like to draw a line from (WINDOW_LENGTH/2, 0) to (WINDOW_LENGTH/2, WINDOW_HEIGHT/2) That is the line from the bottom center of the window to the center of the window.
If you need more information let me know.
Let me try answer your questions:
You are working in a model-view (world to view) system. So you start modelling in world coordinates and transform it to the view coordinates. Therefore, glTranslatef is moving your world 1 coordinates points away from de camera.
What you do in openGL is weakly related to your windows coordinates. So, 0.25 really means 0.25 to openGL and nothing more. This means that you can stablish any semantics to points, like meters, kilometres, milimeters and so on. The correlation between openGL buffer and windows coordinates is stablished in the function gluPerspective, in which it says, basically, the region of your world that must be mapped to your windows coordinate system. The second function, glViewport only says how this map will be translated to you windows coordinates. In your case, you are telling to use all the windows.
As I said before, you need to manipulate your gluPerspective to control how much the openGL world will be mapped to your windows coordinates. To do that, you change the angle of the perspective. Greater angles, more openGL regions will be mapped, and you get an effect of zoom out. Lesser angles, less openGL regions will be mapped, and you get an effect of zoom in

OpenGL screen layout

I have some questions about the screen set up. Originally when I would draw a triangle the x vector 1 would be all the way to the right and -1 would be all the way to the left. Now I have adjusted it to account for the different aspect ratio of the window. My new question how do I make the numbers which are used to render a 2d tri go along with the pixel values. If my window is 480 pixels wide and 320 tall I want to have to enter this to span the screen with a tri
glBegin(GL_TRIANGLES);
glVertex2f(240, 320);
glVertex2f(480, 0);
glVertex2f(0, 0);
glEnd();
but instead it currently looks like this
glBegin(GL_TRIANGLES);
glVertex2f(0, 1);
glVertex2f(1, -1);
glVertex2f(-1, -1);
glEnd();
Any ideas?
You need to use functions glViewport and glOrtho with correct values. Basically glViewport sets the part of your window capable of rendering 3D-Graphics using OpenGL. glOrtho establishes coordinate system within that part of a window using OpenGL's coordinates.
So for your task you need to know exact width and height of your window. If you are saying they are 480 and 320 respectively then you need to call
glViewport(0, 0, 480, 320)
// or: glViewport ( 0,0,w,h)
somewhere, maybe in your SizeChanging-handler(if you are using WINAPI it is WM_SIZE message)
Next, when establishing OpenGL's scene you need to specify OpenGL's coordinates. For orthographic projection they will be the same as dimensions of a window so
glOrtho(-240, 240, -160, 160, -100, 100)
// or: glOrtho ( -w/2, w/2, -h/2, h/2, -100, 100 );
is siutable for your purppose. Not that here I'm using depth of 200 (z goes from -100 to 100).
Next on your rendering routine you may draw your triangle
Since the second piece of code is working for you, I assume your transformation matrices are all identity or you have a shader that bypasses them. Also your viewport is spanning the whole window.
In general if your viewport starts at (x0,y0) and has WxH size, the normalized coordinates (x,y) you feed to glVertex2f will be transformed to (vx,vy) as follows:
vx = x0 + (x * .5f + .5f) * W
vy = y0 + (y * .5f + .5f) * H
If you want to use pixel coordinates you can use the function
void vertex2(int x, int y)
{
float vx = (float(x) + .5f) / 480.f;
float vy = (float(y) + .5f) / 320.f;
glVertex3f(vx, vy, -1.f);
}
The -1 z value is the closest depth to the viewer. It's negative because the z is assumed to be reflected after the transformation (which is identity in your case).
The addition of .5f is because the rasterizer considers a pixel as a 1x1 quad and evaluates the coverage of your triangle in the middle of this quad.