Java使用Jogl

1. Jogl

opengl作为图形库,比较出名的库,大多是采用C++去调用相关的API接口,最近想是否可以在JVM中调用相应的OpenGL相应的Api库,在网上找了一圈,提供有相应的API库为jopl,但相应的的示例代码比较少。因此本文将实现简单的Demo,配合Java Swing使用。(ps:考虑到kotlin的语法简单些,本来采用kotlin来实现相应的调用)

2. 使用

2.1 引入相应库

在gradle中添加库文件

	implementation 'org.jogamp.jogl:jogl-all:2.3.2'
    implementation 'org.jogamp.gluegen:gluegen-rt-main:2.3.2'

由于jvm采用JNI的形式调用OpenGL的库文件,因此在其官网上面下载库文件 windows-amd64 ,并且 放入到项目本层目录下的native包中去。至此opengl的引入到jvm中完成。

2.2 结合swing使用

在Java 是使用opengl 仅需实现GLEventListener接口既是

package com.jwds.pointcloud.opengl

import com.jogamp.opengl.GLAutoDrawable
import com.jogamp.opengl.GLCapabilities
import com.jogamp.opengl.GLEventListener
import com.jogamp.opengl.awt.GLJPanel

class DemoPanel(private val glCapabilities: GLCapabilities): GLJPanel(glCapabilities), GLEventListener {
    override fun init(drawable: GLAutoDrawable) {
        TODO("Not yet implemented")
    }

    override fun dispose(drawable: GLAutoDrawable) {
        TODO("Not yet implemented")
    }

    override fun display(drawable: GLAutoDrawable) {
        TODO("Not yet implemented")
    }

    override fun reshape(drawable: GLAutoDrawable, x: Int, y: Int, width: Int, height: Int) {
        TODO("Not yet implemented")
    }
}

并且在主函数中调用此panel即可:

fun main(args: Array<String>) {

    val profile = GLProfile.get(GLProfile.GL2)
    val capabilities = GLCapabilities(profile)


    val b = DemoPanel(capabilities)

    //creating frame
    val frame = JFrame(" Basic Frame")
    frame.add(b)

    frame.size = Dimension(600,400)
    frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE

    frame.setLocationRelativeTo(null)
    frame.isVisible = true
}

2.3 实现绘画三角形

根据C++的示例,在DemoPanel实现相应的三角形绘画:

class DemoPanel(private val glCapabilities: GLCapabilities): GLJPanel(glCapabilities), GLEventListener {
    private val program = ShaderProgram()

    private var vbo = IntBuffer.allocate(1)
    private var vao = IntBuffer.allocate(1)
    
     init {
        addGLEventListener(this)
    }
    
    override fun init(drawable: GLAutoDrawable) {
        val gl = drawable.gl.gL2
        val code1 = """
            #version 330 core

            layout (location = 0) in vec3 position;

            void main()
            {
                gl_Position = vec4(position, 1.0);
            }
        """.trimIndent()

        val code2 = """
            #version 330 core

            out vec4 color;

            void main()
            {
                color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
            }
        """.trimIndent()


        program.add(gl, ShaderCode(GL2ES2.GL_VERTEX_SHADER, 1, arrayOf(arrayOf(code1))), System.out)
        program.add(gl, ShaderCode(GL2ES2.GL_FRAGMENT_SHADER, 1, arrayOf(arrayOf(code2))), System.out)

        program.link(gl, System.out)

        val arr = arrayOf(arrayOf(0.5f,0.5f,0.0f), arrayOf(0.5f,0f,0f), arrayOf(0f,0.5f,0f))

        val buff = FloatBuffer.allocate(arr.size * 3)
        
        arr.forEach { item -> buff.put(item.toFloatArray()) }

        gl.glGenVertexArrays(1,vao)
        gl.glGenBuffers(1,vbo)

        gl.glBindVertexArray(vao[0])

        buff.rewind()
        gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER,vbo[0])
        gl.glBufferData(GL2ES2.GL_ARRAY_BUFFER, (buff.capacity() * 4).toLong(),buff, GL2ES2.GL_STATIC_DRAW)
        gl.glVertexAttribPointer(0, 3, GL2ES2.GL_FLOAT, false, 12, 0)
        gl.glEnableVertexAttribArray(0)

        gl.glBindBuffer(GL2ES2.GL_ARRAY_BUFFER,0)
        gl.glBindVertexArray(0)
    }

    override fun dispose(drawable: GLAutoDrawable) {
    
    }

    override fun display(drawable: GLAutoDrawable) {
        val gl = drawable.gl.gL2
        gl.glClearColor(0.2f, 0.3f, 0.3f, 1.0f)
        gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT)

        gl.glEnableClientState(GLES2.GL_VERTEX_ARRAY)

        program.useProgram(gl, true)

        gl.glBindVertexArray(vao[0])
        gl.glDrawArrays(GL2ES2.GL_TRIANGLES,0,3)
        gl.glBindVertexArray(0)
        gl.glDisableClientState(GLES2.GL_VERTEX_ARRAY)
    }

    override fun reshape(drawable: GLAutoDrawable, x: Int, y: Int, width: Int, height: Int) {
     
    }
}

如上代码,其代码思路参考C++代码参考,在opengl初始化的时候初始化相应的VAO,VBO,以及着色器代码,并且按照相应的思路将数据填充到VBO中去,并且配置VAO的解析规则。值得注意的是在Java中必须调用buff.rewind()函数,使其数据缓存重置为原点处。否则后续填充数据没有效果。

后续在display函数中进行相关的展示数据,调用gl.glDrawArrays函数将VBO中的数据进行绘画到opengl中去,自此jvm中调用相关opengl API简单的Demo已经实现,其结果如下:
在这里插入图片描述

3. 结语

在java中调用与C++调用的主要思路都是一样的,主要要注意的是两种语言对内存的分配问题,以及相应指针引用的问题,在java中使用Buffers对象,必须让内存归于0才方便后续的处理,而C++一般来说就没有这样的问题,因为其指针指向的就是其引用的内存的首地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

myenjoy_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值