2

I am trying to create an application that all it does is display an image full screen and then flash through a sequence of images quickly (144hz) repeatedly. I have just started looking at OpenGL, have done a few tutorials and cannot figure out what I'm doing wrong here. The part that I'm getting stuck on is actually rendering the image to to the display as it only shows up as a white square. I have gone through other stack overflow questions for this but none of the suggestions have worked for me.

I am doing this in Visual Studio 2015, using a win32 application and have installed the NupenGL package. For testing purposes, I am using a 256x256 bitmap image and am loading it through the SOIL library which I have built and statically linked.

I was originally thinking that I did not building/linking the SOIL library properly so something funky was going on trying to load the image. I created a custom BMP loader which didn't work and I also tried other peoples BMP loaders on stack overflow to no avail. I now believe that it is not the loading of the texture but that I am messing up something when actually trying to render it. Also in my code below I output if the texture is invalid but it always comes back good.

Output (FULLSCREEN): enter image description here

Output (WINDOWED): enter image description here

My Code:

#include <gl/freeglut.h>
#include <stdio.h>
#include <iostream>
#include "SOIL.h"

void init();
void display(void);
void keyPressed(unsigned char key, int x, int y);
void resize(int heightY, int widthX);


//  define the window position on screen
int window_x;
int window_y;

//  variables representing the window size
int window_width = 480;
int window_height = 480;

//  variable representing the window title
char *window_title = "Resolution Enhancement via Display Vibrations";

bool fullscreen = false;

//-------------------------------------------------------------------------
//  Program Main method.
//-------------------------------------------------------------------------
void main(int argc, char **argv)
{
    //  Connect to the windowing system + create a window
    //  with the specified dimensions and position
    //  + set the display mode + specify the window title.
    glutInit(&argc, argv);
    glutInitWindowSize(window_width, window_height);
    glutInitWindowPosition(window_x, window_y);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutCreateWindow(window_title);

    glutFullScreen();

    // Setup keyPressed
    glutKeyboardFunc(keyPressed);

    // Handler for when the screen resizes
    glutReshapeFunc(resize);

    //  Set OpenGL program initial state.
    init();

    // Set the callback functions
    glutDisplayFunc(display);

    //  Start GLUT event processing loop
    glutMainLoop();
}

//-------------------------------------------------------------------------
//  Set OpenGL program initial state.
//-------------------------------------------------------------------------
void init()
{
    //  Set the frame buffer clear color to black. 
    glClearColor(0.0, 0.0, 0.0, 0.0);
}

//-------------------------------------------------------------------------
//  This function is passed to glutDisplayFunc in order to display 
//  OpenGL contents on the window.
//-------------------------------------------------------------------------
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -5.0f);
    GLuint texture = SOIL_load_OGL_texture // load an image file directly as a new OpenGL texture
    (
        "C:/Users/joeja/Desktop/Grass.bmp",
        SOIL_LOAD_AUTO,
        SOIL_CREATE_NEW_ID,
        SOIL_FLAG_INVERT_Y | SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_COMPRESS_TO_DXT
    );

    if (texture == 0) {
        std::cout << "Texture not found!\n" << std::endl;
    }
    else
    {
        std::cout << "Texture is good\n" << std::endl;
    }

    glBindTexture(GL_TEXTURE_2D, texture);

    glBegin(GL_QUADS);  // front face
    glTexCoord2f(0.0f, 0.0f); glVertex3f(0.5f, -0.5f, 0.5f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.5f, 0.5f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.5f, 0.5f, 0.5f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, -0.5f, 0.5f);
    glEnd();

    glutSwapBuffers();
}

void resize(int heightY,int widthX) {
    const float ar = (float)widthX / (float)heightY;
    glViewport(0, 20, widthX, heightY);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void keyPressed(unsigned char key, int x, int y) {
    switch (key) {
    case 27:
    case 70:
    case 102: /* Fullscreen mode (Additional) : f/F */
        fullscreen = !fullscreen;
        if (fullscreen)
        {
            glutFullScreen();                /* Go to full screen */
        }
        else
        {
            glutReshapeWindow(800, 600);        /* Restore us */
            glutPositionWindow(0, 0);
        }
        break;
    }
}
Joe Jankowiak
  • 295
  • 3
  • 15
  • 1
    `-ar + 1, ar - 1` looks wrong to me. When widthX and heightY are equal, then ar == 1 and the two values are both 0. Shouldn't that just be `-ar, ar`? And why do you use 20 for the y-value of glViewport (which is in addition not respected in the aspect ratio? – BDL May 06 '16 at 20:56
  • 1
    Whoa! You load the image from file *every frame*. – doug65536 May 06 '16 at 21:54
  • Use `SOIL_FLAG_MIPMAPS` or set `GL_TEXTURE_MIN_FILTER` to a non-`MIPMAP` variant. – genpfault May 06 '16 at 23:37
  • @doug65536: You'd be surprised the kind of performance you can get doing that these days. I have a program that does deferred shading across two separate hosts and one of its unoptimized data paths involves dumping the G-Buffer to disk and fetching it as a network share. If that can sustain 60+ FPS at high resolutions, this is going to be an increasingly frequent mistake. This technically does not even stall the render pipeline, the old (duplicate) data is not interrupted so most drivers will make a separate copy on each frame and it's mostly down to disk throughput / possible image decode. – Andon M. Coleman May 08 '16 at 18:02
  • @AndonM.Coleman I was doing graphics programming when you wrote assembly to poke each pixel into memory, and you cherished every cycle. The horror of disk I/O every frame is a bit much for my eyes! – doug65536 May 08 '16 at 18:20

1 Answers1

1

Do not load the image from file every frame.

In your init you should:

  • load the image with SOIL like you already are, storing the ID as texture

In display you should,

  • glBindTexture(GL_TEXTURE_2D, texture);
  • glEnable(GL_TEXTURE_2D)
  • draw stuff
  • glDisable(GL_TEXTURE_2D);
  • glBindTexture(GL_TEXTURE_2D, 0);

You may notice that you could skip some enables/disables by just enabling texture 2D and leaving it on. I gave pseudocode that tries to always work, skipping redundant state changes is an optimization not relevant to the problem.

doug65536
  • 6,562
  • 3
  • 43
  • 53
  • `SOIL_load_OGL_texture` calls `glGenTextures` and `glTexImage2D` already. – BDL May 06 '16 at 22:11
  • @BDL Ok, but his code is backwards, it loads it then binds some other texture. And loading from file every `display` is utterly ridiculous. – doug65536 May 06 '16 at 22:12
  • 1
    @BDL ah I see your point now. SOIL uploads and all and returns the generated ID. Updating answer... – doug65536 May 06 '16 at 22:16