I apologize if this isn't exact. I'm doing the best I can to copy code by hand from one computer to another, and the destination computer doesn't have a compiler (don't ask).
Header file
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <qopenglwidget.h>
class MyOpenGlWidget : public QOpenGLWidget
{
Q_OBJECT
public:
explicit MyOpenGlWidget(QWidget *parent = 0, Qt::WindowFlags f = Qt::WindowFlags());
virtual ~MyOpenGlWidget();
protected:
// these are supposed to be overridden, so use the "override" keyword to compiler check yourself
virtual void initializeGL() override;
virtual void resizeGL(int w, int h) override;
virtual void paintGL() override;
private:
QPixmap *_foregroundPixmap;
}
#endif
Source file
QOpenGLFunctions_2_1 *f = 0;
MyOpenGlWidget::MyOpenGlWidget(QWidget *parent, Qt::WindowFlags f) :
QOpenGLWidget(parent, f)
{
_foregroundPixmap = 0;
QPixmap *p = new QPixmap("beveled_texture.tiff");
if (!p->isNull())
{
_foregroundPixmap = p;
}
}
MyOpenGlWidget::~MyOpenGlWidget()
{
delete _foregroundPixmap;
}
void MyOpenGlWidget::initializeGL()
{
// getting a deprecated set of functions because such is my work environment
// Note: Also, QOpenGLWidget doesn't support these natively.
f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_1>();
f->glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clearing to green
f->glEnable(GL_DEPTH_TEST);
f->glEnable(GL_CULL_FACE); // implicitly culling front face
f->glEnable(GL_SCISSOR_TEST);
// it is either copy the matrix and viewport code from resizeGL or just call the method
this->resizeGL(this->width(), this->height());
}
void MyOpenGlWidget::resizeGL(int w, int h)
{
// make the viewport square
int sideLen = qMin(w, h);
int x = (w - side) / 2;
int y = (h - side) / 2;
// the widget is 400x400, so this random demonstration square will show up inside it
f->glViewport(50, 50, 100, 100);
f->glMatrixMode(GL_PROJECTION);
f->glLoadIdentity();
f->glOrtho(-2.0f, +2.0f, -2.0f, +2.0f, 1.0f, 15.0f); // magic numbers left over from a demo
f->glMatrixMode(GL_MODELVIEW);
// queue up a paint event
// Note: QGLWidget used updateGL(), but QOpenGLWidget uses update().
this->update();
}
void MyOpenGlWidget::paintGL()
{
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// I want to draw a texture with beveled edges the size of this widget, so I can't
// have the background clearing all the way to the edges
f->glScissor(50, 50, 200, 200); // more magic numbers just for demonstration
// clears to green in just scissored area (unless QPainter is created)
f->glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
// loading identity matrix, doing f->glTranslatef(...) and f->glRotatef(...)
// pixmap loaded earlier in another function
if (_foregroundPixmap != 0)
{
// QPixmap apparently draws such that culling the back face will cull the entire
// pixmap, so have to switch culling for duration of pixmap drawing
f->glCullFace(GL_FRONT);
QPainter(this);
painter.drawPixmap(0, 0, _foregroundPixmap->scaled(this->size()));
// done, so switch back to culling the front face
f->glCullFace(GL_BACK);
}
QOpenGLFunctions_2_1 *f = 0;
void MyOpenGlWidget::initializeGL()
{
// getting a deprecated set of functions because such is my work environment
// Note: Also, QOpenGLWidget doesn't support these natively.
f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_2_1>();
f->glClearColor(0.0f, 1.0f, 0.0f, 1.0f); // clearing to green
f->glEnable(GL_DEPTH_TEST);
f->glEnable(GL_CULL_FACE); // implicitly culling front face
f->glEnable(GL_SCISSOR_TEST);
// it is either copy the matrix and viewport code from resizeGL or just call it directly
this->resizeGL(this->width(), this->height());
}
void MyOpenGlWidget::resizeGL(int w, int h)
{
// make the viewport square
int sideLen = qMin(w, h);
int x = (w - side) / 2;
int y = (h - side) / 2;
// the widget is 400x400, so this random demonstration square will show up inside it
f->glViewport(50, 50, 100, 100);
f->glMatrixMode(GL_PROJECTION);
f->glLoadIdentity();
f->glOrtho(-2.0f, +2.0f, -2.0f, +2.0f, 1.0f, 15.0f); // magic numbers left over from a demo
f->glMatrixMode(GL_MODELVIEW);
// queue up a paint event
// Note: QGLWidget used updateGL(), but QOpenGLWidget uses update().
this->update();
}
void MyOpenGlWidget::paintGL()
{
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// I want to draw a texture with beveled edges the size of this widget, so I can't
// have the background clearing all the way to the edges
f->glScissor(50, 50, 200, 200); // more magic numbers just for demonstration
// clears to green in just scissored area (unless QPainter is created)
f->glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
// loading identity matrix, doing f->glTranslatef(...) and f->glRotatef(...), drawing triangles
// done drawing, so now draw the beveled foreground
if (_foregroundPixmap != 0)
{
// QPixmap apparently draws such that culling the back face will cull the entire
// pixmap, so have to switch culling for duration of pixmap drawing
f->glCullFace(GL_FRONT);
QPainter(this);
painter.drawPixmap(0, 0, _foregroundPixmap->scaled(this->size()));
// done, so switch back to culling the front face
f->glCullFace(GL_BACK);
}
}
The problem is this code from paintGL():
QPainter(this);
As soon as a QPainter object is created, the glScissor(...) call that I made earlier in the function is overrun and some kind of glClearColor(...) call is made (possibly from QPainter's constructor) that clears the entire viewport to the background color that I set just after glScissor(...). Then the pixmap draws my beveled texture just fine.
I don't want QPainter to overrun my scissoring.
The closest I got to an explanation was two QPainter methods, beginNativePainting() and endNativePainting(). According to the documentation, scissor testing is disabled between these two, but in their example they re-enable it. I tried using this "native painting" code, but I couldn't stop QPainter's mere existence from ignoring GL's scissoring and clearing my entire viewport.
Why is this happening and how do I stop this?
Note: This work computer has network policies to prevent me from going to entertainment sites like imgur to upload "what I want" and "what I get" pictures, so I have to make due with text.
Why is this happening
The OpenGL context is a shared resource and you have to share it with other players.
and how do I stop this?
You can't. Just do the proper thing and set viewport, scissor rectangle and all the other drawing related state at the right moment: Right before you are going to draw something that relies on these settings. Don't set them aeons (in computer terms) before, somewhere in some "initialization" or a reshape handler. And be expected that in drawing code any function you call that makes use of OpenGL will leave some garbage behind.
Related
I'm using qWidget which inherits QGLWidget and below the widget I have 2 buttons.
button1: +
button2: -
this is my code:
void GLWidget::paintGL() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(_camera_pos_x,0,_w,_h);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
update();
}
I want each time I'm pressing the + button, the screen will move 10 pixels to the right which means the line should move to the left by 10 pixels.
This is the code when im pressing the button:
void right() {_camera_pos_x += 10;}
_camera_pos_X is just a member int which is initialized to 0.
When I'm pressing the button another line is rendered 10 pixels to the right and I see 2 lines
What's wrong with my code?
By the way, I think im using old code of OpenGL, is there a better way to render a line?
First of all note, that drawing with glBegin/glEnd sequences is deprecated since more than 10 years.
Read about Fixed Function Pipeline and see Vertex Specification for a state of the art way of rendering.
glViewport specifies the transformation from normalized device coordinates to window coordinates. If you want to change the position of the line, then you have to draw the line at a different position, but that doesn't change the size of the viewport. Keep your viewport as large as the window:
glViewport(0, 0, _w, _h);
The default frame buffer is never cleared, so the rendering is always drawn on the rendering of the previous frames. Because of that, you can "see 2 lines". Use glClear to clear the framebuffer at the begine of the rendering:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Change the model view matrix to set the positon of the line:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,_w,0,_h,-1,1);
glViewport(0, 0, _w, _h);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(_camera_pos_x, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2i(50,50);
glVertex2i(200,200);
glEnd();
You must clear the old contents of the framebuffer, before drawing the new image. Put a glClear(GL_COLOR_BUFFER_BIT) at the beginning of paintGL().
I have some issues with my QOpenGLWidget resizing functionality. Obviously, I am aiming for a new viewport with the correct amount of pixels and a scene centered in the actual center of my window. But these two things are off somehow.
Here are some images:
Initial one:
Scaled in Y:
Scaled in X:
The result is pixelated and translated. For me it looks like the GL viewport has the correct amount of pixels, but is scaled to the top and to the right (if the (0,0) is defined as the bottom left corner).
Here is my code:
void GLWidget::initializeGL() {
QOpenGLFunctions::initializeOpenGLFunctions();
glClearColor(0.7f, 0.75f, 0.8f, 1.0f);
glEnable(GL_MULTISAMPLE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void GLWidget::resizeGL(int w, int h) {
qreal aspect = qreal(w) / qreal(h ? h : 1);
const qreal zNear = 3, zFar = 7, fov = 3.14/6;
//I will leave this at it is. This cannot cause the viewport translation
mGraphics->setProjectionPers(fov, aspect, zNear, zFar);
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
//actual Drawing
//...
}
The resizeGL is called with the correct values. What am I doing wrong for having a pixelated and translated image when I run this piece of code?
For whatever reason this was in the header file of my QOpenGLWidget decendant:
void resizeEvent(QResizeEvent* ev) {
resizeGL(width(), height());
}
This pretty much skips all the resize logic of the QOpenGLWidget class.
I have some code to move a toy car from left to right.
I want to transform the code to stop its movement by the pressing of any key for example 's'....could someone help me do that...here is my code so far.
#include <GL/glut.h> // Header File For The GLUT Library
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
//#include <unistd.h> // Header File For sleeping.
/* ASCII code for the escape key. */
#define ESCAPE 27
/* The number of our GLUT window */
int window;
/* rotation angle for the triangle. */
float rtri = 0.0f;
/* rotation angle for the quadrilateral. */
float rquad = 0.0f;
/* A general OpenGL initialization function. Sets all of the initial parameters. */
// We call this right after our OpenGL window is created.
void InitGL(int Width, int Height)
{
// This Will Clear The Background Color To Black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height==0) // Prevent A Divide By Zero If The Window Is Too Small
Height=1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
float ballX = -0.5f;
float ballY = 0.0f;
float ballZ = 0.0f;
void drawBall(void) {
glColor3f(0.0, 1.0, 0.0); //set ball colour
glTranslatef(ballX,ballY,ballZ); //moving it toward the screen a bit on creation
//glRotatef(ballX,ballX,ballY,ballZ);
glutSolidSphere (0.3, 20, 20); //create ball.
glTranslatef(ballX+1.5,ballY,ballZ); //moving it toward the screen a bit on creation
glutSolidSphere (0.3, 20, 20); //
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(rtri,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
//glRotatef(rtri,1.0f,0.0f,0.0f); // Rotate The Triangle On The Y axis
// draw a triangle (in smooth coloring mode)
glBegin(GL_POLYGON); // start drawing a polygon
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f(-1.0f, 1.0f, 0.0f); // Top left
glVertex3f(0.4f, 1.0f, 0.0f);
glVertex3f(1.0f, 0.4f, 0.0f);
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f( 1.0f,0.0f, 0.0f); // Bottom Right
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(-1.0f,0.0f, 0.0f);// Bottom Left
//glVertex3f();
glEnd(); // we're done with the polygon (smooth color interpolation)
drawBall();
rtri+=0.005f; // Increase The Rotation Variable For The Triangle
if(rtri>2)
rtri=-2.0f;
rquad-=15.0f; // Decrease The Rotation Variable For The Quad
// swap the buffers to display, since double buffering is used.
glutSwapBuffers();
}
/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y)
{
/* sleep to avoid thrashing this procedure */
// usleep(100);
/* If escape is pressed, kill everything. */
if (key == ESCAPE)
{
/* shut down our window */
glutDestroyWindow(window);
/* exit the program...normal termination. */
exit(0);
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
/* get a 640 x 480 window */
glutInitWindowSize(640, 480);
/* the window starts at the upper left corner of the screen */
glutInitWindowPosition(0, 0);
/* Open a window */
window = glutCreateWindow("Moving Car");
/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(&DrawGLScene);
/* Go fullscreen. This is as soon as possible. */
//glutFullScreen();
/* Even if there are no events, redraw our gl scene. */
glutIdleFunc(&DrawGLScene);
/* Register the function called when our window is resized. */
glutReshapeFunc(&ReSizeGLScene);
/* Register the function called when the keyboard is pressed. */
glutKeyboardFunc(&keyPressed);
/* Initialize our window. */
InitGL(640, 480);
/* Start Event Processing Engine */
glutMainLoop();
return 1;
}
conditionally disable the following bit of code:
rtri+=0.005f; // Increase The Rotation Variable For The Triangle
if(rtri>2)
rtri=-2.0f;
rquad-=15.0f; // Decrease The Rotation Variable For The Quad
this can be done by adding the following to the keyPressed function
if (key == S)
{
updateGeom = false;//stop updating
}
if (key == D)
{
updateGeom = true;//start updating
}
and changing the above mentioned code as
if(updageGeom){
rtri+=0.005f; // Increase The Rotation Variable For The Triangle
if(rtri>2)
rtri=-2.0f;
rquad-=15.0f; // Decrease The Rotation Variable For The Quad
}
you need to add a global boolean updateGeom as well
I would like to draw some overlay on my image viewer : a dashed rectangle around the image, indicating the bounding box.
Here 's what I do in the paintEvent function:
void ViewerGL::paintEvent(QPaintEvent* event){
makeCurrent();
QPainter p(this);
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT); // << If I don't do this it clears out my viewer white
// and I want it black
p.setBackgroundMode(Qt::TransparentMode); // < was a test, doesn't seem to do anything
p.setBackground(QColor(0,0,0,0));
//loading the appropriate shader before texture mapping
if(rgbMode() && _shaderLoaded){
shaderRGB->bind();
}else if(!rgbMode() && _shaderLoaded){
shaderLC->bind();
}
paintGL(); // render function (texture mapping)
//drawing a rect around the texture on the viewer
QPen pen(Qt::DashLine);
pen.setColor(QColor(233,233,233));
p.setPen(pen);
QPoint btmRight=mousePosFromOpenGL(dataWindow().w(),dataWindow().h() +transY*2 + ( zoomY-dataWindow().h()/2)*2);
QPoint btmLeft=mousePosFromOpenGL(0,dataWindow().h() +transY*2 + ( zoomY-dataWindow().h()/2)*2);
QPoint topLeft=mousePosFromOpenGL(0,0 +transY*2 + ( zoomY-dataWindow().h()/2)*2);
QPoint topRight=mousePosFromOpenGL(dataWindow().w(), 0+ +transY*2 + ( zoomY-dataWindow().h()/2)*2);
p.drawLine(topLeft,topRight);
p.drawLine(topRight,btmRight);
p.drawLine(btmRight,btmLeft);
p.drawLine(btmLeft,topLeft);
QPoint pos = mousePosFromOpenGL( (dataWindow().w()) + 10 ,
(dataWindow().h()) +transY*2 + ( zoomY-dataWindow().h()/2)*2 +10); // bottom right of the texture +10
p.drawText(pos, _resolutionOverlay);
p.end();
}
And here is what I do in the paintGL function:
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
... my drawing code
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
And the initializeGL function :
initAndCheckGlExtensions();
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glGenTextures (1, texId);
glGenTextures (1, texBlack);
glGenBuffersARB(1, &texBuffer);
shaderBlack=new QGLShaderProgram(context());
shaderBlack=new QGLShaderProgram(context());
if(!shaderBlack->addShaderFromSourceCode(QGLShader::Vertex,vertRGB))
cout << shaderBlack->log().toStdString().c_str() << endl;
if(!shaderBlack->addShaderFromSourceCode(QGLShader::Fragment,blackFrag))
cout << shaderBlack->log().toStdString().c_str() << endl;
if(!shaderBlack->link()){
cout << shaderBlack->log().toStdString().c_str() << endl;
}
So far it works, I have what I want, but my program is flooding stderr on exit with :
'QGLContext::makeCurrent: Cannot make invalid context current'.
I know this is coming from the QPainter and not from something else in my program.
I tried to move the code in the paintGL function to another function that is not virtual but that did not change anything.
You should first perform OpenGL calls, clear your OpenGL state, then wrap ALL QPainter draw calls between QPainter::begin(QGLWidget *) and QPainter::end(QGLWidget *).
Your program is most likely causing a problem because you interleave QPainter and OpenGL drawing calls. When you instantiate the QPainter object with QPainter(QPaintDevice *) you tell the QPainter to use the native drawing facilities of the QGLWidget to perform QPainter operations. So... QPainter uses OpenGL fixed-function calls to perform 2D drawing and it may interfere with your OpenGL rendering calls when your state has not been cleared.
I suggest following this guide:
https://doc.qt.io/archives/qt-4.8/qt-opengl-overpainting-example.html
I have a wxWigets application, using the wxGLCanvas widget from the contrib package. Every time the widget is refreshed, I recreate the projection matrix and the viewport before rendering the scene. The problem is, after the frame is resized, whether by dragging or maximizing or w/e, the widget is correctly resized, but the viewport or projection (can't really discern which) is not resized, so the scene ends up being cropped.
Now for some code.
The constructor of my wxGLCanvas widget looks like this:
int attrib_list[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER };
RenderCanvas::RenderCanvas(wxFrame* parent) : wxGLCanvas(parent, idRender, wxPoint(200, -1), wxSize(800, 600), wxFULL_REPAINT_ON_RESIZE, wxT("GLCanvas"), attrib_list)
{
Connect(idRender, wxEVT_PAINT, wxPaintEventHandler(RenderCanvas::PaintIt));
Connect(idRender, wxEVT_SIZE, wxSizeEventHandler(RenderCanvas::Resize));
Connect(idRender, wxEVT_LEFT_DOWN, wxMouseEventHandler(RenderCanvas::OnMouseLeftDown));
Connect(idRender, wxEVT_LEFT_UP, wxMouseEventHandler(RenderCanvas::OnMouseLeftUp));
Connect(idRender, wxEVT_MOTION, wxMouseEventHandler(RenderCanvas::OnMouseMotion));
}
I overriode the PaintIt method like so:
void RenderCanvas::PaintIt(wxPaintEvent& event)
{
SetCurrent();
wxPaintDC(this);
Render();
Refresh(false);
}
and the resize method:
void RenderCanvas::Resize(wxSizeEvent& event)
{
Refresh();
}
The Render method used above looks like this:
void RenderCanvas::Render()
{
Prepare2DViewport(0,GetClientSize().y,GetClientSize().x, 0);
glClear(GL_COLOR_BUFFER_BIT);
//Renders stuff...
glFlush();
SwapBuffers();
}
And lastly, the Prepare2DViewport, where the glViewport and glOrtho functions are being called is:
void RenderCanvas::Prepare2DViewport(int x, int h, int w, int y)
{
glClearColor(0.7f, 0.7f, 0.7f, 1.0f); // Grey Background
glEnable(GL_TEXTURE_2D); // textures
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glViewport(x, y, w, -h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(x, (float)w, y, (float)h, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
It should also be noted that I have tried using GetSize() instead of GetClientSize() but the effects are the same. Also, I am on Ubuntu 12.04 and wxWidgets is using GTK
UPDATE:
It should also be noted that I have click/drag functionality implemented as well (not shown), and every time the mouse is clicked or dragged, the widget is refreshed. With that said, I tried disconnecting the wxEVT_SIZE event, but after resizing and then clicking and dragging, the same effect persists.
From a quick glance at your code, I notice that your resize event handler is not doing anything more than asking for another refresh. This does not seem correct to me. A resize handler would normally do some calculation, call resize handlers of one or more child windows and so on before asking for a refresh. So, I think that your problem is that the canvas has not been resized BEFORE being repainted. This would explain why your scene is clipped. Not sure what the fix would be - hopefully this will be enough of a hint so you can look in the right direction.
Okay, so it turned out to be a very, very stupid mistake on my part.
in this line
glViewport(x, y, w, -h);
I accidentally set the height to a negative value. removing the negative sign fixed the issue. I am not sure why it was causing a crop. I would think having the height negative would prevent me from seeing anything, but it works, so I can't complain I guess. Thanks again all for the help!