Проблемы с нарезкой и выравниванием glTexImage2D, появляющиеся в окне

Я работаю над созданием собственной топографической карты и использую файлы .hgt от НАСА.

Я загружаю файлы, используя

void MapImage::load_map_file(const char* filename) {
    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file) {
        std::cout << "Error opening file!" << std::endl;
    }
    std::vector<short> tempHeight(TOTAL_SIZE);
    unsigned char buffer[2];

    int x, y;
    for (int i = 0; i < TOTAL_SIZE; i++) {
        if (!file.read(reinterpret_cast<char*>(buffer), sizeof(buffer))) {
            std::cout << "Error reading file!" << std::endl;
        }
        tempHeight[i] = (buffer[0] << 8) | buffer[1];
    }

    height = tempHeight;
}

А затем добавить их в растровое изображение в памяти, используя:

void MapImage::loadTextureImage() {
img_tex = 0;
glGenTextures(1, &img_tex);

int x, y, w, h;
w = h = SRTM_SIZE;
unsigned char* img;
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, sizeof(img));

int g = 0;
double height_color;

/*
for(int i = 0; i < TOTAL_SIZE; i++){
    height_color = (float)height[i] / 10.0;
    g = (height_color * 255);
    if (g>255)g = 255;

    img[i * 3 + 2] = (unsigned char)0;
    img[i * 3 + 1] = (unsigned char)g;
    img[i * 3 + 0]= (unsigned char)0;
}
*/

for (int i = 0; i < w; i++) {
    for (int j = 0; j < h; ++j) {
        x = i; 
        y = (h - 1) - j;

        height_color = (float)height[j + (i * w)] / 10.0;
        g = (height_color * 255);
        if (g>255)g = 255;

        img[(x + y*w) * 3 + 2] = (unsigned char)0;
        img[(x + y*w) * 3 + 1] = (unsigned char)g;
        img[(x + y*w) * 3]     = (unsigned char)0;
    }
}


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, img_tex);

glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_RGB,
    w,
    h,
    0,
    GL_RGB,
    GL_UNSIGNED_BYTE,
    img
);
}

Однако это приводит к изображению со срезанным углом, например Нарезанное изображение

Использование закомментированной версии в loadTextureImage() выглядит немного иначе, однако с тем же срезанным углом. Разрезанное изображение 2

У кого-нибудь есть намек на то, что происходит? Я пытался использовать изображение в качестве текстуры, загрузив библиотеку stbi, и это работает нормально, поэтому я не уверен, где что-то не так.

(координаты изображения N10E099)


person AlexVestin    schedule 03.08.2017    source источник


Ответы (1)


Это похоже на несовпадение строк, вызванное 3-ширинными данными цвета. Попробуйте использовать следующий вызов непосредственно перед glTexImage2D:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

Это значение выравнивания, которое по умолчанию равно 4, используется glTexImage2D и его друзьями всякий раз, когда данные текстуры считываются для отправки в графический процессор.

Нет никакой проверки того, что они соответствуют тому, как на самом деле выглядят данные, поэтому в таких случаях, как ваш, когда строка не заканчивается на 4-байтовой границе, первые несколько байтов следующей строки будут пропущены, что приведет к этому диагональному искажению. .

Передача текстурных данных в другом направлении (от графического процессора в память клиента) выравнивается через glPixelStorei(GL_PACK_ALIGNMENT, 1);.

person Quentin    schedule 03.08.2017
comment
@AlexVestin так ... Какой это был? Надеюсь, я запомню это в следующий раз :p - person Quentin; 03.08.2017
comment
Я буду, нужно еще пару минут. Первый, glPixelStorei(GL_UNPACK_ALIGNMENT, 1);! - person AlexVestin; 03.08.2017
comment
@Квентин, почему ты удалил нижнюю часть!! - person Krupip; 03.08.2017
comment
@snb хорошо, потому что он предназначен для получения данных текстуры с графического процессора, а не для их отправки (что является фактической проблемой). Я просто не мог точно вспомнить, что было чем, поэтому я включил оба. - person Quentin; 03.08.2017
comment
@ Квентин, почему ему пришлось исправлять выравнивание в этом случае? Какая часть будет смещена? Изображение на самом деле 4 байта? В противном случае похоже, что это должно было сработать, учитывая, что и устройство, и хост настроены на rgb на glTexImage2D. - person Krupip; 03.08.2017
comment
@snb, честно говоря, я не знаю, почему он был разработан таким образом. Какими бы ни были исходный и внутренний форматы, glTexImage2D и его друзья по умолчанию попытаются выровнять строки по кратным 4 байтам, даже если это не соответствует ширине формата. Я нахожу это довольно неясным и потерял много времени, когда это впервые случилось со мной. - person Quentin; 03.08.2017
comment
@ Квентин, можешь добавить это к ответу? Я знаю, что эта информация вызовет у многих головную боль в будущем. - person Krupip; 03.08.2017
comment
@snb Хорошая идея, я так и сделал. - person Quentin; 03.08.2017