JAVA OpenGL开发 IDEA配置LWJGL

最近公司没什么手机项目,也不知道该做些什么就研究PC上的JAVA开发,刚开始是研究OpenCV的,发现一些OpenGL的滤镜用OpenCV处理的挺慢的,就开始研究OpenGL了,网上搜了一下发现大家比较推荐用LWJGL就试着学习学习。

先说LWJGL版本,我在Github上下载的是最新的LWJGL 3.2.3

IDEA版本是2020.2

开始在IDEA上添加jar包

File->Project Structure

点Libraries再点+号选java

添加需要的jar包

我是Android开发的,所以选择了在Android上比较熟悉的OpenGLES来练手,等熟悉一些了再试试其他jar包,对IDEA不太熟悉还不会其他配置方法,先这么用着

然后我根据官方Demo里的代码试着改成我在Android上经常用的几个OpenGLES工具类

首先是EGLUtils.java

import org.lwjgl.egl.EGL;
import org.lwjgl.egl.EGLCapabilities;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengles.GLES;
import org.lwjgl.opengles.GLESCapabilities;
import org.lwjgl.system.MemoryStack;

import java.lang.reflect.Field;
import java.nio.IntBuffer;

import static org.lwjgl.egl.EGL10.eglGetError;
import static org.lwjgl.egl.EGL10.eglInitialize;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFWNativeEGL.glfwGetEGLDisplay;
import static org.lwjgl.opengles.GLES20.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;

public class EGLUtils {
    private long window = NULL;
    public void initEGL(int width,int height,String title){
        GLFWErrorCallback.createPrint().set();
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize glfw");
        }

        glfwDefaultWindowHints();
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);

        // GLFW setup for EGL & OpenGL ES
        glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
        glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);

        int WIDTH  = 300;
        int HEIGHT = 300;
        if(width != 0 && width != WIDTH){
            WIDTH = width;
        }
        if(height != 0 && height != HEIGHT){
            HEIGHT = height;
        }

        String t = "";
        if(title != null){
            t = title;
        }

        window = glfwCreateWindow(WIDTH, HEIGHT, t, NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        glfwSetKeyCallback(window, (windowHnd, key, scancode, action, mods) -> {
            if (action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE) {
                glfwSetWindowShouldClose(windowHnd, true);
            }
        });

        // EGL capabilities
        long dpy = glfwGetEGLDisplay();
        EGLCapabilities egl;
        try (MemoryStack stack = stackPush()) {
            IntBuffer major = stack.mallocInt(1);
            IntBuffer minor = stack.mallocInt(1);
            if (!eglInitialize(dpy, major, minor)) {
                throw new IllegalStateException(String.format("Failed to initialize EGL [0x%X]", eglGetError()));
            }
            egl = EGL.createDisplayCapabilities(dpy, major.get(0), minor.get(0));
        }
        try {
            System.out.println("EGL Capabilities:");
            for (Field f : EGLCapabilities.class.getFields()) {
                if (f.getType() == boolean.class) {
                    if (f.get(egl).equals(Boolean.TRUE)) {
                        System.out.println("\t" + f.getName());
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        // OpenGL ES capabilities
        glfwMakeContextCurrent(window);
        GLESCapabilities gles = GLES.createCapabilities();

        try {
            System.out.println("OpenGL ES Capabilities:");
            for (Field f : GLESCapabilities.class.getFields()) {
                if (f.getType() == boolean.class) {
                    if (f.get(gles).equals(Boolean.TRUE)) {
                        System.out.println("\t" + f.getName());
                    }
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        System.out.println("GL_VENDOR: " + glGetString(GL_VENDOR));
        System.out.println("GL_VERSION: " + glGetString(GL_VERSION));
        System.out.println("GL_RENDERER: " + glGetString(GL_RENDERER));

        // Render with OpenGL ES
        glfwShowWindow(window);
    }
    public void setWindowSize(int width,int height){
        if(window == NULL){
            return;
        }
        glfwSetWindowSize(window,width,height);
    }
    public int getWindowWidth(){
        if(window == NULL){
            return 0;
        }
        int[] width = new int[1];
        int[] height = new int[1];
        glfwGetWindowSize(window,width,height);
        return width[0];
    }
    public int getWindowHeight(){
        if(window == NULL){
            return 0;
        }
        int[] width = new int[1];
        int[] height = new int[1];
        glfwGetWindowSize(window,width,height);
        return height[0];
    }
    public int[] getWindowSize(){
        if(window == NULL){
            return null;
        }
        int[] width = new int[1];
        int[] height = new int[1];
        glfwGetWindowSize(window,width,height);
        return new int[]{width[0],height[0]};
    }

    public void setWindowTitle(String title){
        if(window == NULL){
            return;
        }
        glfwSetWindowTitle(window,title);
    }
    public boolean isClose(){
        if(window == NULL){
            return true;
        }
        return glfwWindowShouldClose(window);
    }
    public void glPollEvents(){
        glfwPollEvents();
    }
    public void glWaitEvents(){
        glfwWaitEvents();
    }
    public void swap() {
        if(window == NULL){
            return;
        }
        glfwSwapBuffers(window);
    }
    public void release(){
        GLES.setCapabilities(null);
        glfwFreeCallbacks(window);
        glfwTerminate();
        window = NULL;
    }
}

然后是ShaderUtils.java

import org.lwjgl.opengles.GLES20;

public class ShaderUtils {
    public static void checkGlError(String label) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            System.out.println(label + ": glError " + error);
            throw new RuntimeException(label + ": glError " + error);
        }
    }

    public static int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (pixelShader == 0) {
            return 0;
        }
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            GLES20.glAttachShader(program, vertexShader);
            checkGlError("glAttachShader");
            GLES20.glAttachShader(program, pixelShader);
            checkGlError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                System.out.println( "Could not link program: ");
                System.out.println(GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }


    public static int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled);
            if (compiled[0] == 0) {
                System.out.println("Could not compile shader " + shaderType + ":");
                System.out.println(GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }
}

最后是GLRenderer.java

import org.lwjgl.BufferUtils;
import org.lwjgl.opengles.GLES20;

import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class GLRenderer {

    private int[] textures = new int[1];

    private int[] bos = new int[2];

    private int programId;
    private int aPositionHandle;
    private int aTextureCoordHandle;
    private int uTextureSamplerHandle;


    private int imageWidth,imageHeight;

    public void initShader(BufferedImage image){
        imageWidth = image.getWidth();
        imageHeight = image.getHeight();
        String vertexShader = "attribute vec4 aPosition;\n" +
                "attribute vec2 aTexCoord;\n" +
                "varying vec2 vTexCoord;\n" +
                "void main() {\n" +
                "  vTexCoord = aTexCoord;\n" +
                "  gl_Position = aPosition;\n" +
                "}";
        String fragmentShader = "varying highp vec2 vTexCoord;\n" +
                "uniform highp sampler2D uTexture;\n" +
                "void main() {\n" +
                "    highp vec4 color = texture2D(uTexture, vec2(vTexCoord.x,1.0-vTexCoord.y));\n" +
                "    gl_FragColor = color;\n" +
                "}";
        programId = ShaderUtils.createProgram(vertexShader, fragmentShader);
        aPositionHandle = GLES20.glGetAttribLocation(programId, "aPosition");
        aTextureCoordHandle = GLES20.glGetAttribLocation(programId, "aTexCoord");
        uTextureSamplerHandle = GLES20.glGetUniformLocation(programId, "uTexture");

        final float[] vertexData = {
                1f, -1f, 0f,
                -1f, -1f, 0f,
                1f, 1f, 0f,
                -1f, 1f, 0f
        };


        final float[] textureVertexData = {
                1f, 0f,
                0f, 0f,
                1f, 1f,
                0f, 1f
        };
        FloatBuffer vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(vertexData);
        vertexBuffer.position(0);

        FloatBuffer textureVertexBuffer = ByteBuffer.allocateDirect(textureVertexData.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(textureVertexData);
        textureVertexBuffer.position(0);

        GLES20.glGenBuffers(bos);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bos[0]);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBuffer, GLES20.GL_STATIC_DRAW);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bos[1]);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,  textureVertexBuffer, GLES20.GL_STATIC_DRAW);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);



        GLES20.glGenTextures(textures);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, imageWidth, imageHeight,0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, imageToBuffer(image));
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

    private void viewportSize(int screenWidth,int screenHeight,int width,int height) {
        int left, top, viewWidth, viewHeight;
        float sh = screenWidth * 1.0f / screenHeight;
        float vh = width * 1.0f / height;
        if (sh < vh) {
            left = 0;
            viewWidth = screenWidth;
            viewHeight = (int) (height * 1.0f / width * viewWidth);
            top = (screenHeight - viewHeight) / 2;
        } else {
            top = 0;
            viewHeight = screenHeight;
            viewWidth = (int) (width * 1.0f / height * viewHeight);
            left = (screenWidth - viewWidth) / 2;
        }
        GLES20.glViewport(left, top, viewWidth, viewHeight);
    }

    public void drawFrame(int screenWidth,int screenHeight){
        viewportSize(screenWidth,screenHeight,imageWidth,imageHeight);
        GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);

        GLES20.glUseProgram(programId);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
        GLES20.glUniform1i(uTextureSamplerHandle, 0);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bos[0]);
        GLES20.glEnableVertexAttribArray(aPositionHandle);
        GLES20.glVertexAttribPointer(aPositionHandle, 3, GLES20.GL_FLOAT, false,
                0, 0);
        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bos[1]);
        GLES20.glEnableVertexAttribArray(aTextureCoordHandle);
        GLES20.glVertexAttribPointer(aTextureCoordHandle, 2, GLES20.GL_FLOAT, false, 0, 0);


        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        GLES20.glUseProgram(0);
    }

    public static ByteBuffer imageToBuffer(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        int[] pixels = new int[width * height];
        image.getRGB(0, 0, width, height, pixels, 0, width);
        ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * 4);
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int pixel = pixels[y * width + x];
                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();
        return buffer;
    }
}

代码和Android上很像,在main里运行一下

public static void main(String[] args) {
	// write your code here
        new Thread(){
            @Override
            public void run() {
                super.run();
                EGLUtils eglUtils = new EGLUtils();
                GLRenderer renderer = new GLRenderer();
                eglUtils.initEGL(500,500,"test");
                BufferedImage image = null;
                try {
                    image = ImageIO.read(new File("X:\\test\\ic_car.jpg"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if(image != null){
                    renderer.initShader(image);
                    while (!eglUtils.isClose()){
                        eglUtils.glPollEvents();
                        int[] size = eglUtils.getWindowSize();
                        renderer.drawFrame(size[0],size[1]);
                        eglUtils.swap();
                    }
                }
                eglUtils.release();
            }
        }.start();
    }

效果

由于还不会用IDEA上传代码到Github上就把代码都贴上了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值