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()
  }
示例#2
0
 /**
  * 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();
 }
示例#3
0
  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();
    }
  }
示例#4
0
/**
 * 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);
  }
}
示例#5
0
  @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();
  }
示例#6
0
  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);
  }
示例#7
0
  @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();
  }