Как загрузить изображение для использования в качестве текстуры openGL с LWJGL? - PullRequest
6 голосов
/ 04 марта 2011

Я пытаюсь загрузить изображение в качестве текстуры для openGL, используя библиотеку LWJGL. Из того, что я обнаружил до сих пор, мне нужно передать текстуру как ByteBuffer для openGL. Сейчас у меня есть некоторый код, который правильно загружает изображение и сохраняет его в объекте BufferedImage. Дело в том, что я понятия не имею, как получить из BufferedImage ByteBuffer, который содержит данные в правильном формате для использования с openGL (как входные данные для функции GL11.glTexImage2D ()). Помощь очень ценится!

Ответы [ 4 ]

6 голосов
/ 22 апреля 2011

Вот метод из примера Space Invaders, который делает то, что вы хотите.(Я думаю)

/**
 * Convert the buffered image to a texture
 */
private ByteBuffer convertImageData(BufferedImage bufferedImage) {
    ByteBuffer imageBuffer;
    WritableRaster raster;
    BufferedImage texImage;

    ColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace
            .getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 },
            true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

    raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
            bufferedImage.getWidth(), bufferedImage.getHeight(), 4, null);
    texImage = new BufferedImage(glAlphaColorModel, raster, true,
            new Hashtable());

    // copy the source image into the produced image
    Graphics g = texImage.getGraphics();
    g.setColor(new Color(0f, 0f, 0f, 0f));
    g.fillRect(0, 0, 256, 256);
    g.drawImage(bufferedImage, 0, 0, null);

    // build a byte buffer from the temporary image
    // that be used by OpenGL to produce a texture.
    byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer())
            .getData();

    imageBuffer = ByteBuffer.allocateDirect(data.length);
    imageBuffer.order(ByteOrder.nativeOrder());
    imageBuffer.put(data, 0, data.length);
    imageBuffer.flip();

    return imageBuffer;
}
1 голос
/ 29 декабря 2016

Я использовал приведенное выше решение Рона, но цвета изображения при применении в качестве текстуры были неправильными, что означает, что принятое решение, вероятно, не даст одинаковых результатов для всех видов изображений.

Попыткаисправить проблему с цветом, я попытался использовать ColorModel оригинала BufferedImage, к которому можно обратиться, вызвав BufferedImage#getColorModel.Но это дало мне исключение, что ColorModel исходного изображения несовместимо с объектом WritableRaster.

Я искал решение для этого и нашел этот один.Вместо вызова Raster.createInterleavedRaster для создания WritableRaster я использовал ColorModel#createCompatibleWritableRaster.

Надеюсь, это поможет.Вот код:

public static ByteBuffer load(BufferedImage bufferedImage) {

    WritableRaster raster = bufferedImage.getColorModel().createCompatibleWritableRaster
        (bufferedImage.getWidth(), bufferedImage.getHeight());
    BufferedImage textureImage = new BufferedImage(bufferedImage.getColorModel(), raster,
        true, new Hashtable<>());

    Graphics graphics = textureImage.getGraphics();
    graphics.setColor(new Color(0, 0, 0));
    graphics.fillRect(0, 0, 256, 256);
    graphics.drawImage(bufferedImage, 0, 0, null);

    byte[] data = ((DataBufferByte) textureImage.getRaster().getDataBuffer()).getData();

    ByteBuffer imageBuffer = ByteBuffer.allocate(data.length);
    imageBuffer.order(ByteOrder.nativeOrder());
    imageBuffer.put(data, 0, data.length);
    imageBuffer.flip();

    return imageBuffer;
}
0 голосов
/ 24 марта 2019

Мы также можем сделать это в шейдере.

BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

DataBufferInt dbb = (DataBufferInt) image.getRaster().getDataBuffer();
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0,   GL_RGBA,   GL_UNSIGNED_INT_8_8_8_8,dbb.getData());

GL_FRAGMENT_SHADER:

#version 130

uniform sampler2D tex;

in vec2 texCoordsVarying;
out vec4 color;

void main() {
  vec4 c2 = texture(tex, texCoordsVarying);
  color = vec4(c2.g, c2.b, c2.a, c2.r);
}

Метод, заданный @Displee, использует процессорное время, если вы просто загрузите текстуру, когда все в порядке. Если вы обновляете текстуру каждый кадр, вы можете использовать шейдер, он использует графический процессор и меньше времени (1/4 раза я тестировал на своем ПК)

0 голосов
/ 21 января 2019
public static ByteBuffer imageToBuffer(BufferedImage image) {
    int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
    ByteBuffer buffer = ByteBuffer.allocateDirect(pixels.length * 4);
    for (int pixel : pixels) {
        buffer.put((byte) ((pixel >> 16) & 0xFF));
        buffer.put((byte) ((pixel >> 8) & 0xFF));
        buffer.put((byte) (pixel & 0xFF));
        buffer.put((byte) (pixel >> 24));
    }
    buffer.flip();
    return buffer;
}

работал на меня.

...