/* An example of the minimal Win32 & OpenGL program. It only works in 16 bit color modes or higher (since it doesn't create a palette). */ #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glew32.lib") #include /* must include this before GL/gl.h */ #include #include /* OpenGL header file */ #include /* OpenGL utilities header file */ #include #include #include #include using namespace std; HDC hDC; // Globals // Real programs don't use globals :-D // Data would normally be read from files GLfloat vertices[] = { -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f }; GLfloat colours[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; GLfloat vertices2[] = { 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f }; // two vertex array objects, one for each object drawn unsigned int vertexArrayObjID[2]; // three vertex buffer objects in this example unsigned int vertexBufferObjID[3]; void display() { // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindVertexArray(vertexArrayObjID[0]); // First VAO glDrawArrays(GL_TRIANGLES, 0, 3); // draw first object glBindVertexArray(vertexArrayObjID[1]); // select second VAO glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute glDrawArrays(GL_TRIANGLES, 0, 3); // draw second object glBindVertexArray(0); SwapBuffers(hDC); } LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static PAINTSTRUCT ps; switch (uMsg) { case WM_PAINT: display(); BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; case WM_SIZE: glViewport(0, 0, LOWORD(lParam), HIWORD(lParam)); PostMessage(hWnd, WM_PAINT, 0, 0); return 0; case WM_CHAR: switch (wParam) { case 27: /* ESC key */ PostQuitMessage(0); break; } return 0; case WM_CLOSE: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } char* loadFile(char *fname, GLint &fSize) { ifstream::pos_type size; char * memblock; string text; // file read based on example in cplusplus.com tutorial ifstream file(fname, ios::in | ios::binary | ios::ate); if (file.is_open()) { size = file.tellg(); fSize = (GLuint)size; memblock = new char[size]; file.seekg(0, ios::beg); file.read(memblock, size); file.close(); cout << "file " << fname << " loaded" << endl; text.assign(memblock); } else { cout << "Unable to open file " << fname << endl; exit(1); } return memblock; } HWND CreateOpenGLWindow(char* title, int x, int y, int width, int height, BYTE type, DWORD flags) { int pf; HWND hWnd; WNDCLASS wc; PIXELFORMATDESCRIPTOR pfd; static HINSTANCE hInstance = 0; /* only register the window class once - use hInstance as a flag. */ if (!hInstance) { hInstance = GetModuleHandle(NULL); wc.style = CS_OWNDC; wc.lpfnWndProc = (WNDPROC)WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = "OpenGL"; if (!RegisterClass(&wc)) { MessageBox(NULL, "RegisterClass() failed: " "Cannot register window class.", "Error", MB_OK); return NULL; } } hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, x, y, width, height, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { MessageBox(NULL, "CreateWindow() failed: Cannot create a window.", "Error", MB_OK); return NULL; } hDC = GetDC(hWnd); /* there is no guarantee that the contents of the stack that become the pfd are zeroed, therefore _make sure_ to clear these bits. */ memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | flags; pfd.iPixelType = type; pfd.cColorBits = 32; pf = ChoosePixelFormat(hDC, &pfd); if (pf == 0) { MessageBox(NULL, "ChoosePixelFormat() failed: " "Cannot find a suitable pixel format.", "Error", MB_OK); return 0; } if (SetPixelFormat(hDC, pf, &pfd) == FALSE) { MessageBox(NULL, "SetPixelFormat() failed: " "Cannot set format specified.", "Error", MB_OK); return 0; } DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd); ReleaseDC(hWnd, hDC); return hWnd; } int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow) { HDC hDC; /* device context */ HGLRC hRC; /* opengl context */ HWND hWnd; /* window */ MSG msg; /* message */ hWnd = CreateOpenGLWindow("minimal", 0, 0, 800, 600, PFD_TYPE_RGBA, 0); if (hWnd == NULL) exit(1); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); hDC = GetDC(hWnd); hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); ShowWindow(hWnd, nCmdShow); glewInit(); // Allocate Vertex Array Objects glGenVertexArrays(2, &vertexArrayObjID[0]); // Setup first Vertex Array Object glBindVertexArray(vertexArrayObjID[0]); glGenBuffers(2, vertexBufferObjID); // VBO for vertex data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); // VBO for colour data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), colours, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(1); // Setup second Vertex Array Object glBindVertexArray(vertexArrayObjID[1]); glGenBuffers(1, &vertexBufferObjID[2]); // VBO for vertex data glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[2]); glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), vertices2, GL_STATIC_DRAW); glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(0); glBindVertexArray(0); GLuint p, f, v; char *vs, *fs; v = glCreateShader(GL_VERTEX_SHADER); f = glCreateShader(GL_FRAGMENT_SHADER); // load shaders & get length of each GLint vlen; GLint flen; vs = loadFile("shaders/shader.vert", vlen); fs = loadFile("shaders/shader.frag", flen); const char * vv = vs; const char * ff = fs; glShaderSource(v, 1, &vv, &vlen); glShaderSource(f, 1, &ff, &flen); GLint compiled; glCompileShader(v); glGetShaderiv(v, GL_COMPILE_STATUS, &compiled); if (!compiled) { cout << "Vertex shader not compiled." << endl; } glCompileShader(f); glGetShaderiv(f, GL_COMPILE_STATUS, &compiled); if (!compiled) { cout << "Fragment shader not compiled." << endl; } p = glCreateProgram(); glBindAttribLocation(p, 0, "in_Position"); glBindAttribLocation(p, 1, "in_Color"); glAttachShader(p, v); glAttachShader(p, f); glLinkProgram(p); glUseProgram(p); delete[] vs; // dont forget to free allocated memory delete[] fs; // we allocated this in the loadFile function... while (GetMessage(&msg, hWnd, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } wglMakeCurrent(NULL, NULL); ReleaseDC(hWnd, hDC); wglDeleteContext(hRC); DestroyWindow(hWnd); return msg.wParam; }