我需要每帧更新一个像素数组到屏幕。它最初工作,但是当我尝试调整屏幕大小时,它会出现故障并最终抛出EXC_BAD_ACCESS 1
。我已经检查过每个帧之前缓冲区是否分配了正确的大小,但它似乎不会影响结果。
#include <stdio.h>
#include <stdlib.h>
#include <GLUT/GLUT.h>
unsigned char *buffer = NULL;
int width = 400, height = 400;
unsigned int screenTexture;
void Display()
{
for (int y = 0; y < height; y+=4) {
for (int x = 0; x < width; x++) {
buffer[(x + y * width) * 3] = 255;
}
}
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// This function results in EXC_BAD_ACCESS 1, although the buffer is always correctly allocated
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glMatrixMode(GL_MODELVIEW);
glBegin (GL_QUADS);
glTexCoord2f(0,0); glVertex2i(0, 0);
glTexCoord2f(1,0); glVertex2i(width,0);
glTexCoord2f(1,1); glVertex2i(width,height);
glTexCoord2f(0,1); glVertex2i(0, height);
glEnd ();
glFlush();
glutPostRedisplay();
}
void Resize(int w, int h)
{
width = w;
height = h;
buffer = (unsigned char *)realloc(buffer, sizeof(unsigned char) * width * height * 3);
if (!buffer) {
printf("Error Reallocating buffer\n");
exit(1);
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(width, height);
glutCreateWindow("Rasterizer");
glutDisplayFunc(Display);
glutReshapeFunc(Resize);
glGenTextures(1, &screenTexture);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glDisable(GL_DEPTH_TEST);
buffer = (unsigned char *)malloc(sizeof(unsigned char) * width * height * 3);
glutMainLoop();
}
调整大小后屏幕无法正常显示:
是什么导致了这个问题?代码编译并运行,您只需链接GLUT和OpenGL。
答案 0 :(得分:2)
正如@genpfault所提到的,OpenGL每个像素读取4个字节,而不是假设3个。
您也可以通过简单的GL_UNPACK_ALIGNMENT
将代码更改为每像素4个字节的正确假设,而不是更改struct
:
struct pixel {
unsigned char r, g, b;
unsigned char unused;
};
然后,您可以使用更清晰的sizeof(struct pixel)
,而不是使用魔术常数3。这使得更容易阅读和传达代码的意图,并且它不会产生任何额外的代码(因为结构是&#34;有效&#34; 4字节的数组)。
答案 1 :(得分:0)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
^^^^^^
GL_UNPACK_ALIGNMENT
默认为4
,而不是1
。因此OpenGL将为每个像素读取 4 字节,而不是您所假设的3个字节。
使用GL_UNPACK_ALIGNMENT
将1
设置为glPixelStorei()
。
答案 2 :(得分:0)
听起来你发现了一些有效的东西,但我认为问题没有得到正确的诊断。我认为最大的问题在于你在这里初始化纹理数据:
for (int y = 0; y < height; y+=4) {
for (int x = 0; x < width; x++) {
buffer[(x + y * width) * 3] = 255;
}
}
这仅在每第4行设置数据,然后仅在这些行中的每第3个字节设置数据。要将所有数据初始化为白色,您需要将行号(y
)递增1而不是4,并在循环中设置所有3个组件:
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
buffer[(x + y * width) * 3 ] = 255;
buffer[(x + y * width) * 3 + 1] = 255;
buffer[(x + y * width) * 3 + 2] = 255;
}
}
您还需要将GL_UNPACK_ALIGNMENT
设置为1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
这可以控制行对齐(不是像素对齐,如其他几个答案所示)。 GL_UNPACK_ALIGNMENT
的默认值为4.但是如果您使用的GL_RGB
格式为每像素3个字节,则如果像素数为多个,则行的大小仅为4个字节的倍数因此,对于具有3个字节/像素的紧密排列的行,该值需要设置为1。