したがって、OpenGL レンダリング コンテキスト用のウィンドウ作成の基本的な手順をすべて実行しました。
問題は、opengl でコア プロファイル コンテキストを作成しようとすると失敗し、a.exe ファイルを実行すると Windows から「プログラムが動作を停止しました」というメッセージが表示されることです。問題が存在する場所は示されません。何が問題を引き起こしているのか、gdbを実行しようとしましたが、関数のみを参照しています
wglCreateContextAttribsARB であり、その他の情報は提供されません
これが現在プログラムに含まれている私のファイルです
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;
}
最後に 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);
}
wglCreateContextAttribsARB を使用せずにこれを古い方法で行うと、正常に動作し、シェーダーがなくても本来の動作を実行しますが、wgl でコア プロファイル コンテキストを作成してこれを実行しようとすると、プログラムが失敗します。
私はコンパイルします
gcc -Wall -Werror mainWin.c -lopengl32 -lglew32 -lgdi32
エラーは発生しません