Package net.krazyweb.opengl

Source Code of net.krazyweb.opengl.OpenGL

package net.krazyweb.opengl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.HashMap;

import net.krazyweb.renderer.Color;
import net.krazyweb.renderer.Renderer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.TextureLoader;

public class OpenGL implements Renderer {
 
  private static final int SIZE_OF_FLOAT = 4;
 
  private Color clearColor = Color.WHITE;
 
  private HashMap<Integer, OpenGLMesh> meshes = new HashMap<Integer, OpenGLMesh>();
  private OpenGLMesh currentMesh;

  private HashMap<Integer, OpenGLFBO> fbos = new HashMap<Integer, OpenGLFBO>();
  private OpenGLFBO currentFBO;
 
  private int currentShader;
  private int meshCount = 0;
  private int fboCount = 0;
 
  private int activeTextureUnit = -1;
 
  private int width, height;
 
  private int frames = 0;
  private long lastFPS = 0;
 
  private ArrayList<Float> vertexList;
  private ArrayList<Integer> indexList;
 
  private ArrayList<Float> colorList;
  private ArrayList<Float> textureList;
 
  @Override
  public void setClearColor(Color color) {
    clearColor = color;
    GL11.glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
  }
 
  @Override
  public void createContext(int width, int height) {
   
    try {
     
      Display.setDisplayMode(new DisplayMode(width, height));
      Display.create(new PixelFormat(4, 8, 0));
 
      GL11.glViewport(0, 0, width, height);
      GL11.glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
      GL11.glClearDepth(1.0f);
      GL11.glEnable(GL11.GL_DEPTH_TEST);
      GL11.glDepthFunc(GL11.GL_LEQUAL);
      GL11.glEnable(GL11.GL_CULL_FACE);
     
      lastFPS = (System.nanoTime() / 1000000);
     
      this.width = width;
      this.height = height;
     
    } catch (LWJGLException e) {
      System.err.println("Could not create OpenGL context!");
      e.printStackTrace();
    }
   
    activeTextureUnit = GL13.GL_TEXTURE0;
   
  }
 
  @Override
  public void update() {
   
    Display.update();
   
    if ((System.nanoTime() / 1000000) - lastFPS > 1000) {
      System.out.println("FPS: " + frames);
      frames = 0; //reset the FPS counter
      lastFPS += 1000; //add one second
    }
   
    frames++;
   
  }
 
  @Override
  public void syncFrames(int frameRate) {
    Display.sync(frameRate);
  }

  @Override
  public boolean isClosed() {
    return Display.isCloseRequested();
  }

  @Override
  public void destroy() {
    Display.destroy();
  }

  @Override
  public int beginMesh() {
   
    meshCount++;
   
    currentMesh = new OpenGLMesh();
    meshes.put(meshCount, currentMesh);
   
    vertexList = new ArrayList<Float>();
    indexList = new ArrayList<Integer>();
    colorList = new ArrayList<Float>();
    textureList = new ArrayList<Float>();
   
    return meshCount;
   
  }

  @Override
  public int addVertexToMesh(Vector3f point) {
    return addVertexToMesh(point, new Vector3f(0.0f, 0.0f, 0.0f), new Vector2f(0.0f, 0.0f), Color.WHITE);
  }
 
  @Override
  public int addVertexToMesh(Vector3f point, Color color) {
    return addVertexToMesh(point, new Vector3f(0.0f, 0.0f, 0.0f), new Vector2f(0.0f, 0.0f), color);
  }

  @Override
  public int addVertexToMesh(Vector3f point,  Vector2f texture) {
    return addVertexToMesh(point, new Vector3f(0.0f, 0.0f, 0.0f), texture, Color.WHITE);
  }

  @Override
  public int addVertexToMesh(Vector3f point, Vector3f normal, Color color) {
    return addVertexToMesh(point, normal, new Vector2f(0.0f, 0.0f), color);
  }

  @Override
  public int addVertexToMesh(Vector3f point, Vector2f texture, Color color) {
    return addVertexToMesh(point, new Vector3f(0.0f, 0.0f, 0.0f), texture, color);
  }

  @Override
  public int addVertexToMesh(Vector3f point, Vector3f normal, Vector2f texture, Color color) {

    colorList.add(color.r);
    colorList.add(color.g);
    colorList.add(color.b);
    colorList.add(color.a);
   
    textureList.add(texture.x);
    textureList.add(texture.y);
   
    vertexList.add(point.x);
    vertexList.add(point.y);
    vertexList.add(point.z);
   
    vertexList.add(normal.x);
    vertexList.add(normal.y);
    vertexList.add(normal.z);
   
    return (vertexList.size() / 6) - 1;
   
  }

