Я использую библиотеку 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!
Проблема в том, что красный и синий цвет канала поменялись местами.
В 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.
Других решений пока нет …