最好的OpenGL Java绑定是什么?

时间:2020-03-05 18:54:23  来源:igfitidea点击:

我正在尝试为我的Java SWT应用程序实现更好的性能,但我发现可以在SWT中使用OpenGL。似乎有不止一种针对OpenGL的Java绑定。你更倾向哪个?

请注意,我以前从未使用过OpenGL,并且该应用程序需要在Windows,Linux和Mac OS X上运行。

解决方案

回答

就个人而言,除了JOGL之外,我什至不了解OpenGL的Java绑定-我认为JOGL几乎是Java OpenGL的标准。

它可以在Windows,Linux和OS X上运行,但是我们可能需要阅读官方文档,以获取有关每个平台中特定问题的一些说明。

请记住,OpenGL范例与Swing / AWT或者Java 2D API完全不同。 OpenGL不能替代Swing。

回答

约格

我的理由可以从以前链接的网站上引用:

JOGL provides full access to the APIs in the OpenGL 2.0 specification as well as nearly all vendor extensions, and integrates with the AWT and Swing widget sets.

此外,如果我们想获得一些有趣的学习和知识,处理是一种很好的开始方法(处理还使用JOGL btw ...)

回答

我建议我们查看LWJGL,LightWeight Java游戏库。它具有OpenGL绑定,但也具有OpenAL绑定和一些不错的教程来入门。

请记住,Swing / SWT和OpenGL通常用于完全不同的事物。我们可能最终想要同时使用两者。只需尝试一下LWJGL,看看它与我们正在做的事情相适应的程度。

回答

JOGL可能是唯一值得考虑的选择。
请注意,至少有两个选项可以将其集成到SWT应用程序中。有一个属于SWT的GLCanvas和一个属于AWT的GLCanvas。
SWT中的那个功能不完整,并且没有真正维护。最好在SWT_AWT容器中使用AWT GLCanvas。
来自最近项目的一些代码:

import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

import javax.media.opengl.*;
import javax.media.opengl.glu.*;

import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.events.*;

