OpenGL не работает при изменении размера буфера

Мне нужно обновлять массив пикселей на экране каждый кадр. Изначально работает, однако при попытке изменить размер экрана глючит и в итоге выкидывает 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

Решение

Как упоминалось @genpfault, OpenGL читает 4 байта на пиксель вместо вашего предположения 3.

Вместо смены GL_UNPACK_ALIGNMENTВы также можете изменить свой код на правильное допущение 4 байта на пиксель с помощью простого struct:

struct pixel {
unsigned char r, g, b;
unsigned char unused;
};

Тогда вместо магической константы 3 вы можете использовать гораздо более четкое sizeof(struct pixel), Это облегчает чтение и передачу смысла кода, и это не приводит к дополнительному коду (поскольку структура «эффективно» представляет собой массив из 4 байтов).

2

Другие решения

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(),

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. Но с 3 байтами на пиксель в GL_RGB В используемом формате размер строки кратен 4 байтам, если число пикселей кратно 4. Таким образом, для плотно упакованных строк с 3 байтами на пиксель значение должно быть установлено равным 1.

0
По вопросам рекламы [email protected]