Java tutorial
/******************************************************************************* * MIT License * * Copyright (c) 2016 Ashur Rafiev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. *******************************************************************************/ package com.xrbpowered.gl; import java.util.Arrays; import java.util.Comparator; import org.lwjgl.LWJGLException; import org.lwjgl.Sys; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.ContextAttribs; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.DisplayMode; import org.lwjgl.opengl.EXTTextureFilterAnisotropic; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.NVXGpuMemoryInfo; import org.lwjgl.opengl.PixelFormat; import org.lwjgl.util.glu.GLU; import com.xrbpowered.gl.SystemSettings.WindowMode; import com.xrbpowered.gl.res.buffers.RenderTarget; import com.xrbpowered.utils.JNIUtils; public abstract class Client { public static SystemSettings settings = SystemSettings.load("settings.json", null); protected DisplayMode displayMode; public Client init(String windowTitle) { return init(windowTitle, 3, 3); } public Client init(String windowTitle, int glMajor, int glMinor) { JNIUtils.addLibraryPath("lib/native"); try { setupOpenGL(windowTitle, glMajor, glMinor); setupResources(); printInfo(); } catch (LWJGLException e) { e.printStackTrace(); System.exit(-1); } return this; } protected void setupOpenGL(String windowTitle, int glMajor, int glMinor) throws LWJGLException { PixelFormat pixelFormat = new PixelFormat(); ContextAttribs contextAtrributes = new ContextAttribs(glMajor, glMinor).withForwardCompatible(true) .withProfileCore(true); Display.setTitle(windowTitle); if (settings.windowMode == WindowMode.fullscreen) { Display.create(pixelFormat, contextAtrributes); displayMode = settings.applyAll(this); } else { displayMode = settings.applyAll(this); Display.create(pixelFormat, contextAtrributes); } settings.verifyAnisotropy(); createRenderTarget(); } public void run() { long prevTime = Sys.getTime(); long time; while (!Display.isCloseRequested()) { if (Display.wasResized()) { createRenderTarget(); resizeResources(); } time = Sys.getTime(); float dt = (time - prevTime) / (float) Sys.getTimerResolution(); update(dt); render(RenderTarget.primaryBuffer); prevTime = time; Display.update(false); if (settings.vsync) Display.sync(displayMode.getFrequency() * 2); else if (settings.maxFps > 0) Display.sync(settings.maxFps); while (Mouse.next()) ; while (Keyboard.next()) ; Display.processMessages(); } exit(); } public void exit() { destroyResources(); Display.destroy(); System.exit(0); } protected void update(float dt) { } public void render(RenderTarget primaryTarget) { } public void createRenderTarget() { } protected abstract void setupResources(); protected abstract void destroyResources(); protected void resizeResources() { } public void updateResources(SystemSettings settings, SystemSettings old) { } public void switchToWindowed(int width, int height, boolean resizeResources) throws LWJGLException { System.setProperty("org.lwjgl.opengl.Window.undecorated", "false"); Display.setFullscreen(false); Display.setDisplayMode(new DisplayMode(width, height)); Display.setResizable(true); if (resizeResources) { GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight()); createRenderTarget(); resizeResources(); } } public void switchToBorderless(boolean resizeResources) throws LWJGLException { DisplayMode desktop = Display.getDesktopDisplayMode(); System.setProperty("org.lwjgl.opengl.Window.undecorated", "true"); Display.setFullscreen(false); Display.setDisplayMode(new DisplayMode(desktop.getWidth(), desktop.getHeight())); Display.setResizable(false); if (resizeResources) { GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight()); createRenderTarget(); resizeResources(); } } public DisplayMode switchToFullscreen(int width, int height, int freq, boolean resizeResources) throws LWJGLException { DisplayMode mode = findFullscreenMode(width, height, freq); Display.setDisplayModeAndFullscreen(mode); if (resizeResources) { GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight()); createRenderTarget(); resizeResources(); } return mode; } public static DisplayMode findFullscreenMode(int width, int height, int freq) throws LWJGLException { DisplayMode[] modes = Display.getAvailableDisplayModes(); DisplayMode match = null; for (DisplayMode m : modes) { if (m.getBitsPerPixel() != 32 || !m.isFullscreenCapable()) continue; if (match == null) match = m; else { if (Math.abs(m.getHeight() - height) < Math.abs(match.getHeight() - height) || Math.abs(m.getWidth() - width) < Math.abs(match.getWidth() - width) || freq <= 0 && m.getFrequency() > match.getFrequency() || freq > 0 && Math.abs(m.getFrequency() - freq) < Math.abs(match.getFrequency() - freq)) match = m; } } return match; } public static void printInfo() { System.out.println("\n--------------------------------\nSYSTEM INFO\n--------------------------------"); System.out.println("Device: " + GL11.glGetString(GL11.GL_RENDERER)); System.out.println("Device vendor: " + GL11.glGetString(GL11.GL_VENDOR)); System.out.println("OpenGL version: " + GL11.glGetString(GL11.GL_VERSION)); System.out.printf("Max texture size: %d\n", GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE)); System.out.printf("Max MSAA samples: %d\n", GL11.glGetInteger(GL30.GL_MAX_SAMPLES)); System.out.printf("Max anisotropy: %d\n", GL11.glGetInteger(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)); System.out.printf("Max texture array layers: %d\n", GL11.glGetInteger(GL30.GL_MAX_ARRAY_TEXTURE_LAYERS)); System.out.printf("Max vertex attribs: %d\n", GL11.glGetInteger(GL20.GL_MAX_VERTEX_ATTRIBS)); System.out.printf("Max uniform components: %d\n", GL11.glGetInteger(GL20.GL_MAX_VERTEX_UNIFORM_COMPONENTS)); System.out.printf("Available video memory (NVIDIA only): %.1f%%\n", getAvailMemoryNVidia() * 100f); System.out.println("--------------------------------"); System.out.println(); GL11.glGetError(); // clear errors } public static void printFulscreenModes() { System.out.println("Available fullscreen modes:"); DisplayMode desktop = Display.getDesktopDisplayMode(); try { DisplayMode[] modes = Display.getAvailableDisplayModes(); Arrays.sort(modes, new Comparator<DisplayMode>() { @Override public int compare(DisplayMode o1, DisplayMode o2) { if (o1.getWidth() != o2.getWidth()) return Integer.compare(o1.getWidth(), o2.getWidth()); else return Integer.compare(o1.getHeight(), o2.getHeight()); } }); for (DisplayMode m : modes) { if (m.getBitsPerPixel() != 32 || m.getFrequency() < 60 || !m.isFullscreenCapable()) continue; boolean aspect = (m.getWidth() / (float) m.getHeight() == desktop.getWidth() / (float) desktop.getHeight()); if (!aspect) continue; System.out.printf("%dx%d%s@%dHz\n", m.getWidth(), m.getHeight(), !aspect ? "(aspect!)" : "", m.getFrequency()); } System.out.println(); } catch (LWJGLException e) { e.printStackTrace(); } } public float getAspectRatio() { return Display.getWidth() / (float) Display.getHeight(); } public static float getAvailMemoryNVidia() { try { return (float) GL11.glGetInteger(NVXGpuMemoryInfo.GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX) / (float) GL11.glGetInteger(NVXGpuMemoryInfo.GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX); } catch (Exception e) { return -1f; } } public static boolean isGLExtensionSupported(String name) { int count = GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS); for (int i = 0; i < count; i++) { String ext = GL30.glGetStringi(GL11.GL_EXTENSIONS, i); if (name.equals(ext)) return true; } return false; } public static void checkError(boolean crash) { int err = GL11.glGetError(); if (err != GL11.GL_NO_ERROR) { (new RuntimeException(GLU.gluErrorString(err))).printStackTrace(); if (crash) { printInfo(); System.exit(1); } } } public static void checkError() { checkError(true); } private static long time = 0L; public static void timestamp(String s) { long t = System.nanoTime(); if (time > 0L && s != null) { System.out.printf("%5.1f ms\t - %s\n", (t - time) / 1000000.0, s); } time = t; } }