public class Main implements GLEventListener
{
    public static void main(String[] args) 
    {
        Display display = new Display();
    Main main = new Main();
    main.runMain(display);
    display.dispose();
}

void runMain(Display display)
{
    final Shell shell = new Shell(display);
    shell.setText("Q*bert 3D - OpenGL Exercise");
    GridLayout gridLayout = new GridLayout();
    gridLayout.marginHeight = 0;
    gridLayout.marginWidth = 0;

    shell.setLayout(gridLayout);

    // this allows us to set particular properties for the GLCanvas
    GLCapabilities glCapabilities = new GLCapabilities();

    glCapabilities.setDoubleBuffered(true);
    glCapabilities.setHardwareAccelerated(true);

    // instantiate the canvas
    final GLCanvas canvas = new GLCanvas(glCapabilities);

    // we can't use the default Composite because using the AWT bridge
    // requires that it have the property of SWT.EMBEDDED
    Composite composite = new Composite(shell, SWT.EMBEDDED);
    GridData ld = new GridData(GridData.FILL_BOTH);
    composite.setLayoutData(ld);

    // set the internal layout so our canvas fills the whole control
    FillLayout clayout = new FillLayout();
    composite.setLayout(clayout);

    // create the special frame bridge to AWT
    java.awt.Frame glFrame = SWT_AWT.new_Frame(composite);
    // we need the listener so we get the GL events
    canvas.addGLEventListener(this);

    // finally, add our canvas as a child of the frame
    glFrame.add(canvas);

    // show it all
    shell.open();
    // the event loop.
    while (!shell.isDisposed ()) {
        if (!display.readAndDispatch ()) display.sleep ();
    }
}

回答

JOGL将为我们提供最佳的性能和可移植性。但是请注意,学习JOGL(与学习OpenGL基本相同)并不容易。

回答

使用JOGL,我们的工作很顺利。新的2.0版本位于http://jogamp.org/(最后的"旧"版本位于http://download.java.net/media/jogl/builds/archive/jsr-231-1.1.1a/) 。

对于专门用于SWT的JOGL 2,我从http://wadeawalker.wordpress.com/2010/10/09/tutorial-a-cross-platform-workbench-program-using-java-opengl开始了一系列教程-and-eclipse /精确演示了如何制作跨平台的JOGL SWT应用程序,以及可安装的本机二进制文件。

或者,如果我们不想使用Eclipse RCP,那么这里有一个更简单的示例,它仅使用JOGL 2和SWT绘制了一个三角形。要构建它,请将其放入带有swt.jar(来自http://www.eclipse.org/swt/)和最新的JOGL autobuild .jar和.dll文件(来自http://jogamp.org/)的项目中。这个简单示例的唯一问题是,如果没有一些额外的帮助,它将不会跨平台-我们需要Eclipse RCP能够将多组平台库捆绑到一个项目中。

package name.wadewalker.onetriangle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

import javax.media.opengl.GL;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GL2;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.glu.GLU;

public class OneTriangle {

    public static void main(String [] args) {
        GLProfile.initSingleton( true );

        GLProfile glprofile = GLProfile.get( GLProfile.GL2 );

        Display display = new Display();
        Shell shell = new Shell( display );
        shell.setLayout( new FillLayout() );
        Composite composite = new Composite( shell, SWT.NONE );
        composite.setLayout( new FillLayout() );

        GLData gldata = new GLData();
        gldata.doubleBuffer = true;
        // need SWT.NO_BACKGROUND to prevent SWT from clearing the window
        // at the wrong times (we use glClear for this instead)
        final GLCanvas glcanvas = new GLCanvas( composite, SWT.NO_BACKGROUND, gldata );
        glcanvas.setCurrent();
        final GLContext glcontext = GLDrawableFactory.getFactory( glprofile ).createExternalGLContext();

        // fix the viewport when the user resizes the window
        glcanvas.addListener( SWT.Resize, new Listener() {
            public void handleEvent(Event event) {
                setup( glcanvas, glcontext );
            }
        });

        // draw the triangle when the OS tells us that any part of the window needs drawing
        glcanvas.addPaintListener( new PaintListener() {
            public void paintControl( PaintEvent paintevent ) {
                render( glcanvas, glcontext );
            }
        });

        shell.setText( "OneTriangle" );
        shell.setSize( 640, 480 );
        shell.open();

        while( !shell.isDisposed() ) {
            if( !display.readAndDispatch() )
                display.sleep();
        }

        glcanvas.dispose();
        display.dispose();
    }

    private static void setup( GLCanvas glcanvas, GLContext glcontext ) {
        Rectangle rectangle = glcanvas.getClientArea();

        glcanvas.setCurrent();
        glcontext.makeCurrent();

        GL2 gl = glcontext.getGL().getGL2();
        gl.glMatrixMode( GL2.GL_PROJECTION );
        gl.glLoadIdentity();

        // coordinate system origin at lower left with width and height same as the window
        GLU glu = new GLU();
        glu.gluOrtho2D( 0.0f, rectangle.width, 0.0f, rectangle.height );

        gl.glMatrixMode( GL2.GL_MODELVIEW );
        gl.glLoadIdentity();

        gl.glViewport( 0, 0, rectangle.width, rectangle.height );
        glcontext.release();        
    }

    private static void render( GLCanvas glcanvas, GLContext glcontext ) {
        Rectangle rectangle = glcanvas.getClientArea();

        glcanvas.setCurrent();
        glcontext.makeCurrent();

        GL2 gl = glcontext.getGL().getGL2();
        gl.glClear( GL.GL_COLOR_BUFFER_BIT );

        // draw a triangle filling the window
        gl.glLoadIdentity();
        gl.glBegin( GL.GL_TRIANGLES );
        gl.glColor3f( 1, 0, 0 );
        gl.glVertex2f( 0, 0 );
        gl.glColor3f( 0, 1, 0 );
        gl.glVertex2f( rectangle.width, 0 );
        gl.glColor3f( 0, 0, 1 );
        gl.glVertex2f( rectangle.width / 2, rectangle.height );
        gl.glEnd();

        glcanvas.swapBuffers();
        glcontext.release();        
    }
}