3D C/C++ tutorials - Projects - Java OpenGL Native Interface
3D C/C++ tutorials -> Projects -> Java OpenGL Native Interface
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
To compile and run these tutorials some or all of these libraries are required: FreeImage 3.16.0, GLEW 1.11.0, GLUT 3.7.6 / GLUT for Dev-C++, GLM 0.9.5.4
Java OpenGL Native Interface
Warning
This is an experimental project. It's purpose is to make it easier to rewrite our C/C++ OpenGL tutorials to Java. Our native DLL doesn't provide all OpenGL functions and it works only with 32-bit Java on Windows.
Download and install

We downloaded and installed

  • jdk-8u25-windows-i586.exe
  • jdk-8u25-windows-x64.exe
  • netbeans-8.0.2-javase-windows.exe
NetBeans
On 64-bit Windows you must set the NetBeans default JDK the 32-bit one, because our native DLL is 32-bit.

You can change the NetBeans default JDK in the C:\Program Files\NetBeans 8.0.2\etc\netbeans.conf file.

netbeans_jdkhome="C:\Program Files (x86)\Java\jdk1.8.0_25"
Visual Studio
In Tools -> Options -> Projects and Solutions -> VC++ Directories

add

C:\Program Files (x86)\Java\jdk1.8.0_25\include
C:\Program Files (x86)\Java\jdk1.8.0_25\include\win32

to the Directories for Include files

and

C:\Program Files (x86)\Java\jdk1.8.0_25\lib

to the Directories for Library files.
Native Win32 DLL
The joglni.dll is built in Visual Studio and requires GLEW.

After you build your own joglni.dll (in Visual Studio), you must copy it (from the \native-source-vs2008\joglni\Release directory) to the root directory of your Java application's NetBeans project (\java-application-example-netbeans\FirstJOGLNIApplication).
Java class library
If you add or change any native functions in the joglni.dll, don't forget to change and build the joglni.jar (in NetBeans) appropriately.

After you build your own joglni.jar, you must copy it (from the \java-class-library-netbeans\joglni\dist directory) to the lib directory of your Java application's NetBeans project (\java-application-example-netbeans\FirstJOGLNIApplication\lib).
First JOGLNI application
If you change the joglni.jar, don't forget to rebuild your Java application (\java-application-example-netbeans\FirstJOGLNIApplication) in NetBeans.
joglni.h
// ----------------------------------------------------------------------------------------------------------------------------

#include <jni.h>

// ----------------------------------------------------------------------------------------------------------------------------