  @Override
  public void addTriangleToMesh(int vertex1, int vertex2, int vertex3) {

    indexList.add(vertex1);
    indexList.add(vertex2);
    indexList.add(vertex3);
   
  }

  @Override
  public void finishMesh() {

    FloatBuffer vertices;
    IntBuffer indices;
    FloatBuffer colors;
    FloatBuffer textures;
   
    float[] vertexArray = new float[vertexList.size()];

    for (int i = 0; i < vertexList.size(); i++) {
      Float f = vertexList.get(i);
      vertexArray[i] = (f != null ? f : Float.NaN);
    }

    vertices = BufferUtils.createFloatBuffer(vertexArray.length);
    vertices.put(vertexArray);
    vertices.flip();

    int[] indexArray = new int[indexList.size()];

    for (int i = 0; i < indexList.size(); i++) {
      Integer f = indexList.get(i);
      indexArray[i] = (f != null ? f : 0);
    }

    indices = BufferUtils.createIntBuffer(indexArray.length);
    indices.put(indexArray);
    indices.flip();
   
    currentMesh.numberOfIndices = indices.capacity();

    float[] textureArray = new float[textureList.size()];

    for (int i = 0; i < textureList.size(); i++) {
      Float f = textureList.get(i);
      textureArray[i] = f != null ? f : Float.NaN;
    }

    textures = BufferUtils.createFloatBuffer(textureArray.length);
    textures.put(textureArray);
    textures.flip();

    float[] colorArray = new float[colorList.size()];

    for (int i = 0; i < colorList.size(); i++) {
      Float f = colorList.get(i);
      colorArray[i] = (f != null ? f : Float.NaN);
    }

    colors = BufferUtils.createFloatBuffer(colorArray.length);
    colors.put(colorArray);
    colors.flip();
   
    int[] temp = new int[4];
    temp[0] = GL15.glGenBuffers();
    temp[1] = GL15.glGenBuffers();
    temp[2] = GL15.glGenBuffers();
    temp[3] = GL15.glGenBuffers();
   
    currentMesh.VAO = GL30.glGenVertexArrays();
    GL30.glBindVertexArray(currentMesh.VAO);
   
    currentMesh.VBOVertices = temp[0];
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, currentMesh.VBOVertices);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
    GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 6 * SIZE_OF_FLOAT, 0);
    GL20.glVertexAttribPointer(3, 3, GL11.GL_FLOAT, false, 6 * SIZE_OF_FLOAT, 3 * SIZE_OF_FLOAT);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    currentMesh.VBOIndices = temp[1];
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, currentMesh.VBOIndices);
    GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

    currentMesh.VBOColors = temp[2];
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, currentMesh.VBOColors);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colors, GL15.GL_STATIC_DRAW);
    GL20.glVertexAttribPointer(1, 4, GL11.GL_FLOAT, false, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    currentMesh.VBOTextures = temp[3];
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, currentMesh.VBOTextures);
    GL15.glBufferData(GL15.GL_ARRAY_BUFFER, textures, GL15.GL_STATIC_DRAW);
    GL20.glVertexAttribPointer(2, 2, GL11.GL_FLOAT, false, 0, 0);
    GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
   
    GL30.glBindVertexArray(0);
   
    /*currentMesh.vertexList = vertexList;
    currentMesh.textureList = textureList;
    currentMesh.indexList = indexList;
    currentMesh.colorList = colorList;*/

    vertexList = null;
    indexList = null;
    colorList = null;
    textureList = null;
   
    currentMesh = null;
   
  }
 
  @Override
  public void deleteMeshBuffers() {

    GL30.glDeleteVertexArrays(currentMesh.VAO);
   
    GL15.glDeleteBuffers(currentMesh.VBOVertices);
    GL15.glDeleteBuffers(currentMesh.VBOIndices);
    GL15.glDeleteBuffers(currentMesh.VBOColors);
    GL15.glDeleteBuffers(currentMesh.VBOTextures);
   
    currentMesh.numberOfIndices = 0;
   
  }
 
  @Override
  public void deleteMesh(int meshID) {
   
    if (!meshes.containsKey(meshID)) {
      return;
    }
   
    currentMesh = meshes.get(meshID);

    GL30.glDeleteVertexArrays(currentMesh.VAO);
   
    GL15.glDeleteBuffers(currentMesh.VBOVertices);
    GL15.glDeleteBuffers(currentMesh.VBOIndices);
    GL15.glDeleteBuffers(currentMesh.VBOColors);
    GL15.glDeleteBuffers(currentMesh.VBOTextures);
   
    currentMesh.numberOfIndices = 0;
   
    meshes.remove(meshID);
   
    currentMesh = null;
   
  }

  @Override
  public void batchMesh(int receivingMesh, int meshToBatch, Vector3f batchTranslation, boolean deleteMeshToBatch) {
   
    OpenGLMesh target = meshes.get(receivingMesh);
    OpenGLMesh toCombine = meshes.get(meshToBatch);
   
    int high = 0;
   
    for (int x : target.indexList) {
      if (x > high) {
        high = x;
      }
    }
   
    high += 1;
   
    currentMesh = target;
   
    deleteMeshBuffers();
   
    for (int i = 0; i < toCombine.indexList.size(); i++) {
      toCombine.indexList.set(i, toCombine.indexList.get(i) + high);
    }

    for (int i = 0; i < toCombine.vertexList.size(); i++) {
     
      if (i % 3 == 0) {
        toCombine.vertexList.set(i, toCombine.vertexList.get(i) + batchTranslation.x);
      } else if (i % 3 == 1) {
        toCombine.vertexList.set(i, toCombine.vertexList.get(i) + batchTranslation.y);
      } else {
        toCombine.vertexList.set(i, toCombine.vertexList.get(i) + batchTranslation.z);
      }
     
    }

    target.vertexList.addAll(toCombine.vertexList);
    target.indexList.addAll(toCombine.indexList);
    target.colorList.addAll(toCombine.colorList);
    target.textureList.addAll(toCombine.textureList);
   
    vertexList = target.vertexList;
    indexList = target.indexList;
    colorList = target.colorList;
    textureList = target.textureList;
   
    finishMesh();
   
    if (deleteMeshToBatch) {
     
      currentMesh = toCombine;
      deleteMeshBuffers();
      meshes.remove(toCombine);
      currentMesh = null;
     
    }
   
  }

  @Override
  public void drawMesh(int meshID) {
     
    OpenGLMesh mesh = meshes.get(meshID);
   
    GL30.glBindVertexArray(mesh.VAO);
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);
    GL20.glEnableVertexAttribArray(2);
    GL20.glEnableVertexAttribArray(3);

    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, mesh.VBOIndices);
   
    GL11.glDrawElements(GL11.GL_TRIANGLES, mesh.numberOfIndices, GL11.GL_UNSIGNED_INT, 0);
   
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL20.glDisableVertexAttribArray(2);
    GL20.glDisableVertexAttribArray(3);
    GL30.glBindVertexArray(0);
   
  }

  @Override
  public int getQuad(float x, float y, float z, float width, float height) {
   
    int mesh = beginMesh();
   
    int v1 = addVertexToMesh(new Vector3f(x, y, z), new Vector2f(0.0f, 0.0f));
    int v2 = addVertexToMesh(new Vector3f(x + width, y, z), new Vector2f(1.0f, 0.0f));
    int v3 = addVertexToMesh(new Vector3f(x + width, y + height, z), new Vector2f(1.0f, 1.0f));
    int v4 = addVertexToMesh(new Vector3f(x, y + height, z), new Vector2f(0.0f, 1.0f));
   
    addTriangleToMesh(v1, v2, v3);
    addTriangleToMesh(v1, v3, v4);
   
    finishMesh();
   
    return mesh;
   
  }

  @Override
  public void setMatrix(Matrix4f matrix) {
    FloatBuffer matrix44Buffer = BufferUtils.createFloatBuffer(16);
    matrix.store(matrix44Buffer); matrix44Buffer.flip();
    GL20.glUniformMatrix4(GL20.glGetUniformLocation(currentShader, "mvpMatrix"), false, matrix44Buffer);
  }

  @Override
  public int createShader(String vertexShader, String fragmentShader) {
   
    int vertShader = 0, fragShader = 0;

    int shaderID = GL20.glCreateProgram();
   
    boolean useShader = true;
   
    if (shaderID != 0) {
      vertShader = loadShader(vertexShader, GL20.GL_VERTEX_SHADER);
      fragShader = loadShader(fragmentShader, GL20.GL_FRAGMENT_SHADER);
    } else useShader = false;

    if (vertShader != 0 && fragShader != 0) {
      GL20.glAttachShader(shaderID, vertShader);
      GL20.glAttachShader(shaderID, fragShader);
      GL20.glLinkProgram(shaderID);
      GL20.glBindAttribLocation(shaderID, 0, "Position");
      GL20.glBindAttribLocation(shaderID, 1, "Color");
      GL20.glValidateProgram(shaderID);
    } else useShader = false;
   
    if (!useShader) {
      System.exit(-1);
    }
   
    return shaderID;
   
  }
 
  private int loadShader(String filename, int type) {
   
    String shaderCode = "";
    String line;
   
    try {
   
      BufferedReader reader = new BufferedReader(new InputStreamReader(OpenGL.class.getClassLoader().getResourceAsStream(filename)));
   
      while ((line = reader.readLine()) != null) {
        shaderCode += line + "\n";
      }
     
    } catch (IOException e) {
      System.out.println("Failed reading shader file: " + filename);
      return 0;
    }
   
    int shaderID = GL20.glCreateShader(type);
    GL20.glShaderSource(shaderID, shaderCode);
    GL20.glCompileShader(shaderID);
   
    if (GL20.glGetShader(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE){
     
      System.out.println("Shader [" + filename + "] not compiled!");
     
      int maxLength =  GL20.glGetShader(shaderID, GL20.GL_INFO_LOG_LENGTH);
     
      System.out.println(GL20.glGetShaderInfoLog(shaderID, maxLength));
     
      shaderID = 0;
     
    }
   
    return shaderID;
   
  }

  @Override
  public void useShader(int shader) {
    GL20.glUseProgram(shader);
    currentShader = shader;
  }

  @Override
  public void setShaderProperty(String property, Color color) {
    GL20.glUniform4f(GL20.glGetUniformLocation(currentShader, property), color.r, color.g, color.b, color.a);
  }

  @Override
  public void setShaderProperty(String property, int value) {
    int location = GL20.glGetUniformLocation(currentShader, property);
    GL20.glUniform1i(location, value);
  }

  @Override
  public void setShaderProperty(String property, float value) {
    int location = GL20.glGetUniformLocation(currentShader, property);
    GL20.glUniform1f(location, value);
  }

  @Override
  public void setShaderProperty(String property, Vector2f value) {
    int location = GL20.glGetUniformLocation(currentShader, property);
    GL20.glUniform2f(location, value.x, value.y);
  }

  @Override
  public void clear() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
  }

  @Override
  public int loadTexture(String texture, TEXTURE_FORMAT format, TEXTURE_HINT hint) {
    try {
      if (hint == TEXTURE_HINT.BILINEAR) {
        return TextureLoader.getTexture(format.type, OpenGL.class.getClassLoader().getResourceAsStream(texture), true).getTextureID();
      } else {
        return TextureLoader.getTexture(format.type, OpenGL.class.getClassLoader().getResourceAsStream(texture), true, GL11.GL_NEAREST).getTextureID();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return 0;
  }

  @Override
  public void bindTexture(int texture, int textureUnit) {
    if (activeTextureUnit != GL13.GL_TEXTURE0 + textureUnit) {
      GL13.glActiveTexture((activeTextureUnit = GL13.GL_TEXTURE0 + textureUnit));
    }
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
  }

  @Override
  public void unbindTexture(int textureUnit) {
    GL13.glActiveTexture(GL13.GL_TEXTURE0 + textureUnit);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  }

  @Override
  public void enableBlending(BLEND_MODE blendMode) {
   
    GL11.glEnable(GL11.GL_BLEND);
   
    switch (blendMode) {
      case ADDITIVE:
        GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE);
        break;
      case TRANSPARENCY:
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        break;
    }
   
  }

  @Override
  public void disableBlending() {
    GL11.glDisable(GL11.GL_BLEND);
  }

  @Override
  public int beginFBO(int width, int height, int numberOfTextures) {
   
    fboCount++;
   
    currentFBO = new OpenGLFBO(width, height, numberOfTextures);
    fbos.put(fboCount, currentFBO);
   
    return fboCount;
   
  }

  @Override
  public void addTextureToFBO(TEXTURE_TYPE type) {
    currentFBO.addTexture(type);
  }

  @Override
  public void finishFBO() {
   
    currentFBO.finalize();
   
    currentFBO = null;
   
  }

  @Override
  public void enableFBO(int fbo) {
    fbos.get(fbo).enable();
  }

  @Override
  public void disableFBO() {
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    GL11.glViewport(0, 0, width, height);
  }
 
  @Override
  public int getFBOTexture(int fbo, int texture) {
    return fbos.get(fbo).textures[texture];
  }

}
TOP

Related Classes of net.krazyweb.opengl.OpenGL

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.