Skip to content

Instantly share code, notes, and snippets.

@LasseSkogland
Last active February 18, 2017 15:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LasseSkogland/010bda511f15aab3cac724740c9380d0 to your computer and use it in GitHub Desktop.
Save LasseSkogland/010bda511f15aab3cac724740c9380d0 to your computer and use it in GitHub Desktop.
Java-Gaming.org Plez Halp
package game.engine;
import game.engine.gl.Renderer;
import game.engine.input.Input;
import game.engine.util.Logger;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
public abstract class Game {
private long windowHandle;
private boolean exitRequested;
private static double timeLastFrame;
private static double timeCurrentFrame;
private static int width;
private static int height;
protected void initialize() {
Logger.info("Engine", "Starting client");
GLFWErrorCallback.createPrint(System.err).set();
if (!glfwInit()) {
Logger.error("Engine", "Failed to initialize GLFW subsystem");
Logger.info("Engine", "Shutting down client");
System.exit(1);
}
}
protected void createWindow(String title, int width, int height) {
Game.width = width;
Game.height = height;
Logger.info("Engine", "Setting up window and callbacks");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_SAMPLES, 8);
glfwWindowHint(GLFW_RED_BITS, 8);
glfwWindowHint(GLFW_GREEN_BITS, 8);
glfwWindowHint(GLFW_BLUE_BITS, 8);
glfwWindowHint(GLFW_ALPHA_BITS, 8);
glfwWindowHint(GLFW_DEPTH_BITS, 8);
glfwWindowHint(GLFW_STENCIL_BITS, 8);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
Logger.info("Engine", "Creating window");
windowHandle = glfwCreateWindow(width, height, title, 0, 0);
if (windowHandle == 0) {
Logger.error("Engine", "Failed to create window");
Logger.info("Engine", "Shutting down client");
return;
}
glfwMakeContextCurrent(windowHandle);
GL.createCapabilities();
glViewport(0,0, width, height);
//glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_LEQUAL);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
glClearColor(0, 0, 0, 1);
glfwSwapInterval(1);
Renderer.setupContext();
}
protected void resizeWindow(int width, int height) {
Game.width = width;
Game.height = height;
glfwSetWindowSize(windowHandle, width, height);
}
protected void setFullscreen(boolean state) {
glfwSetWindowMonitor(windowHandle, state ? glfwGetPrimaryMonitor() : null, 0, 0, width, height, GLFW_DONT_CARE);
}
public void setClearColor(float r, float g, float b) {
glClearColor(r, g, b, 1f);
}
public void setClearColor(float r, float g, float b, float a) {
glClearColor(r, g, b, a);
}
protected void enterGameLoop() {
Logger.info("Engine", "Initializing input");
Input.initialize(windowHandle);
Logger.info("Engine", "Entering game loop");
exitRequested = false;
glClearColor(0, 0, 0, 1);
timeLastFrame = glfwGetTime();
glfwShowWindow(windowHandle);
do {
timeCurrentFrame = glfwGetTime();
glfwPollEvents();
Input.update();
if (glfwWindowShouldClose(windowHandle)) exitRequested = true;
update();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render();
glfwSwapBuffers(windowHandle);
timeLastFrame = timeCurrentFrame;
} while (!exitRequested);
Logger.info("Engine", "Shutting down client");
glfwFreeCallbacks(windowHandle);
glfwTerminate();
Logger.info("Engine", "Client shut down");
}
public boolean isExitRequested() {
return exitRequested;
}
protected void exit() {
exitRequested = true;
}
/**
* Returns time since the beginning of the last frame
*/
public static double getLastFrameDeltaTime() {
return glfwGetTime() - timeLastFrame;
}
/**
* Returns time since the beginning of this frame
*/
public static double getCurrentFrameDeltaTime() {
return glfwGetTime() - timeCurrentFrame;
}
public static int getWidth() {
return width;
}
public static int getHeight() {
return height;
}
public static int getCenterX() {
return width / 2;
}
public static int getCenterY() {
return height / 2;
}
public abstract void update();
public abstract void render();
}
package game.engine.util.x3d;
import game.Entity;
import game.engine.util.Logger;
import org.lwjgl.system.MemoryStack;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
public class Model extends Entity {
private boolean isColored = false, isTextured = false;
private float[] color, textureCoords, vertices;
private short[] triangles;
private int vertexCount = 0;
private int indexCount = 0;
private int textureID = 0;
private int vertexArrayObject, indicesVBO;
public void setVertices(float[] vertices) {
vertexCount = vertices.length;
this.vertices = vertices;
}
public void setTriangles(short[] triangles) {
indexCount = triangles.length;
this.triangles = triangles;
}
public void setColor(float[] colors) {
isColored = true;
color = colors;
}
public void setTexture(int texture) {
isTextured = true;
textureID = texture;
}
public void setTextureCoords(float[] textureCoords) {
this.textureCoords = textureCoords;
}
public int getTexture() {
return textureID;
}
public int getVertexCount() {
return vertexCount;
}
public int getIndexCount() {
return indexCount;
}
public boolean isColored() {
return isColored;
}
public boolean isTextured() {
return isTextured;
}
public Model upload() {
Logger.info("Engine", "Uploading model into graphics memory");
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer vert = stack.mallocFloat(vertices.length);
vert.put(vertices).flip();
FloatBuffer col = stack.mallocFloat(color.length);
col.put(color).flip();
ShortBuffer indexBuffer = stack.mallocShort(triangles.length);
indexBuffer.put(triangles).flip();
vertexArrayObject = glGenVertexArrays();
glBindVertexArray(vertexArrayObject);
int verticesVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, verticesVBO);
glBufferData(GL_ARRAY_BUFFER, vert, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
int colorVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
glBufferData(GL_ARRAY_BUFFER, col, GL_STATIC_DRAW);
glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
indicesVBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
return this;
}
public int getIndexVBO() {
return indicesVBO;
}
public int getVAO() {
return vertexArrayObject;
}
}
package game.engine.gl;
import game.engine.util.Logger;
import game.engine.util.Util;
import game.engine.util.x3d.Model;
import org.joml.Matrix4f;
import org.lwjgl.system.MemoryStack;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
public class Renderer {
private static int shaderProgram;
private static int vertexArrayObject;
public static Matrix4f matrixModel;
public static Matrix4f matrixView;
public static Matrix4f matrixOrthographic;
public static Matrix4f matrixPerspective;
private static int uniformModel;
private static int uniformView;
private static int uniformProjection;
public static void setupContext() {
String vertex = "", fragment = "";
Logger.info("Engine", "Loading Shader: /resources/vertex.glsl");
try (BufferedReader txtReader = new BufferedReader(new InputStreamReader(Renderer.class.getResourceAsStream("/resources/vertex.glsl")))) {
vertex = txtReader.lines().reduce("", (s, p) -> s + "\n" + p);
} catch (Exception e) {
}
Logger.info("Engine", "Loading Shader: /resources/fragment.glsl");
try (BufferedReader txtReader = new BufferedReader(new InputStreamReader(Renderer.class.getResourceAsStream("/resources/fragment.glsl")))) {
fragment = txtReader.lines().reduce("", (s, p) -> s + "\n" + p);
} catch (Exception e) {
}
Logger.info("Engine", "Compiling Vertex Shader");
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, vertex);
glCompileShader(vertexShader);
if (Util.checkShaderError(vertexShader)) System.exit(1);
Logger.info("Engine", "Compiling Fragment Shader");
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, fragment);
glCompileShader(fragmentShader);
if (Util.checkShaderError(fragmentShader)) System.exit(1);
Logger.info("Engine", "Linking Shader Program");
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "fragColor");
glBindAttribLocation(shaderProgram, 0, "position");
glBindAttribLocation(shaderProgram, 1, "color");
glLinkProgram(shaderProgram);
if (Util.checkShaderProgramError(shaderProgram)) System.exit(1);
glUseProgram(shaderProgram);
Logger.info("Engine", "Setting up shader values");
uniformModel = glGetUniformLocation(shaderProgram, "model");
uniformView = glGetUniformLocation(Renderer.shaderProgram, "view");
uniformProjection = glGetUniformLocation(Renderer.shaderProgram, "projection");
Logger.info("Engine", "Creating Matrices");
matrixModel = new Matrix4f();
matrixView = new Matrix4f();
matrixOrthographic = new Matrix4f().ortho(-1f, 1f, 1f, -1f, -1f, 1f);
matrixPerspective = new Matrix4f().perspective(75, 16f / 9f, -1f, 1024f);
Logger.info("Engine", "Uploading Matrices");
uploadMatrix(uniformModel, matrixModel);
uploadMatrix(uniformView, matrixView);
uploadMatrix(uniformProjection, matrixOrthographic);
}
public static void uploadMatrix(int location, Matrix4f matrix) {
try (MemoryStack stack = MemoryStack.stackPush()) {
FloatBuffer buffer = stack.mallocFloat(16);
matrix.get(buffer).flip();
glUniformMatrix4fv(location, false, buffer);
}
}
public static void renderModel(Model model) {
glUseProgram(shaderProgram);
glBindVertexArray(model.getVAO());
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.getIndexVBO());
glDrawElements(GL_TRIANGLES, model.getIndexCount(), GL_UNSIGNED_SHORT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindVertexArray(0);
glUseProgram(0);
}
}
package game;
import game.engine.Game;
import game.engine.gl.Renderer;
import game.engine.input.Input;
import game.engine.input.Input.Keyboard;
import game.engine.util.x3d.Model;
import game.engine.util.x3d.VoxelBuilder;
import org.joml.Vector3f;
import org.joml.Vector4f;
public class Test extends Game {
private Model model;
private Test(String[] args) {
initialize();
createWindow("Test", 800, 600);
VoxelBuilder.reset();
VoxelBuilder.addCube(new Vector3f(0,0,0), new Vector4f(1,1,1,1), 1f, VoxelBuilder.MASK_All);
model = VoxelBuilder.getModel().upload();//*/
enterGameLoop();
}
public void render() {
Renderer.renderModel(model);
}
public void update() {
if (Input.getKey(Keyboard.Escape)) exit();
}
public static void main(String[] args) {
System.setProperty("org.lwjgl.librarypath", String.format("%s/natives", System.getProperty("user.dir")));
new Test(args);
}
}
package game.engine.util;
import org.joml.Matrix4f;
import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import java.net.URL;
import java.nio.*;
import static org.lwjgl.glfw.GLFW.glfwGetTime;
import static org.lwjgl.opengl.GL11.GL_FALSE;
import static org.lwjgl.opengl.GL11.glGetError;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
public class Util {
public static FloatBuffer getBuffer(float[] buf) {
return (FloatBuffer) BufferUtils.createFloatBuffer(buf.length).put(buf).flip();
}
public static DoubleBuffer getBuffer(double[] buf) {
return (DoubleBuffer) BufferUtils.createDoubleBuffer(buf.length).put(buf).flip();
}
public static IntBuffer getBuffer(int[] buf) {
return (IntBuffer) BufferUtils.createIntBuffer(buf.length).put(buf).flip();
}
public static ShortBuffer getBuffer(short[] buf) {
return (ShortBuffer) BufferUtils.createShortBuffer(buf.length).put(buf).flip();
}
public static ByteBuffer getBuffer(byte[] buf) {
return (ByteBuffer) BufferUtils.createByteBuffer(buf.length).put(buf).flip();
}
public static LongBuffer getBuffer(long[] buf) {
return (LongBuffer) BufferUtils.createLongBuffer(buf.length).put(buf).flip();
}
public static CharBuffer getBuffer(char[] buf) {
return (CharBuffer) BufferUtils.createCharBuffer(buf.length).put(buf).flip();
}
public static PointerBuffer getPointerBuffer(long[] buf) {
return BufferUtils.createPointerBuffer(buf.length).put(buf).flip();
}
public static URL getResource(String name) {
return Util.class.getResource(name);
}
public static void printBuffer(Buffer b) {
while (b.remaining() > 0) {
if (b instanceof FloatBuffer) {
System.out.print(((FloatBuffer) b).get());
} else if (b instanceof DoubleBuffer) {
System.out.print(((DoubleBuffer) b).get());
} else if (b instanceof IntBuffer) {
System.out.print(((IntBuffer) b).get());
} else if (b instanceof ShortBuffer) {
System.out.print(((ShortBuffer) b).get());
} else if (b instanceof ByteBuffer) {
System.out.print(((ByteBuffer) b).get());
} else if (b instanceof LongBuffer) {
System.out.print(((LongBuffer) b).get());
}
System.out.print(" ");
}
System.out.println();
}
public static double getDistance(double x1, double y1, double x2, double y2) {
double x = x1 - x2;
double y = y1 - y2;
return Math.sqrt((x * x) + (y * y));
}
public static double stripDecimals(double d, int decimals) {
double dec = Math.pow(10.0, decimals);
return Math.round(d * dec) / dec;
}
public static boolean isPointWithin(int mx, int my, int x, int y, int w, int h) {
return (mx >= x && mx <= x + w) && (my >= y && my <= y + h);
}
public static double getTime() {
return glfwGetTime();
}
public static boolean checkShaderError(int shader) {
if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) {
if (glGetShaderi(shader, GL_INFO_LOG_LENGTH) > 1) {
String infoLog = glGetShaderInfoLog(shader, 1024);
Logger.error("Engine", "Failed to compile GLSL shader");
Logger.error("Engine", infoLog);
}
return true;
}
return false;
}
public static boolean checkShaderProgramError(int program) {
if (glGetProgrami(program, GL_LINK_STATUS) == GL_FALSE) {
if (glGetProgrami(program, GL_INFO_LOG_LENGTH) > 1) {
String infoLog = glGetProgramInfoLog(program, 1024);
Logger.error("Engine", "Failed to link GLSL shader program");
Logger.error("Engine", infoLog);
return true;
}
}
glValidateProgram(program);
int err;
if ((err = glGetError()) != GL_FALSE) {
Logger.error("Engine", "Shader Program Validation Failed with code; " + err);
return true;
}
return false;
}
}
package game.engine.util.x3d;
import org.joml.Vector3f;
import org.joml.Vector4f;
import java.util.ArrayList;
public class VoxelBuilder {
public static final int
MASK_Top = 1,
MASK_Bottom = 2,
MASK_Front = 4,
MASK_Back = 8,
MASK_Right = 16,
MASK_Left = 32,
MASK_All = 0xFF;
private static ArrayList<Vector3f> vertices = new ArrayList<>();
private static ArrayList<Integer> triangles = new ArrayList<>();
private static ArrayList<Vector4f> colors = new ArrayList<>();
private static int vertexCount = 0;
public static void reset() {
vertices.clear();
triangles.clear();
colors.clear();
}
public static Model getModel() {
float[] vertex = new float[vertexCount * 3];
float[] color = new float[colors.size() * 4];
short[] triangle = new short[triangles.size()];
int num = 0;
for (Vector3f v : vertices) {
vertex[num++] = v.x;
vertex[num++] = v.y;
vertex[num++] = v.z;
}
num = 0;
for (Vector4f c : colors) {
color[num++] = c.x;
color[num++] = c.y;
color[num++] = c.z;
color[num++] = c.w;
}
num = 0;
for (int t : triangles) {
triangle[num++] = (short) t;
}
Model m = new Model();
m.setVertices(vertex);
m.setTriangles(triangle);
m.setColor(color);
reset();
return m;
}
public static void addCube(Vector3f pos, Vector4f color, float size, int mask) {
pos.mul(size);
size /= 2;
if ((mask & MASK_Top) == MASK_Top) {
triangles.add(vertexCount);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z + size));
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z + size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
if ((mask & MASK_Bottom) == MASK_Bottom) {
triangles.add(vertexCount);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z - size));
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z + size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z + size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
if ((mask & MASK_Front) == MASK_Front) {
triangles.add(vertexCount);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z + size));
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z + size));
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z + size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z + size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
if ((mask & MASK_Back) == MASK_Back) {
triangles.add(vertexCount);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z - size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
if ((mask & MASK_Right) == MASK_Right) {
triangles.add(vertexCount);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y + size, pos.z + size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z - size));
vertices.add(new Vector3f(pos.x + size, pos.y, pos.z + size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
if ((mask & MASK_Left) == MASK_Left) {
triangles.add(vertexCount);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 1);
triangles.add(vertexCount + 2);
triangles.add(vertexCount + 3);
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z - size));
vertices.add(new Vector3f(pos.x - size, pos.y + size, pos.z + size));
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z - size));
vertices.add(new Vector3f(pos.x - size, pos.y, pos.z + size));
colors.add(color);
colors.add(color);
colors.add(color);
colors.add(color);
vertexCount += 4;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment