public void display(long deltaTime) { Display.sync(60); elapsedTime += deltaTime; if (Display.wasResized()) resize(); float[] offsets = computePositionOffsets(0, 0, deltaTime); float xOffset = offsets[0]; float yOffset = offsets[1]; adjustVertexData(xOffset, yOffset); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program); glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0); glDrawArrays(GL_TRIANGLES, 0, 3); glDisableVertexAttribArray(0); glUseProgram(0); Display.update(); // calls (among other things) swapBuffers() }
/** * Prepares the screen for rendering, which includes clearing it. * * <p>Also does the current {@link JumboRenderModule}'s custom preparation action. */ public static void prepare() { if (wasResized) { update(); } GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); wasResized = Display.wasResized(); current.prepare(); }
public void render() { if (Display.wasResized()) { WIDTH = Display.getWidth(); HEIGHT = Display.getHeight(); if (currentScreen != null) { currentScreen.setSize(WIDTH, HEIGHT); } } GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); if (currentScreen != null) { currentScreen.render(); } }
/** * Class that handles all OpenGL rendering code. * <p> * Contains an internal buffer of {@link JumboRenderModule}s, and can switch * between them. By default, index 0 has the built-in implemenation, and the * <code>JumboRenderer<code> will use that unless you specify otherwise. */ public final class JumboRenderer { /** */ public static boolean wasResized = Display.wasResized(); static int renderwidth, renderheight; private static final ArrayList<JumboRenderModule> modes = new ArrayList<>(); private static JumboRenderModule current; private static int currentmode = 0; private JumboRenderer() {} /** * Adds a new {@link JumboRenderModule} to the internal buffer. * * @param m JumboRenderMode to be added * @return index of the added JumboRenderMode * @throws NullPointerException if the parameter is null */ public static int addRenderMode(JumboRenderModule m) { if (m == null) { throw new NullPointerException("Inputted JumboRenderMode is null!"); } modes.add(m); return modes.size() - 1; } /** * Removes a {@link JumboRenderModule} from the internal buffer. * * @param m index of the JumboRenderMode to be removed * @throws IndexOutOfBoundsException if the parameter is less than 0 * @throws IllegalArgumentException if the paramater is larger than the internal buffer size */ public static void removeRenderMode(int m) { if (m < 0) { throw new IllegalArgumentException("Input can't be less than 0!"); } if (modes.size() < m) { throw new IndexOutOfBoundsException(m + " is larger than the internal buffer size!"); } if (currentmode == m) { throw new IllegalArgumentException("Can't remove the current JumboRenderMode!"); } modes.remove(m); } /** * Removes a {@link JumboRenderModule} from the internal buffer. * * @param m JumboRenderMode to be removed * @throws NullPointerException if the parameter is null * @throws IllegalArgumentException if the paramater was never added or it is the only * JumboRenderMode in the bufer. */ public static void removeRenderMode(JumboRenderModule m) { if (m == null) { throw new NullPointerException("Inputted JumboRenderMode is null!"); } if (!modes.contains(m)) { throw new IllegalArgumentException("JumboRenderMode " + m + " was never added!"); } if (modes.size() <= 1) { throw new IllegalArgumentException("Can't remove the only existing JumboRenderMode!"); } if (currentmode == modes.indexOf(m)) { throw new IllegalArgumentException("Can't remove the current JumboRenderMode!"); } modes.remove(m); } /** * Get the {@link JumboRenderModule} located at an index. * * @param index location of desired JumboRenderMode * @return The JumboRenderMode located at the specified index * @see #locationOfMode(JumboRenderModule m) */ public static JumboRenderModule getMode(int index) { if (index < 0) { throw new IllegalArgumentException("Input is less than 0!"); } if (index >= modes.size()) { throw new IndexOutOfBoundsException("Input is larger than the internal buffer size!"); } return modes.get(index); } /** * Returns the location of a {@link JumboRenderModule} in the internal buffer. * * @param m the JumboRenderMode to look up * @return the index of parameter <i>m</i> */ public static int locationOfMode(JumboRenderModule m) { if (m == null) { throw new NullPointerException("Input is null!"); } final int loc = modes.indexOf(m); if (loc < 0) { throw new IllegalArgumentException("Render mode " + m + " is not in the internal buffer!"); } return loc; } /** * Sets a new {@JumboRenderMode} to be used for rendering. * * <p>If the input is not in the internal buffer, it will get added automatically * * @param m the JumboRenderMode to be used * @see #render(JumboGraphicsObject obj) * @see #addRenderMode(JumboRenderModule m) * @see #setCurrentRenderMode(int index) */ public static void setCurrentRenderMode(JumboRenderModule m) { if (m == null) { throw new NullPointerException("Input is null!"); } final int loc; if (!modes.contains(m)) { loc = addRenderMode(m); } else { loc = modes.indexOf(m); } currentmode = loc; current = m; current.init(); } /** * Sets the current {@link JumboRenderModule} to be used for rendering. * * @param index the location of the desired mode in the internal buffer * @see #render(JumboGraphicsObject obj) * @see #addRenderMode(JumboRenderModule m) * @see #setCurrentRenderMode(JumboRenderModule m) */ public static void setCurrentRenderMode(int index) { if (index < 0) { throw new IllegalArgumentException("Input is less than 0!"); } if (index >= modes.size()) { throw new IndexOutOfBoundsException("Input is larger than the internal buffer size!"); } setCurrentRenderMode(modes.get(index)); } /** * Set the JumboColor that the screen is cleared to every frame. * * @param r red value represented by 0.0 to 1.0 * @param g green value represented by 0.0 to 1.0 * @param b blue value represented by 0.0 to 1.0 */ public static void setRefreshcolor(float r, float g, float b) { if (r > 1) { throw new IllegalArgumentException("Red cannot be greater than 1!"); } if (g > 1) { throw new IllegalArgumentException("Green cannot be greater than 1!"); } if (b > 1) { throw new IllegalArgumentException("Blue cannot be greater than 1!"); } if (r < 0) { throw new IllegalArgumentException("Red cannot be less than 1!"); } if (g < 0) { throw new IllegalArgumentException("Green cannot be less than 1!"); } if (b < 0) { throw new IllegalArgumentException("Blue cannot be less than 1!"); } refreshcolor = new Position3DF(r, g, b); GL11.glClearColor(refreshcolor.x, refreshcolor.y, refreshcolor.z, 1); } /** * The 'display width' is the width of the current area being rendered to. * * @return the current bounds for rendering * @see #getDisplayheight() * @see #setDisplayheight(int displayheight) * @see #setDisplaywidth(int displaywidth) */ public static int getDisplaywidth() { return renderwidth; } /** * Set the width of the area to render to. Pixels outside this width will not be rendered. * * <p><b>NOTE: DOESN'T ACTUALLY CHANGE THE SIZE OF THE WINDOW</b> * * @param displaywidth the new width * @see #getDisplaywidth() * @see #setDisplayheight(int displayheight) */ public static void setDisplaywidth(int displaywidth) { JumboRenderer.renderwidth = displaywidth; } /** * Returns the current height of the area being rendered to. * * @return the display height * @see #setDisplayheight(int height) */ public static int getDisplayheight() { return renderheight; } /** * Set the height of the area to render to. Pixels outside this height will not be rendered. * * <p><b>NOTE: DOESN'T ACTUALLY CHANGE THE SIZE OF THE WINDOW</b> * * @param displayheight the new height * @see #getDisplayheight() * @see #setDisplaywidth(int width) */ public static void setDisplayheight(int displayheight) { JumboRenderer.renderheight = displayheight; } /** * Set the JumboColor OpenGL will clear to screen to. * * @param c the new JumboColor */ public static void setRefreshcolor(JumboColor c) { if (c == null) { throw new NullPointerException("Input is null!"); } refreshcolor.x = c.getRed() / 255.0f; refreshcolor.y = c.getGreen() / 255.0f; refreshcolor.z = c.getBlue() / 255.0f; GL11.glClearColor(refreshcolor.x, refreshcolor.y, refreshcolor.z, 1); } private static Position3DF refreshcolor = new Position3DF(0, 0, 0); public static void init() { // the default mode addRenderMode(new JumboRenderModuleGL11()); setCurrentRenderMode(0); update(); } /** * Prepares the screen for rendering, which includes clearing it. * * <p>Also does the current {@link JumboRenderModule}'s custom preparation action. */ public static void prepare() { if (wasResized) { update(); } GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); wasResized = Display.wasResized(); current.prepare(); } /** * Called when the screen is resized, and sets some variables, like {@link JumboMathHandler#xmod} * and {@link JumboMathHandler#ymod}. */ public static void update() { // JumboLaunchConfig config = JumboSettings.launchConfig; final int width, height; final float factor; if (JumboSettings.launchConfig.fullscreen) { final DisplayMode current = Display.getDisplayMode(); factor = Display.getPixelScaleFactor(); width = current.getWidth(); height = current.getHeight(); } else { width = Display.getWidth(); height = Display.getHeight(); factor = Display.getPixelScaleFactor(); } // Dynamic resizing only works if its larger than the launch // dimensions. // If its not, it gets strectched, which looks a bit ugly. Because // of // this, developers should make their base window as small as // possible. // if (width < config.width || height < config.height) { // renderwidth = config.width; // renderheight = config.height; // GL11.glOrtho(0.0f, config.width, 0, config.height, 0.0f, 1.0f); // GL11.glViewport(0, 0, width, height); // Maths.currentdim = new Dimension(config.width, config.height); // } else { // for high dpi modes renderwidth = (int) (width * factor); renderheight = (int) (height * factor); for (JumboRenderModule m : modes) { m.resize(renderwidth, renderheight); } JumboPaintClass.getScene().onWindowUpdate(); JumboPaintClass.getPreviousScene().onWindowUpdate(); wasResized = false; } /** * Renders the {@link JumboGraphicsObject} paramater using the specified {@link * JumboRenderModule}, calling its initiation action, preparation action, and finally the render * action. Afterwards, reverts everything to the default render mode. * * <p>This method is slower than the standard {@link #render(JumboGraphicsObject e)}, as it has to * switch render modes. * * @param e GraphicsObject to be rendered * @param index location of the JumboRenderMode in the internal buffer to be used * @see #render(JumboGraphicsObject e) */ public static void render(JumboGraphicsObject e, int index) { if (index != currentmode) { render(e, getMode(index)); } else { render(e); } } /** * Renders the {@link JumboGraphicsObject} parameter using the specified {@link * JumboRenderModule}, calling its initiation action, preparation action, and finally the render * action. Afterwards, reverts everything to the default render mode. * * <p>This method is slower than the standard {@link #render(JumboGraphicsObject e)}, as it has to * switch render modes twice. * * @param e GraphicsObject to be rendered * @param m the JumboRenderMode to use for rendering * @see #render(JumboGraphicsObject e) */ public static void render(JumboGraphicsObject e, JumboRenderModule m) { try { m.init(); m.prepare(); m.render(e, renderwidth, renderheight); current.init(); current.prepare(); } catch (NullPointerException ex) { JumboErrorHandler.handle(ex, "A parameter in the entity " + e + " is null!"); } catch (Exception exc) { JumboErrorHandler.handle(exc, "Error rendering " + exc); } } /** * Renders the {@link JumboGraphicsObject} parameter using the current {@link JumboRenderModule}. * * @param e GraphicsObject to be rendered * @see #render(JumboGraphicsObject e, JumboRenderModule m) * @see #setCurrentRenderMode(int index) */ public static void render(JumboGraphicsObject e) { try { current.render(e, renderwidth, renderheight); } catch (NullPointerException ex) { JumboErrorHandler.handle(ex, "A parameter in the entity " + e + " is null!"); } catch (Exception exc) { JumboErrorHandler.handle(exc, "Error rendering " + exc); } } /** * Returns the current JumboColor that is being refreshed to as a {@link Position3DF}. * * @return current refresh JumboColor * @see JumboColor * @see #setRefreshcolor(Position3DF c) */ public static Position3DF getRefreshcolor() { return refreshcolor; } /** * Set the current JumboColor that the screen will be cleared to. * * @param c new JumboColor, as a {@link Position3DF} * @see #getRefreshcolor() * @see #setRefreshcolor(JumboColor c) * @see #setRefreshcolor(float r, float g, float b) */ public static void setRefreshcolor(Position3DF c) { refreshcolor = c; GL11.glClearColor(refreshcolor.x, refreshcolor.y, refreshcolor.z, 1); } }
@Override public void update(Engine engine, double time, double dt) { Window window = engine.getGlobal(Window.class); window.closing = Display.isCloseRequested(); if (Display.wasResized()) { window.width = Display.getWidth(); window.height = Display.getHeight(); } KeyboardComponent keyboard = engine.getGlobal(KeyboardComponent.class); Keyboard.poll(); for (int i = 0; i < keyboard.down.length; i++) { keyboard.pressed[i] = false; keyboard.released[i] = false; keyboard.down[i] = Keyboard.isKeyDown(i); } while (Keyboard.next()) { int key = Keyboard.getEventKey(); keyboard.pressed[key] = Keyboard.getEventKeyState(); keyboard.released[key] = !keyboard.pressed[key]; } MouseComponent mouse = engine.getGlobal(MouseComponent.class); Mouse.poll(); for (int i = 0; i < Mouse.getButtonCount(); i++) { mouse.pressed[i] = false; mouse.pressed[i] = false; mouse.down[i] = Mouse.isButtonDown(i); mouse.dx = 0; mouse.dy = 0; } while (Mouse.next()) { int btn = Mouse.getEventButton(); if (btn != -1) { mouse.pressed[btn] = Mouse.getEventButtonState(); mouse.released[btn] = !mouse.pressed[btn]; } else { mouse.dx += Mouse.getEventDX(); mouse.dy += Mouse.getEventDY(); } mouse.x = Mouse.getEventX(); mouse.y = Mouse.getEventY(); } mouse.nx = ((float) mouse.x / (float) window.width) * 2.0f - 1.0f; mouse.ny = ((float) mouse.y / (float) window.height) * 2.0f - 1.0f; Vec3[] mp = MouseUtils.mouseToWorld(window, engine.getGlobal(Camera.class), mouse); mouse.near = mp[0]; mouse.far = mp[1]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (Map m : objects.values()) { m.clear(); } // calculate the world matrix of each renderable, // and add them to their respective "shader buckets" for (RenderNode node : engine.getNodeList(RenderNode.class)) { ID<Entity> id = node.getEntity().getId(); worlds.put(id, StateUtils.getMatrix(node.state)); Program program = resourceManager.getProgram(node.renderable.shader); Map<ID<Entity>, RenderNode> renderables = objects.get(program); if (renderables == null) { renderables = new HashMap<>(); objects.put(program, renderables); } renderables.put(id, node); } for (ViewportNode vpnode : engine.getNodeList(ViewportNode.class)) { Camera camera = vpnode.camera; glViewport( (int) (window.width * vpnode.viewport.x), (int) (window.height * vpnode.viewport.y), (int) (window.width * vpnode.viewport.width), (int) (window.height * vpnode.viewport.height)); // for each shader, draw each object that uses that shader for (Map.Entry<Program, Map<ID<Entity>, RenderNode>> e : objects.entrySet()) { Program program = e.getKey(); program.use(); program.setView(camera.viewMatrix); program.setProjection(camera.projection); program.setSun(engine.getGlobal(Sun.class).location); program.setEye(camera.eye); for (Map.Entry<ID<Entity>, RenderNode> e2 : e.getValue().entrySet()) { RenderNode node = e2.getValue(); program.setWorld(worlds.get(e2.getKey())); program.setColour(node.renderable.colour); program.setOpacity(node.renderable.opacity); Mesh mesh = resourceManager.getMesh(node.mesh); mesh.draw(); } } glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_CULL_FACE); Program program = resourceManager.getProgram("passthrough"); program.use(); program.setView(camera.viewMatrix); program.setProjection(camera.projection); for (BBoxNode node : engine.getNodeList(BBoxNode.class)) { program.setWorld(node.bbox.getMatrix()); Vec3 e = node.bbox.getExtents(); glBegin(GL_QUADS); { glColor3f(1, 0, 1); glVertex3f(e.getX(), e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), -e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), -e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), -e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), -e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), -e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), -e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(e.getX(), e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), -e.getY(), e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), -e.getY(), -e.getZ()); glColor3f(1, 0, 1); glVertex3f(-e.getX(), e.getY(), -e.getZ()); } glEnd(); } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); } Display.update(); }
void mainLoop() { try { graphics.setupDisplay(); } catch (LWJGLException e) { throw new GdxRuntimeException(e); } listener.create(); listener.resize(graphics.getWidth(), graphics.getHeight()); graphics.resize = false; int lastWidth = graphics.getWidth(); int lastHeight = graphics.getHeight(); graphics.lastTime = System.nanoTime(); while (running) { Display.processMessages(); if (Display.isCloseRequested()) { exit(); } boolean shouldRender = false; synchronized (runnables) { executedRunnables.clear(); executedRunnables.addAll(runnables); runnables.clear(); for (int i = 0; i < executedRunnables.size(); i++) { shouldRender = true; try { executedRunnables.get(i).run(); } catch (Throwable t) { t.printStackTrace(); } } } input.update(); shouldRender |= graphics.shouldRender(); if (graphics.canvas != null) { int width = graphics.canvas.getWidth(); int height = graphics.canvas.getHeight(); if (lastWidth != width || lastHeight != height) { lastWidth = width; lastHeight = height; Gdx.gl.glViewport(0, 0, lastWidth, lastHeight); listener.resize(lastWidth, lastHeight); shouldRender = true; } } else { graphics.config.x = Display.getX(); graphics.config.y = Display.getY(); if (graphics.resize || Display.wasResized() || Display.getWidth() != graphics.config.width || Display.getHeight() != graphics.config.height) { graphics.resize = false; Gdx.gl.glViewport(0, 0, Display.getWidth(), Display.getHeight()); graphics.config.width = Display.getWidth(); graphics.config.height = Display.getHeight(); if (listener != null) listener.resize(Display.getWidth(), Display.getHeight()); graphics.requestRendering(); } } input.processEvents(); audio.update(); if (shouldRender) { graphics.updateTime(); listener.render(); Display.update(); if (graphics.vsync && graphics.config.useCPUSynch) { Display.sync(60); } } else { // Effectively sleeps for a little while so we don't spend all available // cpu power in an essentially empty loop. Display.sync(60); } } listener.pause(); listener.dispose(); Display.destroy(); audio.dispose(); if (graphics.config.forceExit) System.exit(-1); }
@Override public void run() { double delta = 0; long previousTime = System.nanoTime(); long timer = System.currentTimeMillis(); int ups = 0; double nanoUpdates = 1000000000.0 / 30.0; GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glShadeModel(GL11.GL_SMOOTH); GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glDisable(GL11.GL_LIGHTING); GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F); GL11.glClearDepth(1); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); setupDisplay(); boolean doResize = false; while (!Display.isCloseRequested()) { if (Display.wasResized() && doResize) { setupDisplay(); } doResize = true; long currentTime = System.nanoTime(); double currentTickDelta = (currentTime - previousTime) / nanoUpdates; delta += currentTickDelta; frameDelta = (frameDelta + currentTickDelta) % 1.0; previousTime = currentTime; while (delta >= 1) { update(); renderHandler.update(); delta--; ups++; } GL11.glClear(GL11.GL_COLOR_BUFFER_BIT); GL11.glPushMatrix(); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); renderHandler.render(); fps++; if (System.currentTimeMillis() - timer > 1000) { int bytesPerSecond = 0; int packetsPerSecond = 0; if (networkManager != null) { bytesPerSecond = networkManager.bytesPerSecond; packetsPerSecond = networkManager.packetsPerSecond; networkManager.bytesPerSecond = 0; networkManager.packetsPerSecond = 0; } Display.setTitle( "Slyther - FPS: " + fps + " - UPS: " + ups + " - BPS: " + bytesPerSecond + " - PPS: " + packetsPerSecond); fps = 0; timer += 1000; ups = 0; } GL11.glPopMatrix(); Display.sync(60); Display.update(); } if (networkManager != null && networkManager.isOpen()) { networkManager.closeConnection(ClientNetworkManager.SHUTDOWN_CODE, ""); } try { ConfigHandler.INSTANCE.saveConfig(CONFIGURATION_FILE, configuration); } catch (IOException e) { Log.error("Failed to save config"); Log.catching(e); } Display.destroy(); }