#ifndef __joglni_h__
#define __joglni_h__
#define __JOGLNI_H__
#ifdef __cplusplus
extern "C" {
#endif

// OpenGL 1.1 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBegin(JNIEnv *env, jobject obj, jint mode);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindTexture(JNIEnv *env, jobject obj, jint target, jint texture);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glBlendFunc(JNIEnv *env, jobject obj, jint sfactor, jint dfactor);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glClear(JNIEnv *env, jobject obj, jint mask);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glColor3f(JNIEnv *env, jobject obj, jfloat red, jfloat green, jfloat blue);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glColor4f(JNIEnv *env, jobject obj, jfloat red, jfloat green, jfloat blue, jfloat alpha);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glColorPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glCullFace(JNIEnv *env, jobject obj, jint mode);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteTextures(JNIEnv *env, jobject obj, jint n, jintArray textures);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDisable(JNIEnv *env, jobject obj, jint cap);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDisableClientState(JNIEnv *env, jobject obj, jint cap);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawArrays(JNIEnv *env, jobject obj, jint mode, jint first, jint count);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawBuffer(JNIEnv *env, jobject obj, jint mode);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawElements(JNIEnv *env, jobject obj, jint mode, jint count, jint type, jbyteArray indices);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnable(JNIEnv *env, jobject obj, jint cap);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnableClientState(JNIEnv *env, jobject obj, jint cap);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnd(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenTextures(JNIEnv *env, jobject obj, jint n, jintArray textures);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glGetIntegerv(JNIEnv *env, jobject obj, jint pname, jintArray params);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glLineWidth(JNIEnv *env, jobject obj, jfloat width);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glLoadIdentity(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glLoadMatrixf(JNIEnv *env, jobject obj, jfloatArray m);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMatrixMode(JNIEnv *env, jobject obj, jint mode);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultMatrixf(JNIEnv *env, jobject obj, jfloatArray m);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glNormal3f(JNIEnv *env, jobject obj, jfloat nx, jfloat ny, jfloat nz);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glNormalPointer(JNIEnv *env, jobject obj, jint type, jint stride, jbyteArray ptr, jint offset);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glReadBuffer(JNIEnv *env, jobject obj, jint mode);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glRotatef(JNIEnv *env, jobject obj, jfloat angle, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glScalef(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoord2f(JNIEnv *env, jobject obj, jfloat s, jfloat t);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoord3f(JNIEnv *env, jobject obj, jfloat s, jfloat t, jfloat r);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoordPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexImage2D(JNIEnv *env, jobject obj, jint target, jint level, jint internalFormat, jint width, jint height, jint border, jint format, jint type, jbyteArray pixels);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexParameteri(JNIEnv *env, jobject obj, jint target, jint pname, jint param);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTranslatef(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertex2f(JNIEnv *env, jobject obj, jfloat x, jfloat y);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertex3f(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertexPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glViewport(JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height);

// OpenGL 1.2 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexImage3D(JNIEnv *env, jobject obj, jint target, jint level, jint internalFormat, jint width, jint height, jint depth, jint border, jint format, jint type, jbyteArray pixels);

// OpenGL 1.3 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glActiveTexture(JNIEnv *env, jobject obj, jint texture);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultiTexCoord2f(JNIEnv *env, jobject obj, jint target, jfloat s, jfloat t);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultiTexCoord3f(JNIEnv *env, jobject obj, jint target, jfloat s, jfloat t, jfloat r);

// OpenGL 1.5 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindBuffer(JNIEnv *env, jobject obj, jint target, jint buffer);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glBufferData(JNIEnv *env, jobject obj, jint target, jint size, jbyteArray data, jint usage);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteBuffers(JNIEnv *env, jobject obj, jint n, jintArray buffers);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenBuffers(JNIEnv *env, jobject obj, jint n, jintArray buffers);

// GL_ARB_texture_float -------------------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1ARB_1texture_1float(JNIEnv *env, jobject obj);

// GL_ARB_texture_non_power_of_two --------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1ARB_1texture_1non_1power_1of_1two(JNIEnv *env, jobject obj);

// GL_EXT_framebuffer_object --------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindFramebufferEXT(JNIEnv *env, jobject obj, jint target, jint framebuffer);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteFramebuffersEXT(JNIEnv *env, jobject obj, jint n, jintArray framebuffers);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glFramebufferTexture2DEXT(JNIEnv *env, jobject obj, jint target, jint attachment, jint textarget, jint texture, jint level);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenFramebuffersEXT(JNIEnv *env, jobject obj, jint n, jintArray framebuffers);
JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenerateMipmapEXT(JNIEnv *env, jobject obj, jint target);

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1framebuffer_1object(JNIEnv *env, jobject obj);

// GL_EXT_texture_array -------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glFramebufferTextureLayerEXT(JNIEnv *env, jobject obj, jint target, jint attachment, jint texture, jint level, jint layer);

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1texture_1array(JNIEnv *env, jobject obj);

// GL_EXT_texture_filter_anisotropic ------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1texture_1filter_1anisotropic(JNIEnv *env, jobject obj);

// GLU ------------------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_gluPerspective(JNIEnv *env, jobject obj, jdouble fovy, jdouble aspect, jdouble zNear, jdouble zFar);
JNIEXPORT void JNICALL Java_joglni_OpenGL_gluLookAt(JNIEnv *env, jobject obj, jdouble eyeX, jdouble eyeY, jdouble eyeZ, jdouble centerX, jdouble centerY, jdouble centerZ, jdouble upX, jdouble upY, jdouble upZ);

// OpenGLRenderer -------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGLRenderer_addError(JNIEnv *env, jobject obj, jstring error);

// OpenGLView -----------------------------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGLView_create21(JNIEnv *env, jobject obj, jstring title, jint width, jint height, jint samples);
JNIEXPORT void JNICALL Java_joglni_OpenGLView_destroy(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_joglni_OpenGLView_displayMessage(JNIEnv *env, jobject obj, jstring title, jstring message);
JNIEXPORT jstring JNICALL Java_joglni_OpenGLView_getErrorLog(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_joglni_OpenGLView_mainLoop(JNIEnv *env, jobject obj);
JNIEXPORT void JNICALL Java_joglni_OpenGLView_show(JNIEnv *env, jobject obj, jboolean maximized);

// ----------------------------------------------------------------------------------------------------------------------------

#ifdef __cplusplus
}
#endif
#endif

// ----------------------------------------------------------------------------------------------------------------------------
joglni.cpp
// ----------------------------------------------------------------------------------------------------------------------------

#include <windows.h>

#include <gl/glew.h>
#include <gl/wglew.h>

#include "string.h"

#include "joglni.h"

// ----------------------------------------------------------------------------------------------------------------------------

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")

// ----------------------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBegin(JNIEnv *env, jobject obj, jint mode) { glBegin(mode); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindTexture(JNIEnv *env, jobject obj, jint target, jint texture) { glBindTexture(target, texture); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glBlendFunc(JNIEnv *env, jobject obj, jint sfactor, jint dfactor) { glBlendFunc(sfactor, dfactor); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glClear(JNIEnv *env, jobject obj, jint mask) { glClear(mask); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glColor3f(JNIEnv *env, jobject obj, jfloat red, jfloat green, jfloat blue) { glColor3f(red, green, blue); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glColor4f(JNIEnv *env, jobject obj, jfloat red, jfloat green, jfloat blue, jfloat alpha) { glColor4f(red, green, blue, alpha); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glColorPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset)
{
    if(ptr == NULL)
    {
        glColorPointer(size, type, stride, (void*)offset);
    }
    else
    {
        jbyte *Ptr = env->GetByteArrayElements(ptr, NULL);
        glColorPointer(size, type, stride, Ptr + offset);
        env->ReleaseByteArrayElements(ptr, Ptr, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glCullFace(JNIEnv *env, jobject obj, jint mode) { glCullFace(mode); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteTextures(JNIEnv *env, jobject obj, jint n, jintArray textures)
{
    if(textures != NULL)
    {
        jint *Textures = env->GetIntArrayElements(textures, NULL);
        glDeleteTextures(n, (const GLuint*)Textures);
        env->ReleaseIntArrayElements(textures, Textures, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glDisable(JNIEnv *env, jobject obj, jint cap) { glDisable(cap); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDisableClientState(JNIEnv *env, jobject obj, jint cap) { glDisableClientState(cap); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawArrays(JNIEnv *env, jobject obj, jint mode, jint first, jint count) { glDrawArrays(mode, first, count); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawBuffer(JNIEnv *env, jobject obj, jint mode) { glDrawBuffer(mode); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glDrawElements(JNIEnv *env, jobject obj, jint mode, jint count, jint type, jbyteArray indices)
{
    if(indices == NULL)
    {
        glDrawElements(mode, count, type, NULL);
    }
    else
    {
        jbyte *Indices = env->GetByteArrayElements(indices, NULL);
        glDrawElements(mode, count, type, Indices);
        env->ReleaseByteArrayElements(indices, Indices, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnable(JNIEnv *env, jobject obj, jint cap) { glEnable(cap); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnableClientState(JNIEnv *env, jobject obj, jint cap) { glEnableClientState(cap); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glEnd(JNIEnv *env, jobject obj) { glEnd(); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenTextures(JNIEnv *env, jobject obj, jint n, jintArray textures)
{
    if(textures != NULL)
    {
        jint *Textures = env->GetIntArrayElements(textures, NULL);
        glGenTextures(n, (GLuint*)Textures);
        env->ReleaseIntArrayElements(textures, Textures, 0);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glGetIntegerv(JNIEnv *env, jobject obj, jint pname, jintArray params)
{
    if(params != NULL)
    {
        jint *Params = env->GetIntArrayElements(params, NULL);
        glGetIntegerv(pname, (GLint*)Params);
        env->ReleaseIntArrayElements(params, Params, 0);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glLineWidth(JNIEnv *env, jobject obj, jfloat width) { glLineWidth(width); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glLoadIdentity(JNIEnv *env, jobject obj) { glLoadIdentity(); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glLoadMatrixf(JNIEnv *env, jobject obj, jfloatArray m)
{
    if(m != NULL)
    {
        jfloat *M = env->GetFloatArrayElements(m, NULL);
        glLoadMatrixf(M);
        env->ReleaseFloatArrayElements(m, M, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glMatrixMode(JNIEnv *env, jobject obj, jint mode) { glMatrixMode(mode); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultMatrixf(JNIEnv *env, jobject obj, jfloatArray m)
{
    if(m != NULL)
    {
        jfloat *M = env->GetFloatArrayElements(m, NULL);
        glMultMatrixf(M);
        env->ReleaseFloatArrayElements(m, M, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glNormal3f(JNIEnv *env, jobject obj, jfloat nx, jfloat ny, jfloat nz) { glNormal3f(nx, ny, nz); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glNormalPointer(JNIEnv *env, jobject obj, jint type, jint stride, jbyteArray ptr, jint offset)
{
    if(ptr == NULL)
    {
        glNormalPointer(type, stride, (void*)offset);
    }
    else
    {
        jbyte *Ptr = env->GetByteArrayElements(ptr, NULL);
        glNormalPointer(type, stride, Ptr + offset);
        env->ReleaseByteArrayElements(ptr, Ptr, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glReadBuffer(JNIEnv *env, jobject obj, jint mode) { glReadBuffer(mode); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glRotatef(JNIEnv *env, jobject obj, jfloat angle, jfloat x, jfloat y, jfloat z) { glRotatef(angle, x, y, z); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glScalef(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) { glScalef(x, y, z); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoord2f(JNIEnv *env, jobject obj, jfloat s, jfloat t) { glTexCoord2f(s, t); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoord3f(JNIEnv *env, jobject obj, jfloat s, jfloat t, jfloat r) { glTexCoord3f(s, t, r); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexCoordPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset)
{
    if(ptr == NULL)
    {
        glTexCoordPointer(size, type, stride, (void*)offset);
    }
    else
    {
        jbyte *Ptr = env->GetByteArrayElements(ptr, NULL);
        glTexCoordPointer(size, type, stride, Ptr + offset);
        env->ReleaseByteArrayElements(ptr, Ptr, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexImage2D(JNIEnv *env, jobject obj, jint target, jint level, jint internalFormat, jint width, jint height, jint border, jint format, jint type, jbyteArray pixels)
{
    if(pixels == NULL)
    {
        glTexImage2D(target, level, internalFormat, width, height, border, format, type, NULL);
    }
    else
    {
        jbyte *Pixels = env->GetByteArrayElements(pixels, NULL);
        glTexImage2D(target, level, internalFormat, width, height, border, format, type, Pixels);
        env->ReleaseByteArrayElements(pixels, Pixels, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexParameteri(JNIEnv *env, jobject obj, jint target, jint pname, jint param) { glTexParameteri(target, pname, param); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glTranslatef(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) { glTranslatef(x, y, z); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertex2f(JNIEnv *env, jobject obj, jfloat x, jfloat y) { glVertex2f(x, y); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertex3f(JNIEnv *env, jobject obj, jfloat x, jfloat y, jfloat z) { glVertex3f(x, y, z); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glVertexPointer(JNIEnv *env, jobject obj, jint size, jint type, jint stride, jbyteArray ptr, jint offset)
{
    if(ptr == NULL)
    {
        glVertexPointer(size, type, stride, (void*)offset);
    }
    else
    {
        jbyte *Ptr = env->GetByteArrayElements(ptr, NULL);
        glVertexPointer(size, type, stride, Ptr + offset);
        env->ReleaseByteArrayElements(ptr, Ptr, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glViewport(JNIEnv *env, jobject obj, jint x, jint y, jint width, jint height) { glViewport(x, y, width, height); }

// OpenGL 1.2 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glTexImage3D(JNIEnv *env, jobject obj, jint target, jint level, jint internalFormat, jint width, jint height, jint depth, jint border, jint format, jint type, jbyteArray pixels)
{
    if(pixels == NULL)
    {
        glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, NULL);
    }
    else
    {
        jbyte *Pixels = env->GetByteArrayElements(pixels, NULL);
        glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, Pixels);
        env->ReleaseByteArrayElements(pixels, Pixels, JNI_ABORT);
    }
}

// OpenGL 1.3 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glActiveTexture(JNIEnv *env, jobject obj, jint texture) { glActiveTexture(texture); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultiTexCoord2f(JNIEnv *env, jobject obj, jint target, jfloat s, jfloat t) { glMultiTexCoord2f(target, s, t); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_glMultiTexCoord3f(JNIEnv *env, jobject obj, jint target, jfloat s, jfloat t, jfloat r) { glMultiTexCoord3f(target, s, t, r); }

// OpenGL 1.5 -----------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindBuffer(JNIEnv *env, jobject obj, jint target, jint buffer) { glBindBuffer(target, buffer); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBufferData(JNIEnv *env, jobject obj, jint target, jint size, jbyteArray data, jint usage)
{
    if(data != NULL)
    {
        jbyte *Data = env->GetByteArrayElements(data, NULL);
        glBufferData(target, size, Data, usage);
        env->ReleaseByteArrayElements(data, Data, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteBuffers(JNIEnv *env, jobject obj, jint n, jintArray buffers)
{
    if(buffers != NULL)
    {
        jint *Buffers = env->GetIntArrayElements(buffers, NULL);
        glDeleteBuffers(n, (const GLuint*)Buffers);
        env->ReleaseIntArrayElements(buffers, Buffers, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenBuffers(JNIEnv *env, jobject obj, jint n, jintArray buffers)
{
    if(buffers != NULL)
    {
        jint *Buffers = env->GetIntArrayElements(buffers, NULL);
        glGenBuffers(n, (GLuint*)Buffers);
        env->ReleaseIntArrayElements(buffers, Buffers, 0);
    }
}

// GL_ARB_texture_float -------------------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1ARB_1texture_1float(JNIEnv *env, jobject obj) { return GLEW_ARB_texture_float; }

// GL_ARB_texture_non_power_of_two --------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1ARB_1texture_1non_1power_1of_1two(JNIEnv *env, jobject obj) { return GLEW_ARB_texture_non_power_of_two; }

// GL_EXT_framebuffer_object --------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glBindFramebufferEXT(JNIEnv *env, jobject obj, jint target, jint framebuffer) { glBindFramebufferEXT(target, framebuffer); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glDeleteFramebuffersEXT(JNIEnv *env, jobject obj, jint n, jintArray framebuffers)
{
    if(framebuffers != NULL)
    {
        jint *Framebuffers = env->GetIntArrayElements(framebuffers, NULL);
        glDeleteFramebuffersEXT(n, (const GLuint*)Framebuffers);
        env->ReleaseIntArrayElements(framebuffers, Framebuffers, JNI_ABORT);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glFramebufferTexture2DEXT(JNIEnv *env, jobject obj, jint target, jint attachment, jint textarget, jint texture, jint level) { glFramebufferTexture2DEXT(target, attachment, textarget, texture, level); }

JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenFramebuffersEXT(JNIEnv *env, jobject obj, jint n, jintArray framebuffers)
{
    if(framebuffers != NULL)
    {
        jint *Framebuffers = env->GetIntArrayElements(framebuffers, NULL);
        glGenFramebuffersEXT(n, (GLuint*)Framebuffers);
        env->ReleaseIntArrayElements(framebuffers, Framebuffers, 0);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGL_glGenerateMipmapEXT(JNIEnv *env, jobject obj, jint target) { glGenerateMipmapEXT(target); }

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1framebuffer_1object(JNIEnv *env, jobject obj) { return GLEW_EXT_framebuffer_object; }

// GL_EXT_texture_array -------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_glFramebufferTextureLayerEXT(JNIEnv *env, jobject obj, jint target, jint attachment, jint texture, jint level, jint layer) { glFramebufferTextureLayerEXT(target, attachment, texture, level, layer); }

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1texture_1array(JNIEnv *env, jobject obj) { return GLEW_EXT_texture_array; }

// GL_EXT_texture_filter_anisotropic ------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGL_GL_1EXT_1texture_1filter_1anisotropic(JNIEnv *env, jobject obj) { return GLEW_EXT_texture_filter_anisotropic; }

// GLU ------------------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGL_gluPerspective(JNIEnv *env, jobject obj, jdouble fovy, jdouble aspect, jdouble zNear, jdouble zFar) { gluPerspective(fovy, aspect, zNear, zFar); }
JNIEXPORT void JNICALL Java_joglni_OpenGL_gluLookAt(JNIEnv *env, jobject obj, jdouble eyeX, jdouble eyeY, jdouble eyeZ, jdouble centerX, jdouble centerY, jdouble centerZ, jdouble upX, jdouble upY, jdouble upZ) { gluLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); }

// ----------------------------------------------------------------------------------------------------------------------------

CString ErrorLog;

// OpenGLRenderer -------------------------------------------------------------------------------------------------------------

JNIEXPORT void JNICALL Java_joglni_OpenGLRenderer_addError(JNIEnv *env, jobject obj, jstring error)
{
    const char *Error = env->GetStringUTFChars(error, NULL);

    ErrorLog.Append(Error);
    ErrorLog.Append("\r\n");

    env->ReleaseStringUTFChars(error, Error);
}

// ----------------------------------------------------------------------------------------------------------------------------

HWND Wnd = NULL;
CString Title;
int Width = 0, Height = 0, Samples = 0;
HGLRC GLRC = NULL;

// ----------------------------------------------------------------------------------------------------------------------------

int gl_max_texture_max_anisotropy_ext = 0;

// ----------------------------------------------------------------------------------------------------------------------------

JNIEnv *Env = NULL;

jobject OpenGLViewJObject = NULL;

jmethodID OnPaintJMethodId = NULL;
jmethodID OnSizeJMethodId = NULL;

// ----------------------------------------------------------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam);

// OpenGLView -----------------------------------------------------------------------------------------------------------------

JNIEXPORT jboolean JNICALL Java_joglni_OpenGLView_create21(JNIEnv *env, jobject obj, jstring title, jint width, jint height, jint samples)
{
    const char *Title = env->GetStringUTFChars(title, NULL);

    ::Title.Set(Title);

    env->ReleaseStringUTFChars(title, Title);

    Width = width;
    Height = height;

    HINSTANCE hInstance = NULL;

    WNDCLASSEX WndClassEx;

    memset(&WndClassEx, 0, sizeof(WNDCLASSEX));

    WndClassEx.cbSize = sizeof(WNDCLASSEX);
    WndClassEx.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    WndClassEx.lpfnWndProc = WndProc;
    WndClassEx.hInstance = hInstance;
    WndClassEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    WndClassEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    WndClassEx.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClassEx.lpszClassName = "Win32OpenGL21NativeWindowClass";

    if(RegisterClassEx(&WndClassEx) == 0)
    {
        ErrorLog.Set("RegisterClassEx failed!");
        return false;
    }

    DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

    Wnd = CreateWindowEx(WS_EX_APPWINDOW, WndClassEx.lpszClassName, ::Title, Style, 0, 0, Width, Height, NULL, NULL, hInstance, NULL);

    if(Wnd == NULL)
    {
        ErrorLog.Set("CreateWindowEx failed!");
        return false;
    }

    HDC DC = GetDC(Wnd);

    if(DC == NULL)
    {
        ErrorLog.Set("GetDC failed!");
        return false;
    }

    PIXELFORMATDESCRIPTOR pfd;

    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int PixelFormat = ChoosePixelFormat(DC, &pfd);

    if(PixelFormat == 0)
    {
        ErrorLog.Set("ChoosePixelFormat failed!");
        return false;
    }

    static int MSAAPixelFormat = 0;

    if(SetPixelFormat(DC, MSAAPixelFormat == 0 ? PixelFormat : MSAAPixelFormat, &pfd) == FALSE)
    {
        ErrorLog.Set("SetPixelFormat failed!");
        return false;
    }

    GLRC = wglCreateContext(DC);

    if(GLRC == NULL)
    {
        ErrorLog.Set("wglCreateContext failed!");
        return false;
    }

    if(wglMakeCurrent(DC, GLRC) == FALSE)
    {
        ErrorLog.Set("wglMakeCurrent failed!");
        return false;
    }

    if(glewInit() != GLEW_OK)
    {
        ErrorLog.Set("glewInit failed!");
        return false;
    }

    if(!GLEW_VERSION_2_1)
    {
        ErrorLog.Set("OpenGL 2.1 not supported!");
        return false;
    }

    if(MSAAPixelFormat == 0 && samples > 0)
    {
        if(GLEW_ARB_multisample && WGLEW_ARB_pixel_format)
        {
            while(samples > 0)
            {
                UINT NumFormats = 0;

                int PFAttribs[] =
                {
                    WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
                    WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
                    WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
                    WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
                    WGL_COLOR_BITS_ARB, 32,
                    WGL_DEPTH_BITS_ARB, 24,
                    WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
                    WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
                    WGL_SAMPLES_ARB, samples,
                    0
                };

                if(wglChoosePixelFormatARB(DC, PFAttribs, NULL, 1, &MSAAPixelFormat, &NumFormats) == TRUE && NumFormats > 0) break;

                samples--;
            }

            wglDeleteContext(GLRC);
            DestroyWindow(Wnd);
            UnregisterClass(WndClassEx.lpszClassName, hInstance);

            return Java_joglni_OpenGLView_create21(env, obj, title, width, height, samples);
        }
        else
        {
            samples = 0;
        }
    }

    Samples = samples;

    if(GLEW_EXT_texture_filter_anisotropic)
    {
        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max_texture_max_anisotropy_ext);
    }

    if(WGLEW_EXT_swap_control)
    {
        wglSwapIntervalEXT(0);
    }

    Env = env;

    OpenGLViewJObject = obj;

    jclass OpenGLViewJClass = env->GetObjectClass(OpenGLViewJObject);

    OnPaintJMethodId = env->GetMethodID(OpenGLViewJClass, "onPaint", "(F)V");
    OnSizeJMethodId = env->GetMethodID(OpenGLViewJClass, "onSize", "(II)V");

    return env->CallBooleanMethod(obj, env->GetMethodID(env->GetObjectClass(obj), "onCreate", "()Z"));
}

JNIEXPORT void JNICALL Java_joglni_OpenGLView_destroy(JNIEnv *env, jobject obj)
{
    env->CallBooleanMethod(obj, env->GetMethodID(env->GetObjectClass(obj), "onDestroy", "()V"));

    wglDeleteContext(GLRC);
    DestroyWindow(Wnd);
}

JNIEXPORT void JNICALL Java_joglni_OpenGLView_displayMessage(JNIEnv *env, jobject obj, jstring title, jstring message)
{
    const char *Title = env->GetStringUTFChars(title, NULL);
    const char *Message = env->GetStringUTFChars(message, NULL);

    MessageBox(NULL, Message, Title, MB_OK);

    env->ReleaseStringUTFChars(title, Title);
    env->ReleaseStringUTFChars(message, Message);
}

JNIEXPORT jstring JNICALL Java_joglni_OpenGLView_getErrorLog(JNIEnv *env, jobject obj)
{
    return env->NewStringUTF(ErrorLog);
}

JNIEXPORT void JNICALL Java_joglni_OpenGLView_mainLoop(JNIEnv *env, jobject obj)
{
    MSG Msg;

    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
}

JNIEXPORT void JNICALL Java_joglni_OpenGLView_show(JNIEnv *env, jobject obj, jboolean maximized)
{
    RECT dRect, wRect, cRect;

    GetWindowRect(GetDesktopWindow(), &dRect);
    GetWindowRect(Wnd, &wRect);
    GetClientRect(Wnd, &cRect);

    wRect.right += Width - cRect.right;
    wRect.bottom += Height - cRect.bottom;
    wRect.right -= wRect.left;
    wRect.bottom -= wRect.top;
    wRect.left = dRect.right / 2 - wRect.right / 2;
    wRect.top = dRect.bottom / 2 - wRect.bottom / 2;

    MoveWindow(Wnd, wRect.left, wRect.top, wRect.right, wRect.bottom, FALSE);

    ShowWindow(Wnd, maximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
}

// ----------------------------------------------------------------------------------------------------------------------------

void OnPaint()
{
    static DWORD LastFPSTime = GetTickCount(), LastFrameTime = LastFPSTime, FPS = 0;

    PAINTSTRUCT ps;

    HDC DC = BeginPaint(Wnd, &ps);

    DWORD Time = GetTickCount();

    float FrameTime = (Time - LastFrameTime) * 0.001f;

    LastFrameTime = Time;

    if(Time - LastFPSTime > 1000)
    {
        CString Text = Title;

        Text.Append(" - %dx%d", Width, Height);
        Text.Append(", ATF %dx", gl_max_texture_max_anisotropy_ext);
        Text.Append(", MSAA %dx", Samples);
        Text.Append(", FPS: %d", FPS);
        Text.Append(" - %s", glGetString(GL_RENDERER));

        SetWindowText(Wnd, Text);

        LastFPSTime = Time;
        FPS = 0;
    }
    else
    {
        FPS++;
    }

    Env->CallVoidMethod(OpenGLViewJObject, OnPaintJMethodId, FrameTime);

    SwapBuffers(DC);

    EndPaint(Wnd, &ps);

    InvalidateRect(Wnd, NULL, FALSE);
}

void OnSize(int width, int height)
{
    Width = width;
    Height = height;

    Env->CallVoidMethod(OpenGLViewJObject, OnSizeJMethodId, Width, Height);
}

// ----------------------------------------------------------------------------------------------------------------------------

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uiMsg)
    {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        case WM_PAINT:
            OnPaint();
            break;

        case WM_SIZE:
            OnSize(LOWORD(lParam), HIWORD(lParam));
            break;

        default:
            return DefWindowProc(hWnd, uiMsg, wParam, lParam);
    }

    return 0;
}

// ----------------------------------------------------------------------------------------------------------------------------
OpenGL.java
package joglni;

public class OpenGL
{
    // ------------------------------------------------------------------------------------------------------------------------

    static
    {
        System.loadLibrary("joglni");
    }

    // OpenGL 1.1 -------------------------------------------------------------------------------------------------------------

    protected static final int GL_FALSE = 0;
    protected static final int GL_NONE = 0;
    protected static final int GL_POINTS = 0x0000;
    protected static final int GL_TRUE = 1;
    protected static final int GL_LINES = 0x0001;
    protected static final int GL_TRIANGLES = 0x0004;
    protected static final int GL_QUADS = 0x0007;
    protected static final int GL_DEPTH_BUFFER_BIT = 0x00000100;
    protected static final int GL_SRC_COLOR = 0x0300;
    protected static final int GL_ONE_MINUS_SRC_COLOR = 0x0301;
    protected static final int GL_SRC_ALPHA = 0x0302;
    protected static final int GL_ONE_MINUS_SRC_ALPHA = 0x0303;
    protected static final int GL_DST_ALPHA = 0x0304;
    protected static final int GL_ONE_MINUS_DST_ALPHA = 0x0305;
    protected static final int GL_DST_COLOR = 0x0306;
    protected static final int GL_ONE_MINUS_DST_COLOR = 0x0307;
    protected static final int GL_SRC_ALPHA_SATURATE = 0x0308;
    protected static final int GL_FRONT = 0x0404;
    protected static final int GL_BACK = 0x0405;
    protected static final int GL_FRONT_AND_BACK = 0x0408;
    protected static final int GL_CULL_FACE = 0x0B44;
    protected static final int GL_DEPTH_TEST = 0x0B71;
    protected static final int GL_BLEND = 0x0BE2;
    protected static final int GL_MAX_TEXTURE_SIZE = 0x0D33;
    protected static final int GL_TEXTURE_2D = 0x0DE1;
    protected static final int GL_BYTE = 0x1400;
    protected static final int GL_UNSIGNED_BYTE = 0x1401;
    protected static final int GL_SHORT = 0x1402;
    protected static final int GL_UNSIGNED_SHORT = 0x1403;
    protected static final int GL_INT = 0x1404;
    protected static final int GL_UNSIGNED_INT = 0x1405;
    protected static final int GL_FLOAT = 0x1406;
    protected static final int GL_DOUBLE = 0x140A;
    protected static final int GL_MODELVIEW = 0x1700;
    protected static final int GL_PROJECTION = 0x1701;
    protected static final int GL_DEPTH_COMPONENT = 0x1902;
    protected static final int GL_RGB = 0x1907;
    protected static final int GL_RGBA = 0x1908;
    protected static final int GL_NEAREST = 0x2600;
    protected static final int GL_LINEAR = 0x2601;
    protected static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700;
    protected static final int GL_LINEAR_MIPMAP_NEAREST = 0x2701;
    protected static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702;
    protected static final int GL_LINEAR_MIPMAP_LINEAR = 0x2703;
    protected static final int GL_TEXTURE_MAG_FILTER = 0x2800;
    protected static final int GL_TEXTURE_MIN_FILTER = 0x2801;
    protected static final int GL_TEXTURE_WRAP_S = 0x2802;
    protected static final int GL_TEXTURE_WRAP_T = 0x2803;
    protected static final int GL_CLAMP = 0x2900;
    protected static final int GL_COLOR_BUFFER_BIT = 0x00004000;
    protected static final int GL_RGB8 = 0x8051;
    protected static final int GL_RGBA8 = 0x8058;
    protected static final int GL_VERTEX_ARRAY = 0x8074;
    protected static final int GL_NORMAL_ARRAY = 0x8075;
    protected static final int GL_COLOR_ARRAY = 0x8076;
    protected static final int GL_TEXTURE_COORD_ARRAY = 0x8078;

    protected static final native void glBegin(int mode);
    protected static final native void glBindTexture(int target, int texture);
    protected static final native void glBlendFunc(int sfactor, int dfactor);
    protected static final native void glClear(int mask);
    protected static final native void glColor3f(float red, float green, float blue);
    protected static final native void glColor4f(float red, float green, float blue, float alpha);
    protected static final native void glColorPointer(int size, int type, int stride, byte[] ptr, int offset);
    protected static final native void glCullFace(int mode);
    protected static final native void glDeleteTextures(int n, int[] textures);
    protected static final native void glDisable(int cap);
    protected static final native void glDisableClientState(int cap);
    protected static final native void glDrawArrays(int mode, int first, int count);
    protected static final native void glDrawBuffer(int mode);
    protected static final native void glDrawElements(int mode, int count, int type, byte[] indices);
    protected static final native void glEnable(int cap);
    protected static final native void glEnableClientState(int cap);
    protected static final native void glEnd();
    protected static final native void glGenTextures(int n, int[] textures);
    protected static final native void glGetIntegerv (int pname, int[] params);
    protected static final native void glLineWidth(float width);
    protected static final native void glLoadIdentity();
    protected static final native void glLoadMatrixf(float[] m);
    protected static final native void glMatrixMode(int mode);
    protected static final native void glMultMatrixf(float[] m);
    protected static final native void glNormal3f(float nx, float ny, float nz);
    protected static final native void glNormalPointer(int type, int stride, byte[] ptr, int offset);
    protected static final native void glReadBuffer(int mode);
    protected static final native void glRotatef(float angle, float x, float y, float z);
    protected static final native void glScalef(float x, float y, float z);
    protected static final native void glTexCoord2f(float s, float t);
    protected static final native void glTexCoord3f(float s, float t, float r);
    protected static final native void glTexCoordPointer(int size, int type, int stride, byte[] ptr, int offset);
    protected static final native void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, byte[] pixels);
    protected static final native void glTexParameteri(int target, int pname, int param);
    protected static final native void glTranslatef(float x, float y, float z);
    protected static final native void glVertex2f(float x, float y);
    protected static final native void glVertex3f(float x, float y, float z);
    protected static final native void glVertexPointer(int size, int type, int stride, byte[] ptr, int offset);
    protected static final native void glViewport(int x, int y, int width, int height);

    // OpenGL 1.2 -------------------------------------------------------------------------------------------------------------

    protected static final int GL_TEXTURE_3D = 0x806F;
    protected static final int GL_BGR = 0x80E0;
    protected static final int GL_BGRA = 0x80E1;
    protected static final int GL_CLAMP_TO_EDGE = 0x812F;

    protected static final native void glTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, int border, int format, int type, byte[] pixels);

    // OpenGL 1.3 -------------------------------------------------------------------------------------------------------------

    protected static final int GL_TEXTURE0 = 0x84C0;
    protected static final int GL_TEXTURE1 = 0x84C1;
    protected static final int GL_TEXTURE2 = 0x84C2;
    protected static final int GL_TEXTURE3 = 0x84C3;
    protected static final int GL_TEXTURE4 = 0x84C4;
    protected static final int GL_TEXTURE5 = 0x84C5;
    protected static final int GL_TEXTURE6 = 0x84C6;
    protected static final int GL_TEXTURE7 = 0x84C7;
    protected static final int GL_TEXTURE8 = 0x84C8;
    protected static final int GL_TEXTURE9 = 0x84C9;
    protected static final int GL_TEXTURE_CUBE_MAP = 0x8513;
    protected static final int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
    protected static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
    protected static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
    protected static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
    protected static final int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
    protected static final int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;

    protected static final native void glActiveTexture(int texture);
    protected static final native void glMultiTexCoord2f(int target, float s, float t);
    protected static final native void glMultiTexCoord3f(int target, float s, float t, float r);

    // OpenGL 1.4 -------------------------------------------------------------------------------------------------------------

    protected static final int GL_GENERATE_MIPMAP = 0x8191;
    protected static final int GL_DEPTH_COMPONENT24 = 0x81A6;

    // OpenGL 1.5 -------------------------------------------------------------------------------------------------------------

    protected static final int GL_ARRAY_BUFFER = 0x8892;
    protected static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893;
    protected static final int GL_STATIC_DRAW = 0x88E4;

    protected static final native void glBindBuffer(int target, int buffer);
    protected static final native void glBufferData(int target, int size, byte[] data, int usage);
    protected static final native void glDeleteBuffers(int n, int[] buffers);
    protected static final native void glGenBuffers(int n, int[] buffers);

    // GL_ARB_texture_float ---------------------------------------------------------------------------------------------------

    protected static final int GL_RGBA32F_ARB = 0x8814;
    protected static final int GL_RGBA16F_ARB = 0x881A;

    protected static final native boolean GL_ARB_texture_float();

    // GL_ARB_texture_non_power_of_two ----------------------------------------------------------------------------------------

    protected static final native boolean GL_ARB_texture_non_power_of_two();

    // GL_EXT_framebuffer_object ----------------------------------------------------------------------------------------------

    protected static final int GL_COLOR_ATTACHMENT0_EXT = 0x8CE0;
    protected static final int GL_COLOR_ATTACHMENT1_EXT = 0x8CE1;
    protected static final int GL_COLOR_ATTACHMENT2_EXT = 0x8CE2;
    protected static final int GL_COLOR_ATTACHMENT3_EXT = 0x8CE3;
    protected static final int GL_COLOR_ATTACHMENT4_EXT = 0x8CE4;
    protected static final int GL_COLOR_ATTACHMENT5_EXT = 0x8CE5;
    protected static final int GL_COLOR_ATTACHMENT6_EXT = 0x8CE6;
    protected static final int GL_COLOR_ATTACHMENT7_EXT = 0x8CE7;
    protected static final int GL_COLOR_ATTACHMENT8_EXT = 0x8CE8;
    protected static final int GL_COLOR_ATTACHMENT9_EXT = 0x8CE9;
    protected static final int GL_DEPTH_ATTACHMENT_EXT = 0x8D00;
    protected static final int GL_FRAMEBUFFER_EXT = 0x8D40;

    protected static final native void glBindFramebufferEXT(int target, int framebuffer);
    protected static final native void glDeleteFramebuffersEXT(int n, int[] framebuffers);
    protected static final native void glFramebufferTexture2DEXT(int target, int attachment, int textarget, int texture, int level);
    protected static final native void glGenFramebuffersEXT(int n, int[] framebuffers);
    protected static final native void glGenerateMipmapEXT(int target);

    protected static final native boolean GL_EXT_framebuffer_object();

    // GL_EXT_texture_array ---------------------------------------------------------------------------------------------------

    protected static final int GL_TEXTURE_2D_ARRAY_EXT = 0x8C1A;
    
    protected static final native void glFramebufferTextureLayerEXT(int target, int attachment, int texture, int level, int layer);

    protected static final native boolean GL_EXT_texture_array();

    // GL_EXT_texture_filter_anisotropic --------------------------------------------------------------------------------------

    protected static final int GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
    protected static final int GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;

    protected static final native boolean GL_EXT_texture_filter_anisotropic();

    // GLU --------------------------------------------------------------------------------------------------------------------

    protected static final native void gluPerspective(double fovy, double aspect, double zNear, double zFar);
    protected static final native void gluLookAt(double eyeX, double eyeY, double eyeZ, double centerX, double centerY, double centerZ, double upX, double upY, double upZ);

    // ------------------------------------------------------------------------------------------------------------------------
}
OpenGLRenderer.java
package joglni;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public abstract class OpenGLRenderer extends OpenGL
{
    // ------------------------------------------------------------------------------------------------------------------------

    static
    {
        System.loadLibrary("joglni");
    }

    // ------------------------------------------------------------------------------------------------------------------------

    protected final native void addError(String error);

    // ------------------------------------------------------------------------------------------------------------------------

    public abstract boolean init();
    public abstract void render(float frameTime);
    public abstract void resize(int width, int height);
    public abstract void destroy();

    // ------------------------------------------------------------------------------------------------------------------------

    protected static final byte[] getByteArray(short[] shortArray)
    {
        byte[] byteArray = new byte[shortArray.length * 2];

        ByteBuffer.wrap(byteArray).order(ByteOrder.nativeOrder()).asShortBuffer().put(shortArray);

        return byteArray;
    }

    protected static final byte[] getByteArray(int[] intArray)
    {
        byte[] byteArray = new byte[intArray.length * 4];

        ByteBuffer.wrap(byteArray).order(ByteOrder.nativeOrder()).asIntBuffer().put(intArray);

        return byteArray;
    }

    protected static final byte[] getByteArray(float[] floatArray)
    {
        byte[] byteArray = new byte[floatArray.length * 4];

        ByteBuffer.wrap(byteArray).order(ByteOrder.nativeOrder()).asFloatBuffer().put(floatArray);

        return byteArray;
    }

    protected static final byte[] getByteArray(double[] doubleArray)
    {
        byte[] byteArray = new byte[doubleArray.length * 8];

        ByteBuffer.wrap(byteArray).order(ByteOrder.nativeOrder()).asDoubleBuffer().put(doubleArray);

        return byteArray;
    }

    // ------------------------------------------------------------------------------------------------------------------------
}
OpenGLView.java
package joglni;

public final class OpenGLView
{
    // ------------------------------------------------------------------------------------------------------------------------

    static
    {
        System.loadLibrary("joglni");
    }

    // ------------------------------------------------------------------------------------------------------------------------

    private final OpenGLRenderer openglRenderer;

    // ------------------------------------------------------------------------------------------------------------------------

    public OpenGLView(OpenGLRenderer openglRenderer)
    {
        this.openglRenderer = openglRenderer;
    }

    // ------------------------------------------------------------------------------------------------------------------------

    public native boolean create21(String title, int width, int height, int samples);
    public native void destroy();
    public native void displayMessage(String title, String message);
    public native String getErrorLog();
    public native void mainLoop();
    public native void show(boolean maximized);

    // ------------------------------------------------------------------------------------------------------------------------

    private boolean onCreate()
    {
        if(openglRenderer != null)
        {
            return openglRenderer.init();
        }

        return true;
    }

    private void onPaint(float FrameTime)
    {
        if(openglRenderer != null)
        {
            openglRenderer.render(FrameTime);
        }
    }

    private void onSize(int width, int height)
    {
        if(openglRenderer != null)
        {
            openglRenderer.resize(width, height);
        }
    }

    private void onDestroy()
    {
        if(openglRenderer != null)
        {
            openglRenderer.destroy();
        }
    }

    // ------------------------------------------------------------------------------------------------------------------------
}
MyOpenGLRenderer.java
import joglni.OpenGLRenderer;

public final class MyOpenGLRenderer extends OpenGLRenderer
{
    // ------------------------------------------------------------------------------------------------------------------------

    private final int[] textures = new int[1];
    private final int[] arrayBuffers = new int[3];
    private final int[] elementArrayBuffers = new int[1];

    private byte[] vertices;
    private byte[] texcoords;
    private byte[] data;
    private byte[] indices;

    private float angle = 0.0f;

    // ------------------------------------------------------------------------------------------------------------------------

    @Override
    public boolean init()
    {
        // --------------------------------------------------------------------------------------------------------------------

        glGenTextures(textures.length, textures);

        float[] pixels = new float[1024];

        for(int y = 0; y < 16; y++)
        {
            for(int x = 0; x < 16; x++)
            {
                int i = (y * 16 + x) * 4;

                pixels[i] = (float)x / 15.0f;
                pixels[i + 1] = (float)y / 15.0f;
                pixels[i + 2] = 0.0f;
                pixels[i + 3] = 1.0f;
            }
        }

        glBindTexture(GL_TEXTURE_2D, textures[0]);

        int textureFiltering = 1;

        if(textureFiltering == 1)
        {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        }
        else if(textureFiltering == 2)
        {
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_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);
        }

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 0, GL_RGBA, GL_FLOAT, getByteArray(pixels));

        glBindTexture(GL_TEXTURE_2D, 0);

        // --------------------------------------------------------------------------------------------------------------------

        glGenBuffers(arrayBuffers.length, arrayBuffers);

        float[] vertices = new float[]
        {   //  x,     y,     z
            -0.5f, -0.5f,  0.0f,
             0.5f, -0.5f,  0.0f,
             0.5f,  0.5f,  0.0f,
            -0.5f,  0.5f,  0.0f
        };

        this.vertices = getByteArray(vertices);

        glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[0]);
        glBufferData(GL_ARRAY_BUFFER, this.vertices.length, this.vertices, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        float[] texcoords = new float[]
        {   //  s,     t
             0.0f,  0.0f,
             1.0f,  0.0f,
             1.0f,  1.0f,
             0.0f,  1.0f
        };

        this.texcoords = getByteArray(texcoords);

        glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[1]);
        glBufferData(GL_ARRAY_BUFFER, this.texcoords.length, this.texcoords, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        float[] data = new float[]
        {   //  x,     y,     z,     s,     t
            -0.5f, -0.5f,  0.0f,  0.0f,  0.0f,
             0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
             0.5f,  0.5f,  0.0f,  1.0f,  1.0f,
            -0.5f,  0.5f,  0.0f,  0.0f,  1.0f
        };

        this.data = getByteArray(data);

        glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[2]);
        glBufferData(GL_ARRAY_BUFFER, this.data.length, this.data, GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        // --------------------------------------------------------------------------------------------------------------------

        glGenBuffers(elementArrayBuffers.length, elementArrayBuffers);

        int[] indices = new int[]
        {
            0, 1, 2, // 1. triangle
            2, 3, 0  // 2. triangle
        };

        this.indices = getByteArray(indices);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffers[0]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, this.indices.length, this.indices, GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        // --------------------------------------------------------------------------------------------------------------------

        return true;

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ------------------------------------------------------------------------------------------------------------------------

    @Override
    public void render(float FrameTime)
    {
        // --------------------------------------------------------------------------------------------------------------------

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // --------------------------------------------------------------------------------------------------------------------

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

        // --------------------------------------------------------------------------------------------------------------------

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);

        // --------------------------------------------------------------------------------------------------------------------

        glRotatef(angle, 0.0f, 0.0f, 1.0f);

        // --------------------------------------------------------------------------------------------------------------------

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, textures[0]);

        // --------------------------------------------------------------------------------------------------------------------

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        int method1 = 4;

        if(method1 == 1) // 2 vertex arrays
        {
            glVertexPointer(3, GL_FLOAT, 0, vertices, 0);
            glTexCoordPointer(2, GL_FLOAT, 0, texcoords, 0);
        }
        else if(method1 == 2) // 1 vertex array
        {
            glVertexPointer(3, GL_FLOAT, 20, data, 0);
            glTexCoordPointer(2, GL_FLOAT, 20, data, 12);
        }
        else if(method1 == 3) // 2 vertex buffer objects
        {
            glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[0]);
            glVertexPointer(3, GL_FLOAT, 0, null, 0);

            glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[1]);
            glTexCoordPointer(2, GL_FLOAT, 0, null, 0);

            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }
        else if(method1 == 4) // 1 vertex buffer object
        {
            glBindBuffer(GL_ARRAY_BUFFER, arrayBuffers[2]);

            glVertexPointer(3, GL_FLOAT, 20, null, 0);
            glTexCoordPointer(2, GL_FLOAT, 20, null, 12);

            glBindBuffer(GL_ARRAY_BUFFER, 0);
        }

        // --------------------------------------------------------------------------------------------------------------------

        if(method1 >= 1 && method1 <= 4)
        {
            int method2 = 3;

            if(method2 == 1)
            {
                glDrawArrays(GL_QUADS, 0, 4);
            }
            else if(method2 == 2)
            {
                glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
            }
            else if(method2 == 3)
            {
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementArrayBuffers[0]);
                glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, null);
                glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
            }
        }

        // --------------------------------------------------------------------------------------------------------------------

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);

        // --------------------------------------------------------------------------------------------------------------------

        glBindTexture(GL_TEXTURE_2D, 0);
        glDisable(GL_TEXTURE_2D);

        // --------------------------------------------------------------------------------------------------------------------

        glDisable(GL_CULL_FACE);
        glDisable(GL_DEPTH_TEST);

        // --------------------------------------------------------------------------------------------------------------------

        angle += 11.25f * FrameTime;

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ------------------------------------------------------------------------------------------------------------------------

    @Override
    public void resize(int width, int height)
    {
        // --------------------------------------------------------------------------------------------------------------------

        glViewport(0, 0, width, height);

        // --------------------------------------------------------------------------------------------------------------------

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, (float)width / (float)height, 0.125f, 512.0f);

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ------------------------------------------------------------------------------------------------------------------------

    @Override
    public void destroy()
    {
        // --------------------------------------------------------------------------------------------------------------------

        glDeleteTextures(textures.length, textures);

        // --------------------------------------------------------------------------------------------------------------------

        glDeleteBuffers(arrayBuffers.length, arrayBuffers);

        // --------------------------------------------------------------------------------------------------------------------

        glDeleteBuffers(elementArrayBuffers.length, elementArrayBuffers);

        // --------------------------------------------------------------------------------------------------------------------
    }

    // ------------------------------------------------------------------------------------------------------------------------
}
FirstJOGLNIApplication.java
import joglni.OpenGLView;

public final class FirstJOGLNIApplication
{
    public static void main(String[] args)
    {
        String appName = "First JOGLNI application";

        OpenGLView openGLView = new OpenGLView(new MyOpenGLRenderer());

        if(openGLView.create21(appName, 800, 600, 4))
        {
            openGLView.show(false);
            openGLView.mainLoop();
        }
        else
        {
            openGLView.displayMessage(appName, openGLView.getErrorLog());
        }

        openGLView.destroy();
    }
}
Download
joglni.zip (Visual Studio 2008 Professional, NetBeans)

© 2010 - 2016 Bc. Michal Belanec, michalbelanec@centrum.sk
Last update June 25, 2016
OpenGL® is a registered trademark of Silicon Graphics Inc.