So i have followed all of the fundamental instructions in windows creation for OpenGL rendering context
the problem is to do when i try to create a core profile context with opengl , it fails and i get the "the program stopped working" message from windows when i run the a.exe file, there is no indication where the problem exists and what is causing the problem , i even tried to run gdb but it only refers to the function
wglCreateContextAttribsARB and no other information is given
here is my files which are currently included in the program
mainWin.c
#include "mainWin.h"
#include "glPart.c"
//main function, point of entry for windows application
//must be present in a windows application
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG Msg; //variable for storing messages retrieved from operating system by using GetMessage
HWND hWnd;
WNDCLASS WndCls;
// Create the window object
//sends a WM_CREATE message to windows which doesnt get processed until you retrieve messages and process them
//initialize window class must be initialized no default class
initWinClass(&WndCls, hInstance);
//Register the application must register application to make it available to other controls
RegisterClass(&WndCls);
hWnd = CreateWindow(ClsName,
WndName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
640,
640,
NULL,
NULL,
hInstance,
NULL);
//printf("at initialization %x\n",hWnd);
// Find out if the window was created
if( !hWnd ) // If the window was not created,
return 0; // stop the application
printf("Window was created....\n");
// Display the window to the user
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
initGL(hDC);
//GLint a, b;
while (Msg.message != WM_QUIT)
{
while (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE) > 0) //Or use an if statement
{
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
//Here is were all the "animation that isn't used when the user does something" code will go.
renderTri();
SwapBuffers(hDC);
}
return Msg.wParam;
}
winMain.h
#define true 1
#define false 0
#include <windows.h>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/wglew.h>
#include <GL/gl.h>
LPCTSTR ClsName = "OpenGL App";
LPCTSTR WndName = "My Game";
//global hdc
HDC hDC;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), //size of structure
1, //default version
PFD_DRAW_TO_WINDOW | //window drawing support
PFD_SUPPORT_OPENGL | //opengl support
PFD_DOUBLEBUFFER, //double buffering support
PFD_TYPE_RGBA, //RGBA color mode
32, //32 bit color mode
0, 0, 0, 0, 0, 0, //ignore color bits
0, //no alpha buffer
0, //ignore shift bit
0, //no accumulation buffer
0, 0, 0, 0, //ignore accumulation bits
24, //16 bit z-buffer size
8, //stencil buffer
0, //no aux buffer
PFD_MAIN_PLANE, //main drawing plane
0, //reserved
0, 0, 0 }; //layer masks ignored
//context attributes
int attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_FLAGS_ARB, 0,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void initWinClass(PWNDCLASS WndCls, HINSTANCE hInstance){
// Create the application window
//WndCls.cbSize = sizeof(WNDCLASSEX); wndclassex
WndCls->style = CS_HREDRAW | CS_VREDRAW |CS_OWNDC;
//the style member variable specifies the primary operations applied on the window class
//if user moves or changes its size, you would need the window redrawn to get its characteristics
//CS_HREDRAW CS_VREDRAW draw the window vertically and horizontally
WndCls->lpfnWndProc = WndProcedure;
WndCls->cbClsExtra = 0;
WndCls->cbWndExtra = 0;
WndCls->hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndCls->hCursor = LoadCursor(NULL, IDC_ARROW);
WndCls->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //cast to HBRUSH
WndCls->lpszMenuName = NULL;
WndCls->lpszClassName = ClsName;
WndCls->hInstance = hInstance;
//WndCls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); wndclassex
}
void setupPixelFormat(HDC hDC){
int nPixelFormat;
/* Choose best matching format*/
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
if (nPixelFormat == 0) printf("Error in choose pixel format\n");
/* Set the pixel format to the device context*/
BOOL bResult = SetPixelFormat(hDC, nPixelFormat, &pfd);
if (!bResult) printf("Error in set pixel format\n");
}
void setupPixelFormatARB(HDC hDC){
const int attribList[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0, //End
};
int pixelFormat;
UINT numFormats;
wglChoosePixelFormatARB(hDC, attribList, NULL, 1, &pixelFormat, &numFormats);
SetPixelFormat(hDC, pixelFormat, &pfd);
}
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
//printf("the message %d memory address is %x\n", Msg, hWnd);
static HGLRC hRC;
switch(Msg)
{
//this is the favourite message you can use to perform any early processing that you want to make
//sure happens before most things show up you can use this message to initialize anything in your application
//The window procedure of the new window receives this message after the window is created,
//but before the window becomes visible.
//will only run once on creation
case WM_CREATE:
hDC = GetDC(hWnd); //get the device context for window
setupPixelFormat(hDC); //call our pixel format setup function
//in order to use ARB context creation you must create a render context
//must be made active and destroyed
HGLRC tempContext = wglCreateContext(hDC);
wglMakeCurrent(hDC, tempContext);
hRC = wglCreateContextAttribsARB(hDC,0, attribs);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
wglMakeCurrent(hDC, hRC);
wglMakeCurrent(hDC,hRC); //make rendering context current old style
break;
//minimum application needs to deal with:
//wm_destroy message to close window and default case for non registered default messaging processing
//otherwise hanging or not reaching event queue
case WM_DESTROY: //Sent when a window is being destroyed.
//It is sent to the window procedure of the window being destroyed after the window is removed from the screen.
//you can use this message to deconstruct the window once the user requests to destroy the window
wglMakeCurrent(hDC,NULL); //deselect rendering context
wglDeleteContext(hRC); //delete rendering context
PostQuitMessage(0); //The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately
//send wm_quit message
//Indicates a request to terminate an application, and is generated when the application calls the PostQuitMessage function.
//This message causes the GetMessage function to return zero.
printf("Window destroyed goodbye...bye");
break;
//this must exist to process left over messages or the application will hang or will not go forward through the
//event queue and the while loop will
default:
// Process the left-over messages and messages that are not dealt with
return DefWindowProc(hWnd, Msg, wParam, lParam);
break;
}
// If something was not done, let it go
return 0;
}
and finally glPart.c
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/gl.h>
void initGL(HDC hDC){
//set experimental value to true so that all functions can be used
glewExperimental = GL_TRUE;
//initialize glew and get result , check result is not a failure
GLenum err = glewInit();
if(err!=GLEW_OK){
printf("glew failed!!!....");
}
//wglGetProcAddress("wglGetExtensionsStringARB")
printf("OpenGL version string is %s\n", glGetString(GL_VERSION));
GLint OpenGLVersion[3];
glGetIntegerv(GL_MAJOR_VERSION, &OpenGLVersion[0]);
glGetIntegerv(GL_MINOR_VERSION, &OpenGLVersion[1]);
printf("Glew version is %s\n", glewGetString(GLEW_VERSION));
printf("GL Major version %d\nGL Minor Version %d\n", OpenGLVersion[0], OpenGLVersion[1]);
printf("GLSL version is %s \nVendor of OpenGL is %s \nRenderer version is %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION),
glGetString(GL_VENDOR) ,glGetString(GL_RENDERER));
// Enable settings
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void renderTri(){
//finally some drawing OpenGL
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// An array of 3 vectors which represents 3 vertices
static const GLfloat verticies[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
// This will identify our vertex buffer
GLuint vbo;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vbo);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
glDisableVertexAttribArray(0);
}
now if i do this the old way without wglCreateContextAttribsARB it works fine and does what it is supposed to do even without the shaders , but when i try to do this by creating a core profile context with wgl is when the program fails
i compile with
gcc -Wall -Werror mainWin.c -lopengl32 -lglew32 -lgdi32
and no error are given
Let's have a look at your code here:
case WM_CREATE: hDC = GetDC(hWnd); //get the device context for window setupPixelFormat(hDC); //call our pixel format setup function //in order to use ARB context creation you must create a render context //must be made active and destroyed HGLRC tempContext = wglCreateContext(hDC); wglMakeCurrent(hDC, tempContext); hRC = wglCreateContextAttribsARB(hDC,0, attribs); wglMakeCurrent(NULL, NULL); wglDeleteContext(tempContext); wglMakeCurrent(hDC, hRC); wglMakeCurrent(hDC,hRC); //make rendering context current old style
Your comment
in order to use ARB context creation you must create a render context must be made active and destroyed
is especially misleading. It is not about creating and destroing some legacy context for its own sake. It is about creating a context to get the WGL extension function pointers, which you simply do not do.
Since you are using GLEW's wglew functionality, it will declare all the necessary function pointers in wglew.h
, but these function pointers are all initialized to NULL
, so your call of wglCreateContextAttribsARB
will just dereference the NULL
pointer and crash.
Creating and making current a legacy OpewGL context will not magically initialize these pointers. You have to explicitely call wglewInit()
to query these function pointers - and that is the only time you need tempContext
being active.