Tell me more ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

An answer to this question can be found here: stackoverflow.com

I'm trying to learn how to do some basic work in OpenGL 2.0 and I'm having difficulties getting any vertex data to show up on the screen. Right now I'm at a loss for where my problem is. I've gone through a number of examples and nothing obvious stands out for me as wrong in my code, but I'm sure I'm missing something simple. I'll try to be short with my code.

Thank you.

bool GameCore::Start(int iCmdShow)
{
    const LPCWSTR appname = TEXT("Maze Game");
    // Create the Window and kill the program if this fails.
    if(!wm->Create(appname))
    {
        return FALSE;
    }

    // Initialize OpenGL
    wm->InitGraphics();
    cam = wm->cam;

    Vector3 *v = new Vector3(0.0f,0.0f,0.0f);
    wm->testSprite = new Sprite(v);

    // Start the update loop.
    _beginthread(&GameCore::Execute, 0, this);

    // Blocking function to run the application.
    wm->RunWindow(iCmdShow);
    return true;
}

// Initialize OpenGL graphics
void OpenGLWM::InitGraphics()
{
    hDC = GetDC(hWnd);

    SetupPixelFormat();

    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

    glClearColor(1, 0, 0, 0);
    glClearDepth(1.0);
    glEnable(GL_DEPTH_TEST);

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        // Add error handling.
    }

    cam = new Camera(0, 0, -10);
    program = new ShaderProgram();
    program->Initialize();
}

// Set up pixel format for graphics initialization
void OpenGLWM::SetupPixelFormat()
{
    PIXELFORMATDESCRIPTOR pfd, *ppfd;
    int pixelformat;

    ppfd = &pfd;

    ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
    ppfd->nVersion = 1;
    ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    ppfd->dwLayerMask = PFD_MAIN_PLANE;
    ppfd->iPixelType = PFD_TYPE_COLORINDEX;
    ppfd->cColorBits = 16;
    ppfd->cDepthBits = 16;
    ppfd->cAccumBits = 0;
    ppfd->cStencilBits = 0;

    pixelformat = ChoosePixelFormat(hDC, ppfd);
    SetPixelFormat(hDC, pixelformat, ppfd);
}

// Camera Constructor
Camera::Camera(double dX, double dY, double dZ)
{
    Vector3 V(dX, dY, dZ);
    Vector3 R(0,0,0);
    Initialization(V, R);
}

bool ShaderProgram::Initialize()
{
    GLint giLinked;
    GLbyte vShaderStr[] =
    "#version 110               \n"
    "attribute vec3 in_Position;\n"
    "void main()\n"
    "{\n"
        "gl_Position = vec4(in_Position, 1.0);\n"
    "}\n";

    GLbyte pShaderStr[] =
    "#version 110               \n"
    "precision mediump float;\n"
    "void main()\n"
    "{\n"
        "gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
    "}\n";

    // Load the shaders
    vertexShader.LoadShader((const char *)&vShaderStr, GL_VERTEX_SHADER);
    pixelShader.LoadShader((const char *)&pShaderStr, GL_FRAGMENT_SHADER);

    guiProgram = glCreateProgram();

    if(guiProgram == 0)
    {
        return false;
    }
    // Add the shaders to the program
    glAttachShader(guiProgram, vertexShader.guiShader);
    glAttachShader(guiProgram, pixelShader.guiShader);

    // Bind the position coordinates
    glBindAttribLocation(guiProgram, 0, "in_Position");

    // Link the program
    glLinkProgram(guiProgram);
    int iError = glGetError();
    // Get the link status
    glGetProgramiv(guiProgram, GL_LINK_STATUS, &giLinked);

    if(giLinked == 0)
    {
        // Add error handling.
        return false;
    }
    return true;
}

GLuint BaseShader::LoadShader(const char *cShaderSrc, GLenum type)
{
    GLint guiCompiled;
    // Creates an empty shader object.
    guiShader = glCreateShader(type);

    if(guiShader == 0)
    {
        return 0;
    }
    // Load the shader.
    glShaderSource(guiShader, 1, &cShaderSrc, NULL);

    // Compile the shader
    glCompileShader(guiShader);

    // Check the compile status
    glGetShaderiv(guiShader, GL_COMPILE_STATUS, &guiCompiled);

    if(guiCompiled == 0)
    {
        // TODO: ADD ERROR LOGGING
        GLint infoLen = 0;
        glGetShaderiv(guiShader, GL_INFO_LOG_LENGTH, &infoLen);
        if(infoLen > 1)
        {
            char* infoLog = (char *)malloc(sizeof(char) * infoLen);
            glGetShaderInfoLog(guiShader, infoLen, NULL, infoLog);
            free(infoLog);
        }
        return 0;
    }
    return guiShader;
}

// Sprite inherits from Render Object
Sprite::Sprite(Vector3 *_vPosition)
{
    // Initialize the position.
    vPosition = _vPosition;
    // Create verticies
    vertexStruct * v = new vertexStruct[4];
    v[0].SetPosition(-2, 2, -40);
    v[0].SetColor(128, 128, 128, 255);
    v[1].SetPosition(2, 2, -40);
    v[1].SetColor(128, 128, 128, 255);
    v[2].SetPosition(2, -2, -40);
    v[2].SetColor(128, 128, 128, 255);
    v[3].SetPosition(-2, -2, -40);
    v[3].SetColor(128, 128, 128, 255);

    // Create the indicies.
    GLubyte * i = new GLubyte[6];
    i[0] = 0;
    i[1] = 1;
    i[2] = 2;
    i[3] = 0;
    i[4] = 2;
    i[5] = 3;

    Initialize(v, 4, i, 6);
}

