导致问题:
通过制作我自己设计的(可能很简单)基于图块的游戏来学习使用 C 的 OpenGL。最初我只绘制了大约 10 个左右的三角形进行测试,我设置了缓冲区数据和索引,如下所示:
const float vertexPositions[] = {
-1.0f, -0.8f, //0
-1.0f, -1.0f, //1
-0.8f, -0.8f, //2
-0.8f, -1.0f, //3
-0.8f, -0.8f, //2
-0.8f, -1.0f, //3
-0.6f, -0.8f, //4
-0.6f, -1.0f, //5
-0.6f, -0.8f, //4
-0.6f, -1.0f, //5
-0.4f, -0.8f, //6
-0.4f, -1.0f, //7
-0.4f, -0.8f, //6
-0.4f, -1.0f, //7
-0.2f, -0.8f, //8
-0.2f, -1.0f, //9
-0.2f, -0.8f, //8
-0.2f, -1.0f, //9
0.0f, -0.8f, //10
0.0f, -1.0f, //11
0.0f, -0.8f, //10
0.0f, -1.0f, //11
/////////////////////////////////// Texture coords:
0.0f, 1.0f, //0
0.0f, 0.0f, //1
1.0f, 1.0f, //2
1.0f, 0.0f, //3
0.0f, 1.0f, //2
0.0f, 0.0f, //3
1.0f, 1.0f, //4
1.0f, 0.0f, //5
0.0f, 1.0f, //4
0.0f, 0.0f, //5
1.0f, 1.0f, //6
1.0f, 0.0f, //7
0.0f, 1.0f, //6
0.0f, 0.0f, //7
1.0f, 1.0f, //8
1.0f, 0.0f, //9
0.0f, 1.0f, //8
0.0f, 0.0f, //9
1.0f, 1.0f, //10
1.0f, 0.0f, //11
0.0f, 1.0f, //10
0.0f, 0.0f, //11
const GLubyte indices[] = {
0, 1, 2,
3, 2, 1,
4, 5, 6,
7, 6, 5,
8, 9, 10,
11, 10, 9,
12, 13, 14,
15, 14, 13,
16, 17, 18,
19, 18, 17,
};
因为我需要更多的三角形来制作更多的三角形,所以我决定自动化它(而且,这些值以像素为单位,而不是屏幕/视口坐标,因为我打算在我的着色器中使用一些矩阵):
float vertexPositions[6400]; //Declared globally outside the function
int blah()
{
int count = 0, texture_start;
for (int y = 0; y < 20; y++)
{
for (int x = 0; x < 21; x++)
{
vertexPositions[count++] = x * 32.0f;
vertexPositions[count++] = (y + 1) * 32.0f;
vertexPositions[count++] = x * 32.0f;
vertexPositions[count++] = y * 32.0f;
if (x > 0 && x < 20)
{
vertexPositions[count++] = x * 32.0f;
vertexPositions[count++] = (y + 1) * 32.0f;
vertexPositions[count++] = x * 32.0f;
vertexPositions[count++] = y * 32.0f;
}
}
}
texture_start = count;
for (int z = 0; z < 400; z++)
{
vertexPositions[count++] = 0.0f;
vertexPositions[count++] = 1.0f;
vertexPositions[count++] = 0.0f;
vertexPositions[count++] = 0.0f;
vertexPositions[count++] = 1.0f;
vertexPositions[count++] = 1.0f;
vertexPositions[count++] = 1.0f;
vertexPositions[count++] = 0.0f;
}
return 0;
}
请注意,我没有自动化索引,因为我想确保我可以从这些新数据中获得完全相同的三角形。
问题:
我在某些GL 调用中反复遇到访问冲突。如果我在断点之间手动步进,它总是在到达glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, positionBufferObject);
.
如果我在这一行上有一个断点,在这一行之后GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
有一个断点,它会跳过(忽略?静默失败?)中间的行并在到达调用内部时中断myProgram = CreateProgram();
(这令人惊讶,因为我的顶点着色器是在之前创建的,带有相同的呼叫并且工作正常)。
GLvoid InitGL(GLvoid)
{
blah(); <----where i initialize my vertex data
FnLdInit();
GetBitmap();
//char * glVer = (char *)glGetString(GL_VERSION);
//char * glSLV = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); ---------------------------//~BREAKPOINT HERE!~
glGenBuffers(1, &positionBufferObject);
errort = glGetError();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, positionBufferObject);
//errort = glGetError();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexPositions), (const float *)vertexPositions, GL_STATIC_DRAW);
//errort = glGetError();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//errort = glGetError();
myProgram = CreateProgram(); -------------------------//~BREAKPOINT HERE!~
}
所有 glGetError() 的返回 0,规范说这意味着:没有问题或 glGetError 有自己的错误。
不管它在哪里中断,调用堆栈 pelles C 在它中断时向我显示的是 'atio6axx.dll; DrvPresentBuffers() +163B7B' 它总是在这里:
我最近为我的 Radeon HD 6850 安装了最新的 Catalyst 更新。我找不到关于 GPU/顶点缓冲区对象/等的内存限制的任何信息,而且我怀疑大约 25KB 的数据会破坏任何东西。我觉得这不是 OpenGL 问题,而是我实现代码的方式或我不熟悉的限制/内存问题。
此站点上的海报#20也有类似的问题,但它似乎与程序故障有关,而不是代码(我认为它发生在最新驱动程序出现之前,即使它是在 10 月 11 日发布的)。GetBitmap()
使用 glBindTexture 和其他调用没有问题。
这似乎是最明显的,但我从旧算法到新算法的唯一变化是数据创建的自动化。不涉及任何指针,我什至将其转换为 a const float *
,编译器甚至没有警告我这是必要的。
我是否在错误的地方寻找一个简单问题的解决方案?如果需要,我会尝试解释我的代码/添加更多代码,请问。我真的不想手动写出 ~6400 或更多的值。
编辑#1:经过一些其他测试后,即使使用旧实现,似乎也会出现此错误。我一定有一段时间没有编译它(一直在处理着色器,它们是单独的文件)。我很困惑。
编辑#2:更多代码。这是在 InitGL 之前发生的唯一函数,也是调用 InitGl 的函数。:
bool CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat;
WNDCLASS wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT WindowRect;
WindowRect.left = (long)0;
WindowRect.right = (long)width;
WindowRect.top = (long)0;
WindowRect.bottom = (long)height;
fullscreen = fullscreenflag;
hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW |CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
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, "Failed to register the window class", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
if (fullscreen)
{
int changeresult;
//char msg[100];
DISPLAY_DEVICE disp;
DEVMODE dmScreenSettings;
int dw;
memset(&disp, 0, sizeof(disp));
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
disp.cb = sizeof(disp);
if (!(EnumDisplayDevices(NULL, 0, &disp, 0)))
{
return 1;
}
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
//ENUM_CURRENT_SETTINGS
if (!(EnumDisplaySettings(disp.DeviceName, ENUM_CURRENT_SETTINGS, &dmScreenSettings)))
{
dw = GetLastError();
}
dmScreenSettings.dmPelsWidth = width; //enable this in real
dmScreenSettings.dmPelsHeight = height; //enable this in real
changeresult = ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
//dmScreenSettings.dmPelsWidth = width;
//dmScreenSettings.dmPelsHeight = height;
//dmScreenSettings.dmBitsPerPel = bits;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (changeresult != DISP_CHANGE_SUCCESSFUL)
{
if (MessageBox(NULL, "Use window mode?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
{
fullscreen = FALSE;
}
else
{
return FALSE;
}
}
}
if (fullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);
if(!(hWnd = CreateWindowEx( dwExStyle,
"OpenGL",
title,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
0,
0,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
NULL,
NULL,
hInstance,
NULL)))
{
KillGLWindow();
MessageBox(NULL, "Window Creation error", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
0, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
pfd.cColorBits = bits;
if (!(hDC = GetDC(hWnd)))
{
KillGLWindow();
MessageBox(NULL, "Can't create a GL device context", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
{
KillGLWindow();
MessageBox(NULL, "Can't find a suitable pixelformat", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
if (!SetPixelFormat(hDC, PixelFormat, &pfd))
{
KillGLWindow();
MessageBox(NULL, "Can't set the pixel format", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
if (!(hRC = wglCreateContext(hDC)))
{
KillGLWindow();
MessageBox(NULL, "Can't create a GL rendering context", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
if (!wglMakeCurrent(hDC, hRC))
{
KillGLWindow();
MessageBox(NULL, "Can't activate the GL rendering context", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
ShowWindow(hWnd, SW_SHOW);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
InitGL();
ResizeGLScene(width, height);
//char * glVer = (char *)glGetString(GL_VERSION);
//char * glSLV = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
return TRUE;
}
FnLdInit 是我连接所有扩展的地方:
void FnLdInit(void)
{
HINSTANCE hGLLIB = NULL;
hGLLIB = LoadLibrary("opengl32.dll");
glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
glBindBuffer = (PFNGLBINDBUFFERPROC)wglGetProcAddress("glBindBuffer");
glBufferData = (PFNGLBUFFERDATAPROC)wglGetProcAddress("glBufferData");
glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
glDeleteShader = (PFNGLDELETESHADERPROC)wglGetProcAddress("glDeleteShader");
glDetachShader = (PFNGLDETACHSHADERPROC)wglGetProcAddress("glDetachShader");
glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glDisableVertexAttribArray");
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
glGenBuffers = (PFNGLGENBUFFERSPROC)wglGetProcAddress("glGenBuffers");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog");
glGetShaderiv = (PFNGLGETSHADERIVPROC)wglGetProcAddress("glGetShaderiv");
glGetUniformfv = (PFNGLGETUNIFORMFVPROC)wglGetProcAddress("glGetUniformfv");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
glUniform2f = (PFNGLUNIFORM2FPROC)wglGetProcAddress("glUniform2f");
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress("glVertexAttribPointer");
glBindTexture = (PFNGLBINDTEXTUREPROC)GetProcAddress(hGLLIB, "glBindTexture");
glClear = (PFNGLCLEARPROC)GetProcAddress(hGLLIB, "glClear");
glClearColor = (PFNGLCLEARCOLORPROC)GetProcAddress(hGLLIB, "glClearColor");
glClearDepth = (PFNGLCLEARDEPTHPROC)GetProcAddress(hGLLIB, "glClearDepth");
glDepthFunc = (PFNGLDEPTHFUNCPROC)GetProcAddress(hGLLIB, "glDepthFunc");
glDrawArrays = (PFNGLDRAWARRAYSPROC)GetProcAddress(hGLLIB, "glDrawArrays");
glEnable = (PFNGLENABLEPROC)GetProcAddress(hGLLIB, "glEnable");
glGenTextures = (PFNGLGENTEXTURESPROC)GetProcAddress(hGLLIB, "glGenTextures");
glTexImage2D = (PFNGLTEXIMAGE2DPROC)GetProcAddress(hGLLIB, "glTexImage2D");
glTexParameteri = (PFNGLTEXPARAMETERIPROC)GetProcAddress(hGLLIB, "glTexParameteri");
glViewport = (PFNGLVIEWPORTPROC)GetProcAddress(hGLLIB, "glViewport");
glDrawElements = (PFNGLDRAWELEMENTSPROC)GetProcAddress(hGLLIB, "glDrawElements");
glGetError = (PFNGLGETERRORPROC)GetProcAddress(hGLLIB, "glGetError");
glGetString = (PFNGLGETSTRINGPROC)GetProcAddress(hGLLIB, "glGetString");
}
这是 GetBitmap():
int GetBitmap(void)
{
char * bmBuffer, * pxPtr;
FILE * bmFile;
//FILE * result;
GLuint texture;
int bmSize,
dataOffset,
dibSize,
bmWidthPx,
bmHeightPx,
bmCompression,
dataSize,
dataHorRes,
dataVerRes,
paletteNumClrs,
importantClrs,
bmBytesPerPixel = 3, //Default -> RGB
totalBytesPerRow,
pixelBytesPerRow,
padCount = 0;
short int bmClrPlane, bmBPP;
char bmChar0, bmChar1;
//char msgData[100];
bmFile = fopen("multisquare.bmp", "rb");
if (bmFile == NULL)
{
return 1;
}
bmChar0 = fgetc(bmFile);
bmChar1 = fgetc(bmFile);
if (bmChar0 != 'B' || bmChar1 != 'M')
{
return 2;
}
//sprintf(msgData, "%c%c", bmChar0, bmChar1);
//MessageBox(NULL, msgData, NULL, MB_OK | MB_ICONINFORMATION);
bmSize = Get4Bytes(bmFile);
//Skip 4 bytes. These bytes are application specific,
//and generally unused.
if (fseek(bmFile, 4, SEEK_CUR) != 0)
{
return 3;
}
dataOffset = Get4Bytes(bmFile);
dibSize = Get4Bytes(bmFile);
//Replace 'if dibSize' check with case statement
//which branches to functions for different sized
//DIBHeaders.
//
//
if (dibSize != 40)
{
return 4;
}
bmWidthPx = Get4Bytes(bmFile);
bmHeightPx = Get4Bytes(bmFile); //Later -> handle negative = top->bottom.
bmClrPlane = Get2Bytes(bmFile); //Must always be 1 anyways, consider removing this and skipping 2 bytes.
bmBPP = Get2Bytes(bmFile);
if (bmBPP == 24)
{
bmBytesPerPixel = 3;
}
bmCompression = Get4Bytes(bmFile);
//Handle other compressions at some later time.
if (bmCompression != 0)
{
return 5;
}
//Can use this to allocate appropriate memory space.
dataSize = Get4Bytes(bmFile);
//Resolutions doesn't seem too important atm.
dataHorRes = Get4Bytes(bmFile);
dataVerRes = Get4Bytes(bmFile);
//Will probably both be 0. Irrelevant atm.
paletteNumClrs = Get4Bytes(bmFile);
importantClrs = Get4Bytes(bmFile);
bmBuffer = (char *) calloc(dataSize, sizeof(char)); //Space allocated.
fseek(bmFile, dataOffset, SEEK_SET);
//Ex: 10 pixels * 3 bytes/pixel = 30 bytes
// 30 + 3 = 33 -> 0010 0001
// Right shift 2: 0000 1000 -> These operations round to nearest
// Shift left 2: 0010 0000 -> multiple of 4.
// 32 bytes to reach 4byte multiple
// So 30 bytes for 10 pixles plus 2 extra bytes of padding, per row.
pixelBytesPerRow = bmWidthPx * bmBytesPerPixel;
totalBytesPerRow = ((pixelBytesPerRow + bmBytesPerPixel) >> 2) << 2;
padCount = totalBytesPerRow - pixelBytesPerRow;
pxPtr = bmBuffer;
switch(padCount)
{
case 0:
{
for (int A = 0; A <= bmHeightPx; A++)
{
/*
for (int B = 0; B <= bmWidthPx; B++)
{
*(pxPtr + 2) = fgetc(bmFile);
*(pxPtr + 1) = fgetc(bmFile);
*pxPtr = fgetc(bmFile);
}
*/
fread(pxPtr, 1, pixelBytesPerRow, bmFile);
pxPtr += totalBytesPerRow;
}
break;
}
case 1:
case 2:
case 3:
{
for (int A = 0; A <= bmHeightPx; A++)
{
/*
for (int B = 0; B <= bmWidthPx; B++)
{
*(pxPtr + 2) = fgetc(bmFile);
*(pxPtr + 1) = fgetc(bmFile);
*pxPtr = fgetc(bmFile);
}
*/
fread(pxPtr, 1, pixelBytesPerRow, bmFile);
if (fseek(bmFile, padCount, SEEK_CUR) != 0)
{
return 3;
}
pxPtr += totalBytesPerRow;
}
break;
}
default:
//Shouldn't get here
break;
}
//result = fopen("test.txt","w");
//fwrite(bmBuffer, 1, dataSize , result);
//fclose(result);
fclose(bmFile);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, /*Type of texture*/
0, /*Level of Detail number*/
GL_RGB, /*Internal format*/
bmWidthPx, /*Width in texels(pixels?)*/
bmHeightPx, /*Height in texels(pixels?)*/
0, /*Border. Must be 0 (probably only for 2D)*/
GL_BGR, /*Format, of the data the texture will be created from*/
GL_UNSIGNED_BYTE,/*Data type of the pixel data*/
bmBuffer); /*Pointer to the image data to create the texture from*/
//glBindTexture(GL_TEXTURE_2D, 0);
free(bmBuffer);
return 0;
}
编辑#3:未安装的 Catalyst 12.10 和所有相关驱动程序。重新安装12.8。同样的问题,但现在它发生在 GenBuffers 上。奇怪的。
编辑#4:我尝试将我的项目制作为 32 位,并对其进行编译。我遇到了完全相同的问题,尽管出于某种原因,Pelles C 没有标记 LIB(它只是在提到一个时说“无标题”)所以我只能假设 AMD 提供的 32 位库也失败了(作为 atio6axx.dll/. lib 未加载)。我觉得这个问题不会有任何真正的解决方案,因为它似乎源于驱动程序,而不是我的代码。在搜索并看到类似这样的相关问题之后,似乎并没有真正的客户端解决方案。
编辑#5:另一个我之前没有注意到的问题,因为程序在这一点上从来没有给我访问冲突,是代码将到达glActiveTexture(GL_TEXTURE0);
并突然跳过后面的所有行并退出函数。通过删除此行,将执行下一行。glActiveTexture(GL_TEXTURE0);
is fromatio6axx.dll
而所有其他命令都是 from OPENGL32.dll
,所以它似乎已经缩小了范围。奇怪的是此时没有访问冲突,只是奇怪的跳过。
我想没有人能看到发生这种情况的原因吗?我什至安装了beta Catalyst 驱动程序,它的 atio6axx.dll 版本的日期为 15\11\2012(上个星期四)。因此,最新的驱动程序不是问题。我什至尝试了自 Catalyst 12.4 以来的每个驱动程序版本(当前是 12.10,这个程序运行 12.8)。不知所措,甚至一个新程序也遇到了同样的问题。