3D C/C++ tutorials - OpenGL 1.5 - Cube rendering, rotating and lighting
3D C/C++ tutorials -> OpenGL 1.5 -> Cube rendering, rotating and lighting
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
To compile and run these tutorials some or all of these libraries are required: FreeImage 3.16.0, GLEW 1.11.0, GLUT 3.7.6 / GLUT for Dev-C++, GLM 0.9.5.4
win32_opengl_window.h
#include <windows.h>

#include "string.h"

#include <gl/glew.h> // http://glew.sourceforge.net/
#include <gl/wglew.h>

// ----------------------------------------------------------------------------------------------------------------------------

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")

// ----------------------------------------------------------------------------------------------------------------------------

extern CString ErrorLog;

// ----------------------------------------------------------------------------------------------------------------------------

class COpenGLRenderer
{
protected:
    int Width, Height;

public:
    COpenGLRenderer();
    ~COpenGLRenderer();

    bool Init();
    void Render(float FrameTime);
    void Resize(int Width, int Height);
    void Destroy();
};

// ----------------------------------------------------------------------------------------------------------------------------

class COpenGLView
{
protected:
    char *Title;
    int Width, Height;
    HWND hWnd;
    HGLRC hGLRC;

public:
    COpenGLView();
    ~COpenGLView();

    bool Init(HINSTANCE hInstance, char *Title, int Width, int Height);
    void Show(bool Maximized = false);
    void MessageLoop();
    void Destroy();

    void OnPaint();
    void OnSize(int Width, int Height);
};

// ----------------------------------------------------------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);

// ----------------------------------------------------------------------------------------------------------------------------

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR sCmdLine, int iShow);
win32_opengl_window.cpp
#include "win32_opengl_window.h"

// ----------------------------------------------------------------------------------------------------------------------------

COpenGLRenderer::COpenGLRenderer()
{
}

COpenGLRenderer::~COpenGLRenderer()
{
}

bool COpenGLRenderer::Init()
{
    GLfloat LightModelAmbient[] = {0.0f, 0.0f, 0.0f, 1.0f};
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightModelAmbient);

    GLfloat LightAmbient[] = {0.25f, 0.25f, 0.25f, 1.0f};
    glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);

    GLfloat LightDiffuse[] = {0.75f, 0.75f, 0.75f, 1.0f};
    glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);

    GLfloat MaterialAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialAmbient);

    GLfloat MaterialDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialDiffuse);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);

    return true;
}

void COpenGLRenderer::Render(float FrameTime)
{
    static float LightPosition[] = {0.0f, 0.0f, 2.5f, 1.0f}, a = 0.0f;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0.0f, 0.0f, 2.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

    glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);

    glRotatef(a, 0.0f, 1.0f, 0.0f);
    glRotatef(a, 1.0f, 0.0f, 0.0f);

    glColor3f(1.0f, 1.0f, 1.0f);

    glBegin(GL_QUADS);

    glNormal3f( 0.0f,  0.0f,  1.0f);
    glVertex3f(-0.5f, -0.5f,  0.5f);
    glVertex3f( 0.5f, -0.5f,  0.5f);
    glVertex3f( 0.5f,  0.5f,  0.5f);
    glVertex3f(-0.5f,  0.5f,  0.5f);

    glNormal3f( 0.0f,  0.0f, -1.0f);
    glVertex3f( 0.5f, -0.5f, -0.5f);
    glVertex3f(-0.5f, -0.5f, -0.5f);
    glVertex3f(-0.5f,  0.5f, -0.5f);
    glVertex3f( 0.5f,  0.5f, -0.5f);

    glNormal3f( 1.0f,  0.0f,  0.0f);
    glVertex3f( 0.5f, -0.5f,  0.5f);
    glVertex3f( 0.5f, -0.5f, -0.5f);
    glVertex3f( 0.5f,  0.5f, -0.5f);
    glVertex3f( 0.5f,  0.5f,  0.5f);

    glNormal3f(-1.0f,  0.0f,  0.0f);
    glVertex3f(-0.5f, -0.5f, -0.5f);
    glVertex3f(-0.5f, -0.5f,  0.5f);
    glVertex3f(-0.5f,  0.5f,  0.5f);
    glVertex3f(-0.5f,  0.5f, -0.5f);

    glNormal3f( 0.0f,  1.0f,  0.0f);
    glVertex3f(-0.5f,  0.5f,  0.5f);
    glVertex3f( 0.5f,  0.5f,  0.5f);
    glVertex3f( 0.5f,  0.5f, -0.5f);
    glVertex3f(-0.5f,  0.5f, -0.5f);

    glNormal3f( 0.0f, -1.0f,  0.0f);
    glVertex3f(-0.5f, -0.5f, -0.5f);
    glVertex3f( 0.5f, -0.5f, -0.5f);
    glVertex3f( 0.5f, -0.5f,  0.5f);
    glVertex3f(-0.5f, -0.5f,  0.5f);

    glEnd();

    a += 22.5f * FrameTime;
}

void COpenGLRenderer::Resize(int Width, int Height)
{
    this->Width = Width;
    this->Height = Height;

    glViewport(0, 0, Width, Height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, (float)Width / (Height > 0 ? (float)Height : 1.0f), 0.125f, 512.0f);
}

void COpenGLRenderer::Destroy()
{
}

// ----------------------------------------------------------------------------------------------------------------------------

COpenGLRenderer OpenGLRenderer;

// ----------------------------------------------------------------------------------------------------------------------------

CString ErrorLog;

// ----------------------------------------------------------------------------------------------------------------------------

COpenGLView::COpenGLView()
{
}

COpenGLView::~COpenGLView()
{
}

bool COpenGLView::Init(HINSTANCE hInstance, char *Title, int Width, int Height)
{
    this->Title = Title;
    this->Width = Width;
    this->Height = Height;

    WNDCLASSEX WndClassEx;

    memset(&WndClassEx, 0, sizeof(WNDCLASSEX));

    WndClassEx.cbSize = sizeof(WNDCLASSEX);
    WndClassEx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    WndClassEx.lpfnWndProc = WndProc;
    WndClassEx.hInstance = hInstance;
    WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClassEx.lpszClassName = "Win32OpenGLWindow";

    if(RegisterClassEx(&WndClassEx) == 0)
    {
        ErrorLog.Set("RegisterClassEx failed!");
        return false;
    }

    DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

    hWnd = CreateWindowEx(WS_EX_APPWINDOW, WndClassEx.lpszClassName, Title, Style, 0, 0, Width, Height, NULL, NULL, hInstance, NULL);

    if(hWnd == NULL)
    {
        ErrorLog.Set("CreateWindowEx failed!");
        return false;
    }

    HDC hDC = GetDC(hWnd);

    if(hDC == NULL)
    {
        ErrorLog.Set("GetDC failed!");
        return false;
    }

    PIXELFORMATDESCRIPTOR pfd;

    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int PixelFormat = ChoosePixelFormat(hDC, &pfd);

    if(PixelFormat == 0)
    {
        ErrorLog.Set("ChoosePixelFormat failed!");
        return false;
    }

    if(SetPixelFormat(hDC, PixelFormat, &pfd) == FALSE)
    {
        ErrorLog.Set("SetPixelFormat failed!");
        return false;
    }

    hGLRC = wglCreateContext(hDC);

    if(hGLRC == NULL)
    {
        ErrorLog.Set("wglCreateContext failed!");
        return false;
    }

    if(wglMakeCurrent(hDC, hGLRC) == FALSE)
    {
        ErrorLog.Set("wglMakeCurrent failed!");
        return false;
    }

    if(glewInit() != GLEW_OK)
    {
        ErrorLog.Set("glewInit failed!");
        return false;
    }

    if(WGLEW_EXT_swap_control)
    {
        wglSwapIntervalEXT(0);
    }

    return OpenGLRenderer.Init();
}

void COpenGLView::Show(bool Maximized)
{
    RECT dRect, wRect, cRect;

    GetWindowRect(GetDesktopWindow(), &dRect);
    GetWindowRect(hWnd, &wRect);
    GetClientRect(hWnd, &cRect);

    wRect.right += Width - cRect.right;
    wRect.bottom += Height - cRect.bottom;
    wRect.right -= wRect.left;
    wRect.bottom -= wRect.top;
    wRect.left = dRect.right / 2 - wRect.right / 2;
    wRect.top = dRect.bottom / 2 - wRect.bottom / 2;

    MoveWindow(hWnd, wRect.left, wRect.top, wRect.right, wRect.bottom, FALSE);

    ShowWindow(hWnd, Maximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
}

void COpenGLView::MessageLoop()
{
    MSG Msg;

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

void COpenGLView::Destroy()
{
    OpenGLRenderer.Destroy();
    wglDeleteContext(hGLRC);
    DestroyWindow(hWnd);
}

void COpenGLView::OnPaint()
{
    static DWORD LastFPSTime = GetTickCount(), LastFrameTime = LastFPSTime, FPS = 0;

    PAINTSTRUCT ps;

    HDC hDC = BeginPaint(hWnd, &ps);

    DWORD Time = GetTickCount();

    float FrameTime = (Time - LastFrameTime) * 0.001f;

    LastFrameTime = Time;

    if(Time - LastFPSTime > 1000)
    {
        CString Text = Title;

        Text.Append(" - %dx%d", Width, Height);
        Text.Append(", FPS: %d", FPS);
        Text.Append(" - %s", (char*)glGetString(GL_RENDERER));

        SetWindowText(hWnd, Text);

        LastFPSTime = Time;
        FPS = 0;
    }
    else
    {
        FPS++;
    }

    OpenGLRenderer.Render(FrameTime);

    SwapBuffers(hDC);

    EndPaint(hWnd, &ps);

    InvalidateRect(hWnd, NULL, FALSE);
}

void COpenGLView::OnSize(int Width, int Height)
{
    this->Width = Width;
    this->Height = Height;

    OpenGLRenderer.Resize(Width, Height);
}


// ----------------------------------------------------------------------------------------------------------------------------

COpenGLView OpenGLView;

// ----------------------------------------------------------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uiMsg)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        case WM_PAINT:
            OpenGLView.OnPaint();
            break;

        case WM_SIZE:
            OpenGLView.OnSize(LOWORD(lParam), HIWORD(lParam));
            break;

        default:
            return DefWindowProc(hWnd, uiMsg, wParam, lParam);
    }

    return 0;
}

// ----------------------------------------------------------------------------------------------------------------------------

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR sCmdLine, int iShow)
{
    char *AppName = "Cube rendering, rotating and lighting";

    if(OpenGLView.Init(hInstance, AppName, 800, 600))
    {
        OpenGLView.Show();
        OpenGLView.MessageLoop();
    }
    else
    {
        MessageBox(NULL, ErrorLog, AppName, MB_OK | MB_ICONERROR);
    }

    OpenGLView.Destroy();

    return 0;
}
Download
© 2010 - 2016 Bc. Michal Belanec, michalbelanec@centrum.sk
Last update June 25, 2016
OpenGL® is a registered trademark of Silicon Graphics Inc.