Как я могу загрузить bufferedImage в качестве текстуры OpenGL? - PullRequest
1 голос
/ 22 января 2020

Я пытаюсь создать текстуру из загруженного буферизованного изображения следующим образом:

public static long loadTexture(String img) throws IOException{


     File imgPath = new File(img);
     BufferedImage bufferedImage = ImageIO.read(imgPath);


    byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
    int id = glGenTextures();

    glBindTexture(GL_TEXTURE_2D, id);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferedImage.getWidth(), bufferedImage.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, ByteBuffer.wrap(pixels));

    glGenerateMipmap(GL_TEXTURE_2D);

    return id; 
}

Но этот код дает мне ошибку java sigsegv. Я использую Java .nio.Bytebuffer, потому что солнечный не поддерживается в java 11. Так что я делаю не так? Изображение загружено правильно, с 4bpp:

//last 2 digits are lenght
FF-AD-6F-CB-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-00-00-FF-FF-00-00-FF-FF-FF-FF-00-FF-FF-FF-00-FF-00-00-FF-FF-00-00-FF-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-FF-FF-FF-00-64

Вот изображение: enter image description here оно довольно маленькое, но данные верны.

Так почему я получаю sigsegv? журнал довольно бесполезный и длинный, поэтому я не могу его опубликовать.

А как мне создать текстуру opengl из байтового массива 4bpp?

1 Ответ

2 голосов
/ 22 января 2020

Как указано в Java Code Examples for org.lwjgl.opengl.GL11.glTexImage2D() (пример 5), вы должны скопировать данные в ByteBuffer в циклах:

public static long loadTexture(String img) throws IOException{

    File imgPath = new File(img);
    BufferedImage image = ImageIO.read(imgPath);

    int[] pixels = new int[image.getWidth() * image.getHeight()];
    image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
    ByteBuffer buffer = ByteBuffer.allocateDirect(image.getWidth() * image.getHeight() * 4);

    for(int h = 0; h < image.getHeight(); h++) {
        for(int w = 0; w < image.getWidth(); w++) {
            int pixel = pixels[h * image.getWidth() + w];

            buffer.put((byte) ((pixel >> 16) & 0xFF));
            buffer.put((byte) ((pixel >> 8) & 0xFF));
            buffer.put((byte) (pixel & 0xFF));
            buffer.put((byte) ((pixel >> 24) & 0xFF));
        }
    }

    buffer.flip();

    int id = glGenTextures();
    glBindTexture(GL_TEXTURE_2D, id);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(),
                 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    glGenerateMipmap(GL_TEXTURE_2D);

    return id; 
}

Примечание, glPixelStorei(GL_UNPACK_ALIGNMENT, 1) в этом случае не требуется, поскольку размер пикселя RGBA составляет 4 байта, поэтому каждая строка выравнивается по 4 байта, а GL_UNPACK_ALIGNMENT по умолчанию равно 4.

Более того, если вы хотите использовать Mipmaps (glGenerateMipmap), тогда функция минимизации (GL_TEXTURE_MIN_FILTER) должна быть GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR или GL_LINEAR_MIPMAP_LINEAR. (См glTexParameter)

...