0

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

4

2 回答 2

2

让我们在这里看看你的代码:

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

你的评论

为了使用 ARB 上下文创建,您必须创建一个渲染上下文,必须激活并销毁

尤其具有误导性。它不是为了自身的利益而创建和销毁一些遗留上下文。它是关于创建一个上下文来获取 WGL 扩展函数指针,而您根本不会这样做。

由于您使用的是 GLEW 的 wglew 功能,它将在 中声明所有必要的函数指针wglew.h,但这些函数指针都初始化为NULL,因此您的调用wglCreateContextAttribsARB只会取消引用NULL指针并崩溃。

创建和使 current 成为遗留 OpewGL 上下文不会神奇地初始化这些指针。您必须显式调用wglewInit()以查询这些函数指针 - 这是您唯一需要tempContext处于活动状态的时间。

于 2016-12-30T15:41:29.563 回答
2
 //in order to use ARB context creation you must create a render context
 //must be made active and destroyed 

这不是您创建临时渲染上下文的原因。

在 Win32 中,您可以直接访问基本的 WGL 功能。但是 WGL 扩展功能要求您已经有一个渲染上下文,因为该实现实际上提供了这些扩展。

因此,您创建一个临时上下文,然后加载 WGL 扩展,然后销毁临时上下文。

你跳过了中间部分。

此外,您不能多次设置 Win32 HWND 的像素格式。因为您可能想使用 WGL 扩展来选择像素格式,所以这是一个问题。因此,您的临时渲染上下文应该为临时窗口创建,您可以在其中设置临时像素格式。

于 2016-12-30T15:43:25.853 回答