Текстура не отображается FreeGLUT - PullRequest
0 голосов
/ 06 мая 2020

У меня есть простая плоскость (квадрат) с освещением и материалом, я хочу наложить на нее текстуру земли. но ничего не появляется. Я проверил и думаю, что он правильно загружает данные RGB, поэтому я предполагаю, что есть проблема с этой строкой (данные - * char, а изображение - BMP24)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);

вот функция загрузки .bmp:

GLuint LoadTexture(const char* imagepath) {
    printf("Reading image %s\n", imagepath);
    unsigned int outWidth = -1;
    unsigned int outHeight = -1;
    unsigned char header[54];
    unsigned int dataPos;
    unsigned int imageSize;

    FILE* file;
    if (errno_t err = fopen_s(&file, imagepath, "rb") != 0) {
        perror("Can't Open file");
        return 0;
    }

    // If less than 54 byes are read, problem
    if (fread(header, 1, 54, file) != 54) {
        printf("Not a correct BMP file\n");
        return NULL;
    }
    // A BMP files always begins with "BM"
    if (header[0] != 'B' || header[1] != 'M') {
        printf("Not a correct BMP file\n");
        return NULL;
    }
    // Make sure this is a 24bpp file
    if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n");    return NULL; }
    if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n");    return NULL; }

    // Read the information about the image
    dataPos = *(int*)&(header[0x0A]);
    outWidth = *(int*)&(header[0x12]);
    outHeight = *(int*)&(header[0x16]);
    imageSize = *(int*)&(header[0x22]);

    // Some BMP files are misformatted, guess missing information
    if (imageSize == 0)    imageSize = outWidth * outHeight * 3; // 3 : one byte for each Red, Green and Blue component
    if (dataPos == 0)      dataPos = 54; // The BMP header is done that way

    // Read the actual data from the file into the buffer
    unsigned char* data = new unsigned char[imageSize];
    fread(data, 3, imageSize, file);


    // Everything is in memory now, the file wan be closed
    fclose(file);

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);

    return tex;
}

вот основная функция и функция отображения:

void render(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float ratio = 0.75;
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, earthTextureData);

    glBegin(GL_QUADS);
    glVertex3f(-0.5, -0.5, 0);
    glVertex3f(-0.5, 0.5, 0);
    glVertex3f(0.5, 0.5, 0);
    glVertex3f(0.5, -0.5, 0);
    glEnd();

    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
}


int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(1200, 800);
    glutCreateWindow("app");

    init(); // custome initilizing
    initLighting();

    earthTextureData = LoadTexture("Texture/globe.bmp");

    glutDisplayFunc(render);
    glutReshapeFunc(reshape);
    glutMotionFunc(mouseMove);
    glutKeyboardFunc(keyboard);
    glutIdleFunc(idle);

    glutMainLoop();
}

Я играл с кодом, а иногда (когда я использую int вместо char *) я получаю красный материал, покрывающий все, но не знаю точно, что его вызывает

UPDATE: пришлось изменить несколько строк, чтобы он работал (для файлов bmp24):

1 - отредактируйте эту строку: fread (data, 1, imageSize, file);

2 - добавьте эту строку: glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

3- отредактируйте эту строку (для правильного отображения цветов): glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid *) data);

4-добавить UV-координаты (поиск glTexCoord)

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Вы пропустили установку параметров текстуры на glTexParameter.

Если вы не генерируете mipmaps (glGenerateMipmap), тогда установка GL_TEXTURE_MIN_FILTER важна. Поскольку фильтр по умолчанию - GL_NEAREST_MIPMAP_LINEAR, текстура будет неполной mipmap, если вы не измените функцию минимизации на GL_NEAREST или GL_LINEAR.

Когда изображение загружается в объект текстуры, тогда GL_UNPACK_ALIGNMENT должно быть установлено на 1.
По умолчанию GL_UNPACK_ALIGNMENT равно 4, поэтому предполагается, что каждая строка изображения выровнена по 4 байтам. Пиксели BMP-файла обычно имеют размер 3 байта и плотно упакованы, это может вызвать рассогласование.

GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outWidth, outHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

Конечно, вы должны установить параметр текстуры на glTexCoord, перед указанием координаты вершины (glVertex), как указано в другом ответе:

glBindTexture(GL_TEXTURE_2D, earthTextureData);

glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);

glTexCoord2f(0.0, 0.0);
glVertex3f(-0.5, -0.5, 0);

glTexCoord2f(0.0, 1.0);
glVertex3f(-0.5, 0.5, 0);

glTexCoord2f(1.0, 1.0);
glVertex3f(0.5, 0.5, 0);

glTexCoord2f(1.0, 0.0);
glVertex3f(0.5, -0.5, 0);

glEnd();
glDisable(GL_TEXTURE_2D);
0 голосов
/ 06 мая 2020

Вы должны сообщить OpenGL координаты UV, где и как разместить эту текстуру. Это можно сделать в вашей функции рендеринга.

UV-координаты находятся в диапазоне от 0,0 до 1,0 и сообщают OpenGL, как разместить текстуру на рендере.

Вот хорошее изображение, которое хорошо иллюстрирует uv-координаты

Должно работать что-то вроде этого:

void render(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float ratio = 0.75;
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, earthTextureData);

    glBegin(GL_QUADS);
    glTexCoord3f(0.0, 0.0, 0.0);
    glVertex3f(-0.5, -0.5, 0);

    glTexCoord3f(0.0, 1.0, 0.0);
    glVertex3f(-0.5, 0.5, 0);

    glTexCoord3f(1.0, 1.0, 0.0);
    glVertex3f(0.5, 0.5, 0);

    glTexCoord3f(1.0, 0.0, 0);
    glVertex3f(0.5, -0.5, 0);
    glEnd();

    glDisable(GL_TEXTURE_2D);

    glutSwapBuffers();
}
...