void RenderObject::Initialize(vertexStruct *_vertices, unsigned int _uiNumVertices, GLubyte *_indices, unsigned int _uiNumIndicies)
{
    vertices = _vertices;
    indices = _indices;
    uiNumVertices = _uiNumVertices;
    uiNumIndices = _uiNumIndicies;
    CreateBufferObjects();
}

void RenderObject::CreateBufferObjects()
{
    // Get an id for the Vector3 buffer.
    glGenBuffers((GLsizei)1, &uiVertexBuffer);
    // Bind the buffer so we can "upload" the data.
    glBindBuffer(GL_ARRAY_BUFFER, uiVertexBuffer);
    // Upload the data to OpenGL.
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexStruct) * uiNumVertices, vertices, GL_STATIC_DRAW);

    // Get an id for the indice buffer.
    glGenBuffers(1, &uiIndiceBuffer);
    // Bind the indice buffer so we can "upload" the data.
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, uiIndiceBuffer);
    // Upload the data to OpenGL.
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte) * uiNumIndices, indices, GL_STATIC_DRAW);
}

bool WindowManager::RunWindow(int iCmdShow)
{
    // Display the window
    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    // Event loop
    while (1)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
        {
            if (!GetMessage(&msg, NULL, 0, 0))
            {
                return TRUE;
            }

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        // It would be better if this was its own thread.
        if(!DoWork())
        {
            return false;
        }
    }
return true;
}

// "Draw" function.
bool OpenGLWM::DoWork()
{
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(program->guiProgram);

    testSprite->Draw();
    // Show the new scene
    SwapBuffers(hDC);
    return true;
}

void RenderObject::Draw()
{
    // Bind the vertex buffer.
    glBindBuffer(GL_ARRAY_BUFFER, uiVertexBuffer);
    // Set where the vertex data is.
    glVertexAttribPointer(VertexEnum::Data, 3, GL_FLOAT, GL_FALSE, sizeof(vertexStruct), 0);
    glEnableVertexAttribArray(0);//VertexEnum::Data);

    // Load the colors.
    glVertexAttribPointer(VertexEnum::Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, 12, (void*)offsetof(vertexStruct, color));

    glEnableVertexAttribArray(1);//VertexEnum::Color);
    // Bind the indice buffer.
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, uiIndiceBuffer);
    glDrawElements(GL_TRIANGLE_STRIP, uiNumIndices, GL_UNSIGNED_BYTE, 0);
}

Update:

Here is the glViewPort code:

void OpenGLWM::ResizeGraphics()
{
    // Get new window size
    RECT rect;
    int width;
    int height;
    GLfloat aspect;

    GetClientRect(hWnd, &rect);
    width = rect.right;
    height = rect.bottom;
    aspect = (GLfloat)width / height;

    // Adjust graphics to window size
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, aspect, 1.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
    // Call the base function
    WindowManager::ResizeGraphics();
}
share|improve this question
Why the cross-posting? – Laurent Couvidou Jan 23 at 11:31
THIS is supposed to be the short code? – Bartek Banachewicz Jan 23 at 13:35

closed as too localized by Trevor Powell, Josh Petrie, Laurent Couvidou, Tetrad Jan 23 at 17:08

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, see the FAQ.

1 Answer

Well the most glaring issue i can see right now is the lack of glViewport. I don't see you setting up a window procedure anywhere either, you should start there.

Also this looks weird, i don't know what you're going for here, but trying to run multiple threads when you're just trying to display a triangle on the screen is odd.

// Start the update loop.
_beginthread(&GameCore::Execute, 0, this);

If you're not sure what you're doing, then maybe try using a library like GLEW to set up a window and see if that works for you, then jump into using WinAPI.

Beside that, you're using WinAPI and trying to work with OpenGL ES, i don't think that's going to work, OpenGL ES is for mobile devices, are you doing this on a desktop? It's just a detail, your code works like OpenGL 2.1 anyways, so that's not the problem, but there are some differences between the two.

share|improve this answer
Hi Dreta. Thanks for the information. I thought ES was for the custom shader version of OpenGL instead of the fixed pipeline. I'll change the title and post to note that. I'll look into my work to see if that changed anything. – Alikar Jan 15 at 5:25
The glViewPort is called in another function that was not included. I'll include it for you. Also the multiple threads are for some input code that I had to test some fixed pipeline vertex code I used to have. I'm also purposely avoiding GLEW as I wanted to write the code that talks with Windows, but yes I should probably test with GLEW to see if my windows code is the issue. – Alikar Jan 15 at 5:31
@Alikar Try setting glClearColor to something other than black inside of DoWork, it's the easiest way to tell if the window was set up properly. If that works, then you should check your shader and program compilation logs, if you aren't already. – dreta Jan 15 at 5:40
Ahh good to know. I've done as you suggested and glClearColor(1, 0, 0, 1); does make the screen red. – Alikar Jan 15 at 5:42
@Alikar on the note of OpenGL ES versus regular OpenGL, the desktop version GLSL doesn't have "precision mediump float;", so best if you remove it, technically the precision qualifier shouldn't cause problems, but what's in the spec, is not always in the real world. – dreta Jan 15 at 6:01
show 4 more comments

Not the answer you're looking for? Browse other questions tagged or ask your own question.