Почему текстурное изображение цветов не совпадает с оригиналом?

Я использую библиотеку LWJGL (OpenGL для Java) для наложения текстур.
Вот код для чтения изображения из файла:

BufferedImage image = ImageIO.read(new File(url));

Код для получения Data Raster (Pixels of image) в виде байтового массива:

DataBufferByte imageByteBuffer = ((DataBufferByte)image.getRaster().getDataBuffer());
byte[] bytePixels = imageByteBuffer.getData();

Теперь код создания и помещения массива «bytePixels» в байтовый буфер:

pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();

Здесь для привязки всего этого к буферу:

id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, image.getWidth(), image.getHeight(), 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, pixels);

Проблема в том, что цвета изображения не соответствуют цветам оригинального изображения!

Исходное изображение:

введите описание изображения здесь

Текстурированное изображение:

введите описание изображения здесь


Этот ответ на OpenGL Рендерит текстуру с цветом, отличным от исходного изображения?, не могу решить эту проблему, потому что GL_BGR не действует в lwjgl класс GL11!

1

Решение

Проблема в том, что красный и синий цвет канала поменялись местами.

В OpenGL есть возможность использовать GL_BGR формат, который определяет внутренний формат, в котором меняются каналы цвета (по сравнению с GL_RGB).

Увидеть OpenGL 4 Refpages — glTexImage2D
а также OpenGL Рендерит текстуру с цветом, отличным от исходного изображения?.

В OpenGL ES вы должны вручную поменять канал красного и синего цветов, потому что внутренний формат GL_BGR пропал, отсутствует.

Увидеть OpenGL ES 3.0 Refpages — glTexImage2D
а также lwjgl — class GL11.

pixels = BufferUtils.createByteBuffer(bytePixels.length);
pixels.put(bytePixels);
pixels.flip();
for (int i = 0; i < pixels.length; i += 3) {
byte t = pixels[i];
pixels[i] = pixels[i+2];
pixels[i+2] = t;
}

Другая возможность будет предоставлена ​​в OpenGL ES 3.0 или расширении OpenGL EXT_texture_swizzle:

Начиная с OpenGL ES 3.0, вы можете использовать параметры текстуры Swizzle для смены цветовых каналов. Увидеть glTexParameter:

GL_TEXTURE_SWIZZLE_R

Устанавливает swizzle, который будет применен к r-компоненту texel, прежде чем он будет возвращен в шейдер. Допустимые значения для параметра: GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_ZERO а также GL_ONE, Если GL_TEXTURE_SWIZZLE_R является GL_REDзначение для r будет взято из первого канала извлеченного текселя. Если GL_TEXTURE_SWIZZLE_R является GL_GREENзначение для r будет взято со второго канала извлеченного текселя. …

Это означает, что каналы цветов будут заменены при поиске текстуры путем установки следующих параметров текстуры для объекта текстуры:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);

Соответствующая часть в спецификации может быть найдена на Спецификация OpenGL ES 3.0.5; 3.8.14 Состояние текстуры; страница 162

Чтобы проверить, действительно ли расширение OpenGL, glGetString(GL_EXTENSIONS) можно использовать, который возвращает разделенный пробелами список поддерживаемых расширений.

Смотри алос растровый пиксельный формат Android для glTexImage2D.

0

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

Других решений пока нет …

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