Java 如何从PNG加载LWJGL中的纹理而不使用Slick?

Java 如何从PNG加载LWJGL中的纹理而不使用Slick?,java,textures,lwjgl,Java,Textures,Lwjgl,嗨,我对LWJGL(或OpenGL)相当陌生,尽管我有Java方面的经验。我想知道如何在立方体的每一面呈现不同的PNG纹理,我想远离LWJGL以外的其他第三方库。谢谢你的帮助 自LWJGL3起,已包含用于的绑定。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体 要渲染每侧具有不同纹理的立方体,有两个选项: 使用另一个纹理绑定分别渲染每个面。这是更直接的选择 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时 。(它是C++的,但

嗨,我对LWJGL(或OpenGL)相当陌生,尽管我有Java方面的经验。我想知道如何在立方体的每一面呈现不同的PNG纹理,我想远离LWJGL以外的其他第三方库。谢谢你的帮助

自LWJGL3起,已包含用于的绑定。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体


要渲染每侧具有不同纹理的立方体,有两个选项:

  • 使用另一个纹理绑定分别渲染每个面。这是更直接的选择
  • 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时

  • 。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体


    要渲染每侧具有不同纹理的立方体,有两个选项:

  • 使用另一个纹理绑定分别渲染每个面。这是更直接的选择
  • 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时

  • 。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体


    要渲染每侧具有不同纹理的立方体,有两个选项:

  • 使用另一个纹理绑定分别渲染每个面。这是更直接的选择
  • 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时

  • 。(它是C++的,但应该很容易转换成java)。这是一个小的单文件实用程序库,可以加载纹理、声音文件或字体


    要渲染每侧具有不同纹理的立方体,有两个选项:

  • 使用另一个纹理绑定分别渲染每个面。这是更直接的选择
  • 对所有纹理进行渲染,并渲染整个立方体一次。这并不容易做到,但会提供更好的性能,尤其是在渲染多个多维数据集时
  • 。(它是C++的,但应该很容易转换成java)。< /P> < P>查看LWJGL示例。
    /*
    *版权所有LWJGL。版权所有。
    *许可条款:https://www.lwjgl.org/license
    */
    包org.lwjgl.demo.stb;
    导入org.lwjgl.glfw.*;
    导入org.lwjgl.opengl.*;
    导入org.lwjgl.system.*;
    导入java.io.*;
    导入java.nio.*;
    导入java.util.*;
    导入静态java.lang.Math.*;
    导入静态org.lwjgl.demo.glfw.GLFWUtil.*;
    导入静态org.lwjgl.demo.util.IOUtil.*;
    导入静态org.lwjgl.glfw.Callbacks.*;
    导入静态org.lwjgl.glfw.glfw.*;
    导入静态org.lwjgl.opengl.GL11.*;
    导入静态org.lwjgl.opengl.GL12.*;
    导入静态org.lwjgl.stb.STBImage.*;
    导入静态org.lwjgl.stb.stbimanagesize.*;
    导入静态org.lwjgl.system.MemoryStack.*;
    导入静态org.lwjgl.system.MemoryUtil.*;
    /**机顶盒图像演示*/
    公开期末班形象{
    私人最终ByteBuffer图像;
    私人终审法院;
    私人终审法院;
    私人最终国际比较;
    私人长窗;
    私人国际ww;
    私有int-wh;
    私有布尔ctrlDown;
    私有整数规模;
    私有回调debugProc;
    私有映像(字符串imagePath){
    ByteBuffer图像缓冲区;
    试一试{
    imageBuffer=ioResourceToByteBuffer(imagePath,8*1024);
    }捕获(IOE异常){
    抛出新的运行时异常(e);
    }
    try(MemoryStack stack=stackPush()){
    IntBuffer w=stack.mallocInt(1);
    intbufferh=stack.mallocInt(1);
    IntBuffer comp=stack.mallocInt(1);
    //使用info读取图像元数据而不解码整个图像。
    //我们不需要这个演示,只是测试API。
    如果(!stbi_info_from_memory(imageBuffer,w,h,comp)){
    抛出新的运行时异常(“读取映像信息失败:+stbi_failure_reason());
    }否则{
    System.out.println(“确定原因:+stbi_failure_reason());
    }
    System.out.println(“图像宽度:+w.get(0));
    System.out.println(“图像高度:+h.get(0));
    System.out.println(“图像组件:+comp.get(0));
    System.out.println(“图像HDR:+stbi_是来自_内存(imageBuffer))的_HDR_);
    //解码图像
    image=stbi\u从内存加载(imageBuffer,w,h,comp,0);
    if(image==null){
    抛出新的运行时异常(“加载映像失败:+stbi_failure_reason());
    }
    这个.w=w.get(0);
    这个.h=h.get(0);
    this.comp=comp.get(0);
    }
    }
    公共静态void main(字符串[]args){
    字符串图像路径;
    如果(args.length==0){
    System.out.println(“使用'antdemo-Dclass=org.lwjgl.demo.stb.Image-Dargs='加载不同的映像。\n”);
    imagePath=“lwjgl32.png”;
    }否则{
    imagePath=args[0];
    }
    新建图像(imagePath).run();
    }
    私家车{
    试一试{
    init();
    loop();
    }最后{
    试一试{
    破坏();
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    }
    私有无效窗口大小更改(长窗口、整型宽度、整型高度){
    this.ww=宽度;
    这.wh=高度;
    glMatrixMode(GL_投影);
    glLoadIdentity();
    
    /*
     * Copyright LWJGL. All rights reserved.
     * License terms: https://www.lwjgl.org/license
     */
    package org.lwjgl.demo.stb;
    
    import org.lwjgl.glfw.*;
    import org.lwjgl.opengl.*;
    import org.lwjgl.system.*;
    
    import java.io.*;
    import java.nio.*;
    import java.util.*;
    
    import static java.lang.Math.*;
    import static org.lwjgl.demo.glfw.GLFWUtil.*;
    import static org.lwjgl.demo.util.IOUtil.*;
    import static org.lwjgl.glfw.Callbacks.*;
    import static org.lwjgl.glfw.GLFW.*;
    import static org.lwjgl.opengl.GL11.*;
    import static org.lwjgl.opengl.GL12.*;
    import static org.lwjgl.stb.STBImage.*;
    import static org.lwjgl.stb.STBImageResize.*;
    import static org.lwjgl.system.MemoryStack.*;
    import static org.lwjgl.system.MemoryUtil.*;
    
    /** STB Image demo. */
    public final class Image {
    
        private final ByteBuffer image;
    
        private final int w;
        private final int h;
        private final int comp;
    
        private long window;
        private int  ww;
        private int  wh;
    
        private boolean ctrlDown;
    
        private int scale;
    
        private Callback debugProc;
    
        private Image(String imagePath) {
            ByteBuffer imageBuffer;
            try {
            imageBuffer = ioResourceToByteBuffer(imagePath, 8 * 1024);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    
        try (MemoryStack stack = stackPush()) {
            IntBuffer w    = stack.mallocInt(1);
            IntBuffer h    = stack.mallocInt(1);
            IntBuffer comp = stack.mallocInt(1);
    
            // Use info to read image metadata without decoding the entire image.
            // We don't need this for this demo, just testing the API.
            if (!stbi_info_from_memory(imageBuffer, w, h, comp)) {
                throw new RuntimeException("Failed to read image information: " + stbi_failure_reason());
            } else {
                System.out.println("OK with reason: " + stbi_failure_reason());
            }
    
            System.out.println("Image width: " + w.get(0));
            System.out.println("Image height: " + h.get(0));
            System.out.println("Image components: " + comp.get(0));
            System.out.println("Image HDR: " + stbi_is_hdr_from_memory(imageBuffer));
    
            // Decode the image
            image = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
            if (image == null) {
                throw new RuntimeException("Failed to load image: " + stbi_failure_reason());
            }
    
            this.w = w.get(0);
            this.h = h.get(0);
            this.comp = comp.get(0);
        }
        }
    
        public static void main(String[] args) {
            String imagePath;
            if (args.length == 0) {
                System.out.println("Use 'ant demo -Dclass=org.lwjgl.demo.stb.Image -Dargs=<path>' to load a different image.\n");
                imagePath = "lwjgl32.png";
            } else {
                imagePath = args[0];
            }
            new Image(imagePath).run();
        }
    
        private void run() {
            try {
                init();
    
                loop();
            } finally {
                try {
                    destroy();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
        private void windowSizeChanged(long window, int width, int height) {
            this.ww = width;
            this.wh = height;
    
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
            glMatrixMode(GL_MODELVIEW);
        }
    
        private static void framebufferSizeChanged(long window, int width, int height) {
            glViewport(0, 0, width, height);
        }
    
        private void init() {
            GLFWErrorCallback.createPrint().set();
            if (!glfwInit()) {
                throw new IllegalStateException("Unable to initialize GLFW");
            }
    
            glfwDefaultWindowHints();
            glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
            glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    
            GLFWVidMode vidmode = Objects.requireNonNull(glfwGetVideoMode(glfwGetPrimaryMonitor()));
    
            ww = max(800, min(w, vidmode.width() - 160));
            wh = max(600, min(h, vidmode.height() - 120));
    
            this.window = glfwCreateWindow(ww, wh, "STB Image Demo", NULL, NULL);
            if (window == NULL) {
                throw new RuntimeException("Failed to create the GLFW window");
            }
    
            // Center window
            glfwSetWindowPos(
                window,
                (vidmode.width() - ww) / 2,
                (vidmode.height() - wh) / 2
            );
    
            glfwSetWindowRefreshCallback(window, window -> render());
            glfwSetWindowSizeCallback(window, this::windowSizeChanged);
            glfwSetFramebufferSizeCallback(window, Image::framebufferSizeChanged);
    
            glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
                ctrlDown = (mods & GLFW_MOD_CONTROL) != 0;
                if (action == GLFW_RELEASE) {
                    return;
                }
    
                switch (key) {
                    case GLFW_KEY_ESCAPE:
                        glfwSetWindowShouldClose(window, true);
                        break;
                    case GLFW_KEY_KP_ADD:
                    case GLFW_KEY_EQUAL:
                        setScale(scale + 1);
                        break;
                    case GLFW_KEY_KP_SUBTRACT:
                    case GLFW_KEY_MINUS:
                        setScale(scale - 1);
                        break;
                    case GLFW_KEY_0:
                    case GLFW_KEY_KP_0:
                        if (ctrlDown) {
                            setScale(0);
                        }
                        break;
                }
            });
    
            glfwSetScrollCallback(window, (window, xoffset, yoffset) -> {
                if (ctrlDown) {
                    setScale(scale + (int)yoffset);
                }
            });
    
            // Create context
            glfwMakeContextCurrent(window);
            GL.createCapabilities();
            debugProc = GLUtil.setupDebugMessageCallback();
    
            glfwSwapInterval(1);
            glfwShowWindow(window);
    
            glfwInvoke(window, this::windowSizeChanged, Image::framebufferSizeChanged);
        }
    
        private void setScale(int scale) {
            this.scale = max(-9, scale);
        }
    
        private void premultiplyAlpha() {
            int stride = w * 4;
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    int i = y * stride + x * 4;
    
                    float alpha = (image.get(i + 3) & 0xFF) / 255.0f;
                    image.put(i + 0, (byte)round(((image.get(i + 0) & 0xFF) * alpha)));
                    image.put(i + 1, (byte)round(((image.get(i + 1) & 0xFF) * alpha)));
                    image.put(i + 2, (byte)round(((image.get(i + 2) & 0xFF) * alpha)));
                }
            }
        }
    
        private int createTexture() {
            int texID = glGenTextures();
    
            glBindTexture(GL_TEXTURE_2D, texID);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
            int format;
            if (comp == 3) {
                if ((w & 3) != 0) {
                    glPixelStorei(GL_UNPACK_ALIGNMENT, 2 - (w & 1));
                }
                format = GL_RGB;
            } else {
                premultiplyAlpha();
    
                glEnable(GL_BLEND);
                glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    
                format = GL_RGBA;
            }
    
            glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, image);
    
            ByteBuffer input_pixels = image;
            int        input_w      = w;
            int        input_h      = h;
            int        mipmapLevel  = 0;
            while (1 < input_w || 1 < input_h) {
                int output_w = Math.max(1, input_w >> 1);
                int output_h = Math.max(1, input_h >> 1);
    
                ByteBuffer output_pixels = memAlloc(output_w * output_h * comp);
                stbir_resize_uint8_generic(
                    input_pixels, input_w, input_h, input_w * comp,
                    output_pixels, output_w, output_h, output_w * comp,
                    comp, comp == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE, STBIR_FLAG_ALPHA_PREMULTIPLIED,
                    STBIR_EDGE_CLAMP,
                    STBIR_FILTER_MITCHELL,
                    STBIR_COLORSPACE_SRGB
                );
    
                if (mipmapLevel == 0) {
                    stbi_image_free(image);
                } else {
                    memFree(input_pixels);
                }
    
                glTexImage2D(GL_TEXTURE_2D, ++mipmapLevel, format, output_w, output_h, 0, format, GL_UNSIGNED_BYTE, output_pixels);
    
                input_pixels = output_pixels;
                input_w = output_w;
                input_h = output_h;
            }
            if (mipmapLevel == 0) {
                stbi_image_free(image);
            } else {
                memFree(input_pixels);
            }
    
            return texID;
        }
    
        private void loop() {
            int texID = createTexture();
    
            glEnable(GL_TEXTURE_2D);
            glClearColor(43f / 255f, 43f / 255f, 43f / 255f, 0f);
    
            while (!glfwWindowShouldClose(window)) {
                glfwPollEvents();
                render();
            }
    
            glDisable(GL_TEXTURE_2D);
            glDeleteTextures(texID);
        }
    
        private void render() {
            glClear(GL_COLOR_BUFFER_BIT);
    
            float scaleFactor = 1.0f + scale * 0.1f;
    
            glPushMatrix();
            glTranslatef(ww * 0.5f, wh * 0.5f, 0.0f);
            glScalef(scaleFactor, scaleFactor, 1f);
            glTranslatef(-w * 0.5f, -h * 0.5f, 0.0f);
    
            glBegin(GL_QUADS);
            {
                glTexCoord2f(0.0f, 0.0f);
                glVertex2f(0.0f, 0.0f);
    
                glTexCoord2f(1.0f, 0.0f);
                glVertex2f(w, 0.0f);
    
                glTexCoord2f(1.0f, 1.0f);
                glVertex2f(w, h);
    
                glTexCoord2f(0.0f, 1.0f);
                glVertex2f(0.0f, h);
            }
            glEnd();
    
            glPopMatrix();
    
            glfwSwapBuffers(window);
        }
    
        private void destroy() {
            if (debugProc != null) {
                debugProc.free();
            }
    
            glfwFreeCallbacks(window);
            glfwDestroyWindow(window);
            glfwTerminate();
            Objects.requireNonNull(glfwSetErrorCallback(null)).free();
        }
    
    }