所以我已经遵循了Windows创建中用于OpenGL渲染上下文的所有基本指令
问题是当我尝试使用opengl创建核心配置文件上下文时,它会失败并且我得到"程序停止工作"来自Windows的消息当我运行a.exe文件时,没有迹象表明存在问题以及导致问题的原因,我甚至尝试运行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创建核心配置文件上下文时,程序失败< / p>
我用
编译gcc -Wall -Werror mainWin.c -lopengl32 -lglew32 -lgdi32
并且没有给出错误
答案 0 :(得分: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
指针并崩溃。
创建并使当前的传统OpewGL上下文不会神奇地初始化这些指针。您必须明确地调用wglewInit()
来查询这些函数指针 - 这是您需要tempContext
处于活动状态的唯一时间。
答案 1 :(得分:2)
//in order to use ARB context creation you must create a render context //must be made active and destroyed
这不是你create a temporary rendering context的原因。
在Win32中,您可以直接访问基本的WGL功能。但是WGL扩展函数要求您已经具有渲染上下文,因为该实现实际上是提供这些扩展的。
因此,您创建一个临时上下文,然后加载WGL扩展,然后销毁临时上下文。
你跳过了中间部分。
此外,您不能将Win32 HWND的像素格式设置为一次。由于您可能希望使用WGL扩展来选择像素格式,因此这是一个问题。因此,应为临时窗口创建临时渲染上下文,您可以在其中设置临时像素格式。