簡體   English   中英

調整緩沖區大小時OpenGL失敗

[英]OpenGL fails when resizing buffer

我需要每幀更新屏幕像素陣列。 它最初可以正常工作,但是當我嘗試調整屏幕大小時,它會出現毛刺並最終拋出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。

如@genpfault所述,OpenGL每個像素讀取4個字節,而不是您假設的3個字節。

除了更改GL_UNPACK_ALIGNMENT ,您還可以通過一個簡單的struct將代碼更改為每個像素4字節的正確假設:

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

然后,可以使用更清晰的sizeof(struct pixel)代替魔術常數3。 這使得閱讀和傳達代碼意圖更加容易,並且不會導致任何額外的代碼(因為該結構“有效地”是4個字節的數組)。

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
                                                         ^^^^^^

GL_UNPACK_ALIGNMENT默認為4 ,而不是1 因此,OpenGL將為每個像素讀取4個字節,而不是您假設的3個字節。

使用glPixelStorei()GL_UNPACK_ALIGNMENT設置為1

聽起來您找到了可行的方法,但是我認為問題沒有得到正確診斷。 我認為最大的問題是在此處初始化紋理數據的方式:

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的倍數,則行的大小僅是4字節的倍數。因此,對於緊密排列的行每像素3個字節,則需要將該值設置為1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM