From 180aad05decc7eefa87e4e45d6747c48f40e5361 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Mon, 17 Apr 2023 12:12:01 -0400 Subject: save --- .../Minecraft/Render/ChunkRenderer.java | 99 ++++++++++++ .../tylermurphy/Minecraft/Render/Data/Display.java | 175 +++++++++++++++++++++ .../tylermurphy/Minecraft/Render/Data/Mesh.java | 82 ++++++++++ .../tylermurphy/Minecraft/Render/Data/Texture.java | 113 +++++++++++++ .../tylermurphy/Minecraft/Render/FontRenderer.java | 101 ++++++++++++ .../tylermurphy/Minecraft/Render/GuiRenderer.java | 57 +++++++ .../tylermurphy/Minecraft/Render/MainRenderer.java | 73 +++++++++ .../Minecraft/Render/Shaders/ChunkShader.java | 81 ++++++++++ .../Minecraft/Render/Shaders/FontShader.java | 40 +++++ .../Minecraft/Render/Shaders/GuiShader.java | 33 ++++ .../Minecraft/Render/Shaders/QuadShader.java | 37 +++++ .../Minecraft/Render/Util/FrustumCuller.java | 172 ++++++++++++++++++++ .../Minecraft/Render/Util/ShaderProgram.java | 126 +++++++++++++++ 13 files changed, 1189 insertions(+) create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java create mode 100755 src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java (limited to 'src/main/java/net/tylermurphy/Minecraft/Render') diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java new file mode 100755 index 0000000..29e079b --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/ChunkRenderer.java @@ -0,0 +1,99 @@ +package net.tylermurphy.Minecraft.Render; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; +import org.joml.Matrix4f; +import org.joml.Vector3f; + +import net.tylermurphy.Minecraft.Chunk.Chunk; +import net.tylermurphy.Minecraft.Render.Shaders.ChunkShader; +import net.tylermurphy.Minecraft.Render.Util.FrustumCuller; +import net.tylermurphy.Minecraft.Scene.World; +import net.tylermurphy.Minecraft.Scene.Objects.Renderable; +import net.tylermurphy.Minecraft.Util.Constants; +import net.tylermurphy.Minecraft.Util.Maths; + +public class ChunkRenderer { + + private final ChunkShader shader; + + public ChunkRenderer(Matrix4f projectionMatrix) { + this.shader = new ChunkShader(); + shader.start(); + shader.loadProjectionMatrix(projectionMatrix); + shader.connectTextureUnits(); + shader.stop(); + } + + public void render(Matrix4f projectionMatrix) { + FrustumCuller frustum = FrustumCuller.getFrustum(Maths.createViewMatrix(World.camera),projectionMatrix); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glEnable(GL11.GL_CULL_FACE); + GL11.glCullFace(GL11.GL_BACK); + GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); + GL11.glClearColor(Constants.RED, Constants.GREEN, Constants.BLUE, 1); + shader.start(); + if(World.player.isDead) + shader.loadTint(new Vector3f(100,0,0)); + else + shader.loadTint(new Vector3f(0,0,0)); + shader.loadViewMatrix(World.camera); + shader.loadPlayerPosition(World.player.getTransform().getPosition()); + shader.loadRenderDistance(World.renderDistance); + shader.loadSkyColor(new Vector3f(Constants.RED,Constants.GREEN,Constants.BLUE)); + attemptFrameChunkMeshLoad(); + boolean loadedMesh = false; + for (Chunk chunk : World.getChunks()) { + if(chunk==null) continue; + if(!frustum.cubeInFrustum( chunk.gridX*16 - World.world_origin.x(), 0, chunk.gridZ*16 - World.world_origin.z(), chunk.gridX*16 + 16 - World.world_origin.x() , 256, chunk.gridZ*16 + 16 - World.world_origin.z() )) { + continue; + } + if(!loadedMesh) loadedMesh = chunk.loadMesh(); + if(chunk.renderable() != null) + renderChunkMesh(chunk.renderable()); + if(chunk.transparentRenderable() != null) + renderChunkMesh(chunk.transparentRenderable()); + GL20.glDisableVertexAttribArray(0); + GL20.glDisableVertexAttribArray(1); + GL20.glDisableVertexAttribArray(2); + GL20.glDisableVertexAttribArray(3); + GL30.glBindVertexArray(0); + } + GL11.glDisable(GL11.GL_CULL_FACE); + shader.stop(); + } + + private void attemptFrameChunkMeshLoad(){ + + } + + private void renderChunkMesh(Renderable renderable) { + GL30.glBindVertexArray(renderable.getMesh().getID()); + GL20.glEnableVertexAttribArray(0); + GL20.glEnableVertexAttribArray(1); + GL20.glEnableVertexAttribArray(2); + GL20.glEnableVertexAttribArray(3); + GL13.glActiveTexture(GL13.GL_TEXTURE0); + GL11.glBindTexture(GL30.GL_TEXTURE_2D_ARRAY, renderable.getTexture()); + prepareInstance(renderable); + GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, renderable.getMesh().getVertexCount()); + } + + private void prepareInstance(Renderable renderable) { + Matrix4f transformationMatrix = Maths.createTransformationMatrix( + new Vector3f( + renderable.getTransform().getPosition().x - World.world_origin.x(), + renderable.getTransform().getPosition().y, + renderable.getTransform().getPosition().z - World.world_origin.z() + ), + renderable.getTransform().getRotation().x,renderable.getTransform().getRotation().y, renderable.getTransform().getRotation().z, renderable.getTransform().getScale()); + shader.loadTransformationMatrix(transformationMatrix); + } + + public void cleanUp() { + shader.cleanUp(); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java new file mode 100755 index 0000000..f866e97 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Display.java @@ -0,0 +1,175 @@ +package net.tylermurphy.Minecraft.Render.Data; + +import java.nio.DoubleBuffer; +import java.nio.IntBuffer; + +import org.joml.Vector2f; +import org.lwjgl.BufferUtils; +import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWFramebufferSizeCallback; +import org.lwjgl.glfw.GLFWImage; +import org.lwjgl.glfw.GLFWVidMode; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GL11; + +import net.tylermurphy.Minecraft.Input.Input; + +public class Display { + + private static long monitor; + private static long window; + + private static int width,height; + + private static double previousTime = GLFW.glfwGetTime(); + private static double passedTime = 0; + + private static boolean contextReady = false; + + public static boolean wasResized = false; + + public static boolean fullscreen = false; + private static int backup_xpos,backup_ypos,backup_xsize,backup_ysize; + + public static void create(int width, int height, String title, Texture icon) { + + Display.width = width; + Display.height = height; + + if(!GLFW.glfwInit()) { + System.err.println("Error: Coudnt init GLFW"); + System.exit(-1); + } + + Input.init(); + + GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE); + + monitor = GLFW.glfwGetPrimaryMonitor(); + window = GLFW.glfwCreateWindow(width, height, title, 0, 0); + + GLFW.glfwSetKeyCallback(window, Input.getKeyboardCallback()); + GLFW.glfwSetCursorPosCallback(window, Input.getMouseMoveCallback()); + GLFW.glfwSetMouseButtonCallback(window, Input.getMouseButtonCallback()); + GLFW.glfwSetCharCallback(window, Input.getCharCallback()); + + GLFWFramebufferSizeCallback framebufferCallback = new GLFWFramebufferSizeCallback() { + public void invoke(long window, int width, int height) { + if(contextReady) { + Display.width = width; + Display.height = height; + Display.wasResized = true; + GL11.glViewport(0, 0, width, height); + } + } + }; + + GLFW.glfwSetFramebufferSizeCallback(window, framebufferCallback); + + if(window==0) { + System.err.println("Error: Coudnt create window"); + System.exit(-1); + } + + if(icon != null) { + GLFWImage image = GLFWImage.malloc(); GLFWImage.Buffer imagebf = GLFWImage.malloc(1); + image.set(icon.getWidth(), icon.getHeight(), icon.getImage()); + imagebf.put(0, image); + GLFW.glfwSetWindowIcon(window, imagebf); + } + + GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor()); + assert videoMode != null; + GLFW.glfwSetWindowPos(window, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2); + GLFW.glfwMakeContextCurrent(window); + GLFW.glfwSwapInterval(0); + GLFW.glfwShowWindow(window); + + GL.createCapabilities(); + grabCursor(); + + contextReady = true; + + } + + public static boolean closed() { + return !GLFW.glfwWindowShouldClose(window); + } + + public static void update() { + double currentTime = GLFW.glfwGetTime(); + passedTime = currentTime - previousTime; + previousTime = currentTime; + GLFW.glfwPollEvents(); + } + + public static void swapBuffers() { + GLFW.glfwSwapBuffers(window); + } + + public static void close() { + Input.destroy(); + GLFW.glfwDestroyWindow(window); + GLFW.glfwTerminate(); + GL.destroy(); + } + + public static int getWidth() { + return width; + } + + public static int getHeight() { + return height; + } + + public static float getFrameTimeSeconds() { + return (float) passedTime; + } + + public static void grabCursor() { + GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); + } + + public static void releaseCursor() { + GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); + } + + public static Vector2f getCursorPos() { + DoubleBuffer xpos = BufferUtils.createDoubleBuffer(1); + DoubleBuffer ypos = BufferUtils.createDoubleBuffer(1); + GLFW.glfwGetCursorPos(window, xpos, ypos); + return new Vector2f((float)xpos.get(),(float)ypos.get()); + } + + public static void setFullScreen(boolean fullscreen) { + + if(Display.fullscreen == fullscreen) + return; + + Display.fullscreen = fullscreen; + + if(fullscreen) { + + IntBuffer xpos = BufferUtils.createIntBuffer(1); + IntBuffer ypos = BufferUtils.createIntBuffer(1); + GLFW.glfwGetWindowPos(window, xpos, ypos); + + IntBuffer xsize = BufferUtils.createIntBuffer(1); + IntBuffer ysize = BufferUtils.createIntBuffer(1); + GLFW.glfwGetWindowSize(window, xsize, ysize); + + backup_xpos = xpos.get(); + backup_ypos = ypos.get(); + backup_xsize = xsize.get(); + backup_ysize = ysize.get(); + + GLFWVidMode mode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor()); + + assert mode != null; + GLFW.glfwSetWindowMonitor(window, monitor, backup_xpos, backup_ypos, mode.width(), mode.height(), 0); + } else { + GLFW.glfwSetWindowMonitor(window, 0, backup_xpos, backup_ypos, backup_xsize, backup_ysize, 0); + } + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java new file mode 100755 index 0000000..093a58e --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Mesh.java @@ -0,0 +1,82 @@ +package net.tylermurphy.Minecraft.Render.Data; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; + +import java.io.Serializable; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; + +public class Mesh implements Serializable { + + private static final long serialVersionUID = -8137846451745511907L; + + public static List vaos = new ArrayList<>(); + public static List vbos = new ArrayList<>(); + + private final int id; + private final int vertexCount; + private int counter = 0; + + public Mesh(int vertexCount){ + this.id = GL30.glGenVertexArrays(); + vaos.add(id); + this.vertexCount = vertexCount; + GL30.glBindVertexArray(id); + } + + public Mesh store(float[] data, int coordinateSize){ + int id = GL15.glGenBuffers(); + vbos.add(id); + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, id); + FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length); + buffer.put(data); + buffer.flip(); + GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW); + GL20.glVertexAttribPointer(counter,coordinateSize, GL11.GL_FLOAT,false,0,0); + GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0); + counter++; + return this; + } + + public Mesh finish(){ + GL30.glBindVertexArray(0); + return this; + } + + public void delete(){ + IntBuffer amount = BufferUtils.createIntBuffer(1); + GL20.glGetIntegerv(GL20.GL_MAX_VERTEX_ATTRIBS, amount); + GL30.glBindVertexArray(id); + for (int i=0; i < amount.get(0); i++) { + IntBuffer vbo = BufferUtils.createIntBuffer(1); + GL20.glGetVertexAttribiv(i, GL20.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, vbo); + if(vbo.get(0) > 0) { + GL15.glDeleteBuffers(vbo.get(0)); + } + } + GL30.glDeleteVertexArrays(id); + } + + public int getID() { + return id; + } + public int getVertexCount() { + return vertexCount; + } + + public static void cleanUp() { + for(int vao:vaos){ + GL30.glDeleteVertexArrays(vao); + } + for(int vbo:vbos){ + GL30.glDeleteBuffers(vbo); + } + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java new file mode 100755 index 0000000..edfce82 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Data/Texture.java @@ -0,0 +1,113 @@ +package net.tylermurphy.Minecraft.Render.Data; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.lwjgl.opengl.GL30.*; + +import org.lwjgl.opengl.EXTTextureFilterAnisotropic; +import org.lwjgl.opengl.GL; +import org.lwjgl.stb.STBImage; +import org.lwjgl.system.MemoryStack; + +import net.tylermurphy.Minecraft.Util.Constants; + +public class Texture { + + public ByteBuffer getImage() { + return image; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + private ByteBuffer image; + private int width, height; + + private static List ids = new ArrayList(); + + Texture(int width, int heigh, ByteBuffer image) { + this.image = image; + this.height = heigh; + this.width = width; + } + + public static Texture loadRawTextureData(String fileName) { + ByteBuffer image; + int width, height; + try (MemoryStack stack = MemoryStack.stackPush()) { + IntBuffer comp = stack.mallocInt(1); + IntBuffer w = stack.mallocInt(1); + IntBuffer h = stack.mallocInt(1); + image = STBImage.stbi_load(Constants.PNG_LOCATION + fileName + ".png", w, h, comp, 4); + if (image == null) { + System.err.println("Couldn't load " + Constants.PNG_LOCATION + fileName + ".png"); + } + width = w.get(); + height = h.get(); + return new Texture(width, height, image); + } + } + + private static int loadImage(String fileName) { + int id = glGenTextures(); + Texture image = loadRawTextureData(fileName); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getImage()); + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -1); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glBindTexture(GL_TEXTURE_2D, 0); + ids.add(id); + return id; + } + + public static int loadTexture(String fileName) { + return loadImage(fileName); + } + + public static int loadFontAtlas(String fileName) { + return loadImage(fileName); + } + + public static int loadTexture2DArray(HashMap textures){ + int id = glGenTextures(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, id); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (GL.getCapabilities().GL_EXT_texture_filter_anisotropic) { + float maxAnisotropy = glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); + glTexParameterf(GL_TEXTURE_2D_ARRAY, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy); + } + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, textures.get(0).width, textures.get(0).height, textures.values().size(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (ByteBuffer) null); + for(Map.Entry entry : textures.entrySet()){ + glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, entry.getKey(), entry.getValue().width, entry.getValue().height, 1, GL_RGBA, GL_UNSIGNED_BYTE, entry.getValue().getImage()); + } + glGenerateMipmap(GL_TEXTURE_2D_ARRAY); + glBindTexture(GL_TEXTURE_2D_ARRAY, 0); + ids.add(id); + return id; + } + + public static void cleanUp(){ + for(int id:ids){ + glDeleteTextures(id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D_ARRAY, id); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java new file mode 100755 index 0000000..ed17824 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/FontRenderer.java @@ -0,0 +1,101 @@ +package net.tylermurphy.Minecraft.Render; + +import java.util.List; + +import java.util.Map; + +import net.tylermurphy.Minecraft.Render.Data.Mesh; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; +import org.joml.Matrix4f; +import org.joml.Vector2f; +import org.joml.Vector4f; + +import net.tylermurphy.Minecraft.Render.Shaders.FontShader; +import net.tylermurphy.Minecraft.Render.Shaders.QuadShader; +import net.tylermurphy.Minecraft.UI.UIFont; +import net.tylermurphy.Minecraft.UI.UIText; +import net.tylermurphy.Minecraft.Util.Maths; + +public class FontRenderer { + + private final Mesh quad; + private final FontShader fontShader; + private final QuadShader quadShader; + + public FontRenderer() { + float[] positions = {-1, 1, -1, -1, 1, 1, 1, -1}; + quad = new Mesh(positions.length/2).store(positions, 2).finish(); + fontShader = new FontShader(); + quadShader = new QuadShader(); + } + + public void render(Map> texts){ + for(UIFont font : texts.keySet()){ + for(UIText text : texts.get(font)){ + renderQuad(text); + } + } + prepare(); + for(UIFont font : texts.keySet()){ + GL13.glActiveTexture(GL13.GL_TEXTURE0); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, font.getTextureAtlas()); + for(UIText text : texts.get(font)){ + renderText(text); + } + } + endRendering(); + } + + public void cleanUp(){ + fontShader.cleanUp(); + quadShader.cleanUp(); + } + + private void prepare(){ + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_DEPTH_TEST); + fontShader.start(); + } + + private void renderText(UIText text){ + GL30.glBindVertexArray(text.getMesh()); + GL20.glEnableVertexAttribArray(0); + GL20.glEnableVertexAttribArray(1); + fontShader.loadColor(text.getColour()); + fontShader.loadTranslation(text.getConvertedPosition()); + GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, text.getVertexCount()); + GL20.glDisableVertexAttribArray(0); + GL20.glDisableVertexAttribArray(1); + GL30.glBindVertexArray(0); + } + + private void renderQuad(UIText text) { + quadShader.start(); + GL30.glBindVertexArray(quad.getID()); + GL20.glEnableVertexAttribArray(0); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_DEPTH_TEST); + Matrix4f matrix = Maths.createTransformationMatrix(new Vector2f(text.getStretchBackdrop() ? -1 : text.getConvertedPosition().x*2-1,(1-text.getConvertedPosition().y-.0125f*text.getFontSize()-.0025f)*2-1), new Vector2f(text.getStretchBackdrop() ? 2 : (float) text.getMaxX()*2,.025f*text.getFontSize())); + quadShader.loadTransformation(matrix); + quadShader.loadColor(new Vector4f(150/255f,150/255f,150/255f,.5f)); + GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount()); + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL20.glDisableVertexAttribArray(0); + GL30.glBindVertexArray(0); + quadShader.stop(); + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } + + private void endRendering(){ + fontShader.stop(); + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java new file mode 100755 index 0000000..b7ae6f2 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/GuiRenderer.java @@ -0,0 +1,57 @@ +package net.tylermurphy.Minecraft.Render; + +import java.util.List; + + +import net.tylermurphy.Minecraft.Render.Data.Mesh; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; +import org.joml.Matrix4f; +import org.joml.Vector2f; + +import net.tylermurphy.Minecraft.Render.Shaders.GuiShader; +import net.tylermurphy.Minecraft.UI.UIComponent; +import net.tylermurphy.Minecraft.UI.UIImage; +import net.tylermurphy.Minecraft.Util.Maths; + + +public class GuiRenderer { + + private final Mesh quad; + private GuiShader shader; + + public GuiRenderer(){ + float[] positions = {-1, 1, -1, -1, 1, 1, 1, -1}; + quad = new Mesh(positions.length/2).store(positions, 2).finish(); + shader = new GuiShader(); + } + + public void render(List components){ + shader.start(); + GL30.glBindVertexArray(quad.getID()); + GL20.glEnableVertexAttribArray(0); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_DEPTH_TEST); + for(UIComponent cp : components) { + if(!(cp instanceof UIImage)) continue; + UIImage gui = (UIImage)cp; + GL13.glActiveTexture(GL13.GL_TEXTURE0); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, gui.getTexture()); + Matrix4f matrix = Maths.createTransformationMatrix(new Vector2f(gui.getConvertedPosition().x*2-1,(1-gui.getConvertedPosition().y)*2-1), gui.getConvertedSize()); + shader.loadTransformation(matrix); + GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount()); + } + GL11.glEnable(GL11.GL_DEPTH_TEST); + GL11.glDisable(GL11.GL_BLEND); + GL20.glDisableVertexAttribArray(0); + GL30.glBindVertexArray(0); + shader.stop(); + } + + public void cleanUp(){ + shader.cleanUp(); + } +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java b/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java new file mode 100755 index 0000000..28ec88f --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/MainRenderer.java @@ -0,0 +1,73 @@ +package net.tylermurphy.Minecraft.Render; + +import net.tylermurphy.Minecraft.Render.Data.Mesh; +import org.joml.Matrix4f; + +import net.tylermurphy.Minecraft.Audio.SoundManager; +import net.tylermurphy.Minecraft.Render.Data.Texture; +import net.tylermurphy.Minecraft.Scene.World; +import net.tylermurphy.Minecraft.UI.UIMaster; +import net.tylermurphy.Minecraft.Util.Constants; +import net.tylermurphy.Minecraft.Render.Data.Display; +import net.tylermurphy.Minecraft.Util.MousePicker; +import org.joml.Vector3f; + +public class MainRenderer { + + private final GuiRenderer guiRenderer; + private final FontRenderer fontRenderer; + private final ChunkRenderer chunkRenderer; + + private Matrix4f projectionMatrix; + + public MainRenderer() { + guiRenderer = new GuiRenderer(); + fontRenderer = new FontRenderer(); + createProjectionMatrix(); + MousePicker.init(projectionMatrix); + chunkRenderer = new ChunkRenderer(projectionMatrix); + } + + public void update() { + if(Display.wasResized) { + Display.wasResized = false; + createProjectionMatrix(); + } + chunkRenderer.render(projectionMatrix); + if(!World.player.isDead) { + World.player.move(); + World.player.getTransform().setRotation(new Vector3f( + World.camera.getPitch(), + -World.camera.getYaw(), + World.camera.getRoll() + )); + World.camera.move(); + } + UIMaster.renderUI(guiRenderer, fontRenderer); + MousePicker.update(); + SoundManager.setListenerData(World.player.getTransform().getPosition().x, World.player.getTransform().getPosition().y , World.player.getTransform().getPosition().z); + } + + public void close() { + guiRenderer.cleanUp(); + chunkRenderer.cleanUp(); + Mesh.cleanUp(); + Texture.cleanUp(); + } + + private void createProjectionMatrix(){ + float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight(); + float y_scale = (float) ((1f / Math.tan(Math.toRadians(Constants.FOV / 2f)))); + float x_scale = y_scale / aspectRatio; + float frustum_length = Constants.FAR_DISTANCE - Constants.NEAR_DISTANCE; + + projectionMatrix = new Matrix4f() + .m00(x_scale) + .m11(y_scale) + .m22( -((Constants.FAR_DISTANCE + Constants.NEAR_DISTANCE) / frustum_length) ) + .m23(-1) + .m32( -((2 * Constants.NEAR_DISTANCE * Constants.FAR_DISTANCE) / frustum_length) ) + .m33(0); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java new file mode 100755 index 0000000..f998e7a --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/ChunkShader.java @@ -0,0 +1,81 @@ +package net.tylermurphy.Minecraft.Render.Shaders; + +import org.joml.Matrix4f; +import org.joml.Vector3f; + +import net.tylermurphy.Minecraft.Render.Util.ShaderProgram; +import net.tylermurphy.Minecraft.Scene.Camera; +import net.tylermurphy.Minecraft.Util.Maths; + +public class ChunkShader extends ShaderProgram{ + + private static final String VERTEX_FILE = "Chunk_VS.glsl"; + private static final String FRAGMENT_FILE = "Chunk_FS.glsl"; + + private int location_transformationMatrix; + private int location_projectionMatrix; + private int location_viewMatrix; + private int location_modelTexture; + private int location_tint; + private int location_playerPosition; + private int location_renderDistance; + private int location_skyColor; + + public ChunkShader() { + super(VERTEX_FILE, FRAGMENT_FILE); + } + + @Override + public void bindAttributes() { + super.bindAttribute(0, "position"); + super.bindAttribute(1, "textureCoordinates"); + super.bindAttribute(2, "baseLightingValue"); + super.bindAttribute(3, "layer"); + } + + @Override + public void getAllUniformLocations() { + location_transformationMatrix = super.getUniformLocation("transformationMatrix"); + location_projectionMatrix = super.getUniformLocation("projectionMatrix"); + location_viewMatrix = super.getUniformLocation("viewMatrix"); + location_modelTexture = super.getUniformLocation("modelTexture"); + location_tint = super.getUniformLocation("tint"); + location_playerPosition = super.getUniformLocation("playerPosition"); + location_renderDistance = super.getUniformLocation("renderDistance"); + location_skyColor = super.getUniformLocation("skyColor"); + } + + public void connectTextureUnits() { + super.loadInt(location_modelTexture, 0); + } + + public void loadTint(Vector3f tint) { + super.loadVector(location_tint, tint); + } + + public void loadTransformationMatrix(Matrix4f matrix){ + super.loadMatrix(location_transformationMatrix, matrix); + } + + public void loadViewMatrix(Camera camera){ + Matrix4f viewMatrix = Maths.createViewMatrix(camera); + super.loadMatrix(location_viewMatrix, viewMatrix); + } + + public void loadProjectionMatrix(Matrix4f projection){ + super.loadMatrix(location_projectionMatrix, projection); + } + + public void loadPlayerPosition(Vector3f position) { + super.loadVector(location_playerPosition, position); + } + + public void loadRenderDistance(int distance) { + super.loadInt(location_renderDistance, distance); + } + + public void loadSkyColor(Vector3f color) { + super.loadVector(location_skyColor, color); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java new file mode 100755 index 0000000..0615b13 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/FontShader.java @@ -0,0 +1,40 @@ +package net.tylermurphy.Minecraft.Render.Shaders; + +import org.joml.Vector2f; +import org.joml.Vector3f; + +import net.tylermurphy.Minecraft.Render.Util.ShaderProgram; + +public class FontShader extends ShaderProgram{ + + private static final String VERTEX_FILE ="Font_VS.glsl"; + private static final String FRAGMENT_FILE = "Font_FS.glsl"; + + private int location_color; + private int location_translation; + + public FontShader() { + super(VERTEX_FILE, FRAGMENT_FILE); + } + + @Override + protected void getAllUniformLocations() { + location_color = super.getUniformLocation("color"); + location_translation = super.getUniformLocation("translation"); + } + + @Override + protected void bindAttributes() { + super.bindAttribute(0, "position"); + super.bindAttribute(1, "textureCoords"); + } + + public void loadColor(Vector3f colour){ + super.loadVector(location_color, colour); + } + + public void loadTranslation(Vector2f vector2f){ + super.load2DVector(location_translation, vector2f); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java new file mode 100755 index 0000000..cf10ff3 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/GuiShader.java @@ -0,0 +1,33 @@ +package net.tylermurphy.Minecraft.Render.Shaders; + +import org.joml.Matrix4f; + +import net.tylermurphy.Minecraft.Render.Util.ShaderProgram; + +public class GuiShader extends ShaderProgram{ + + private static final String VERTEX_FILE = "Gui_VS.glsl"; + private static final String FRAGMENT_FILE = "Gui_FS.glsl"; + + private int location_transformationMatrix; + + public GuiShader() { + super(VERTEX_FILE, FRAGMENT_FILE); + } + + public void loadTransformation(Matrix4f matrix){ + super.loadMatrix(location_transformationMatrix, matrix); + } + + protected void getAllUniformLocations() { + location_transformationMatrix = super.getUniformLocation("transformationMatrix"); + } + + protected void bindAttributes() { + super.bindAttribute(0, "position"); + } + + + + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java new file mode 100755 index 0000000..0424cc3 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Shaders/QuadShader.java @@ -0,0 +1,37 @@ +package net.tylermurphy.Minecraft.Render.Shaders; + +import org.joml.Matrix4f; +import org.joml.Vector4f; + +import net.tylermurphy.Minecraft.Render.Util.ShaderProgram; + +public class QuadShader extends ShaderProgram{ + + private static final String VERTEX_FILE = "Quad_VS.glsl"; + private static final String FRAGMENT_FILE = "Quad_FS.glsl"; + + private int location_transformationMatrix; + private int location_color; + + public QuadShader() { + super(VERTEX_FILE, FRAGMENT_FILE); + } + + public void loadTransformation(Matrix4f matrix){ + super.loadMatrix(location_transformationMatrix, matrix); + } + + protected void getAllUniformLocations() { + location_transformationMatrix = super.getUniformLocation("transformationMatrix"); + location_color = super.getUniformLocation("color"); + } + + protected void bindAttributes() { + super.bindAttribute(0, "position"); + } + + public void loadColor(Vector4f color) { + super.loadVector(location_color, color); + } + +} diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java b/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java new file mode 100755 index 0000000..41472c4 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Util/FrustumCuller.java @@ -0,0 +1,172 @@ +package net.tylermurphy.Minecraft.Render.Util; + +import java.nio.FloatBuffer; + +import org.lwjgl.BufferUtils; +import org.joml.Matrix4f; + +import net.tylermurphy.Minecraft.Render.Util.FrustumCuller; + +public class FrustumCuller { + public float[][] m_Frustum = new float[6][4]; + public static final int RIGHT = 0; + public static final int LEFT = 1; + public static final int BOTTOM = 2; + public static final int TOP = 3; + public static final int BACK = 4; + public static final int FRONT = 5; + public static final int A = 0; + public static final int B = 1; + public static final int C = 2; + public static final int D = 3; + private static FrustumCuller frustum = new FrustumCuller(); + + private static FloatBuffer modlBuffer = BufferUtils.createFloatBuffer(16); + private static FloatBuffer projBuffer = BufferUtils.createFloatBuffer(16); + + float[] proj = new float[16]; + float[] modl = new float[16]; + float[] clip = new float[16]; + + public static FrustumCuller getFrustum(Matrix4f viewMatrix, Matrix4f projectionMatrix) { + frustum.calculateFrustum(viewMatrix, projectionMatrix); + return frustum; + } + + private void normalizePlane(float[][] frustum, int side) { + float magnitude = (float) Math.sqrt(frustum[side][0] * frustum[side][0] + frustum[side][1] * frustum[side][1] + frustum[side][2] * frustum[side][2]); + + frustum[side][0] /= magnitude; + frustum[side][1] /= magnitude; + frustum[side][2] /= magnitude; + frustum[side][3] /= magnitude; + } + + private void calculateFrustum(Matrix4f viewMatrix, Matrix4f projectionMatrix) { + + modlBuffer.rewind(); + viewMatrix.get(modlBuffer); + projBuffer.rewind(); + projectionMatrix.get(projBuffer); + + for(int i = 0; i < 16; i ++) { + modl[i] = modlBuffer.get(i); + proj[i] = projBuffer.get(i); + } + + this.clip[0] = (this.modl[0] * this.proj[0] + this.modl[1] * this.proj[4] + this.modl[2] * this.proj[8] + this.modl[3] * this.proj[12]); + this.clip[1] = (this.modl[0] * this.proj[1] + this.modl[1] * this.proj[5] + this.modl[2] * this.proj[9] + this.modl[3] * this.proj[13]); + this.clip[2] = (this.modl[0] * this.proj[2] + this.modl[1] * this.proj[6] + this.modl[2] * this.proj[10] + this.modl[3] * this.proj[14]); + this.clip[3] = (this.modl[0] * this.proj[3] + this.modl[1] * this.proj[7] + this.modl[2] * this.proj[11] + this.modl[3] * this.proj[15]); + + this.clip[4] = (this.modl[4] * this.proj[0] + this.modl[5] * this.proj[4] + this.modl[6] * this.proj[8] + this.modl[7] * this.proj[12]); + this.clip[5] = (this.modl[4] * this.proj[1] + this.modl[5] * this.proj[5] + this.modl[6] * this.proj[9] + this.modl[7] * this.proj[13]); + this.clip[6] = (this.modl[4] * this.proj[2] + this.modl[5] * this.proj[6] + this.modl[6] * this.proj[10] + this.modl[7] * this.proj[14]); + this.clip[7] = (this.modl[4] * this.proj[3] + this.modl[5] * this.proj[7] + this.modl[6] * this.proj[11] + this.modl[7] * this.proj[15]); + + this.clip[8] = (this.modl[8] * this.proj[0] + this.modl[9] * this.proj[4] + this.modl[10] * this.proj[8] + this.modl[11] * this.proj[12]); + this.clip[9] = (this.modl[8] * this.proj[1] + this.modl[9] * this.proj[5] + this.modl[10] * this.proj[9] + this.modl[11] * this.proj[13]); + this.clip[10] = (this.modl[8] * this.proj[2] + this.modl[9] * this.proj[6] + this.modl[10] * this.proj[10] + this.modl[11] * this.proj[14]); + this.clip[11] = (this.modl[8] * this.proj[3] + this.modl[9] * this.proj[7] + this.modl[10] * this.proj[11] + this.modl[11] * this.proj[15]); + + this.clip[12] = (this.modl[12] * this.proj[0] + this.modl[13] * this.proj[4] + this.modl[14] * this.proj[8] + this.modl[15] * this.proj[12]); + this.clip[13] = (this.modl[12] * this.proj[1] + this.modl[13] * this.proj[5] + this.modl[14] * this.proj[9] + this.modl[15] * this.proj[13]); + this.clip[14] = (this.modl[12] * this.proj[2] + this.modl[13] * this.proj[6] + this.modl[14] * this.proj[10] + this.modl[15] * this.proj[14]); + this.clip[15] = (this.modl[12] * this.proj[3] + this.modl[13] * this.proj[7] + this.modl[14] * this.proj[11] + this.modl[15] * this.proj[15]); + + this.m_Frustum[0][0] = (this.clip[3] - this.clip[0]); + this.m_Frustum[0][1] = (this.clip[7] - this.clip[4]); + this.m_Frustum[0][2] = (this.clip[11] - this.clip[8]); + this.m_Frustum[0][3] = (this.clip[15] - this.clip[12]); + + normalizePlane(this.m_Frustum, 0); + + this.m_Frustum[1][0] = (this.clip[3] + this.clip[0]); + this.m_Frustum[1][1] = (this.clip[7] + this.clip[4]); + this.m_Frustum[1][2] = (this.clip[11] + this.clip[8]); + this.m_Frustum[1][3] = (this.clip[15] + this.clip[12]); + + normalizePlane(this.m_Frustum, 1); + + this.m_Frustum[2][0] = (this.clip[3] + this.clip[1]); + this.m_Frustum[2][1] = (this.clip[7] + this.clip[5]); + this.m_Frustum[2][2] = (this.clip[11] + this.clip[9]); + this.m_Frustum[2][3] = (this.clip[15] + this.clip[13]); + + normalizePlane(this.m_Frustum, 2); + + this.m_Frustum[3][0] = (this.clip[3] - this.clip[1]); + this.m_Frustum[3][1] = (this.clip[7] - this.clip[5]); + this.m_Frustum[3][2] = (this.clip[11] - this.clip[9]); + this.m_Frustum[3][3] = (this.clip[15] - this.clip[13]); + + normalizePlane(this.m_Frustum, 3); + + this.m_Frustum[4][0] = (this.clip[3] - this.clip[2]); + this.m_Frustum[4][1] = (this.clip[7] - this.clip[6]); + this.m_Frustum[4][2] = (this.clip[11] - this.clip[10]); + this.m_Frustum[4][3] = (this.clip[15] - this.clip[14]); + + normalizePlane(this.m_Frustum, 4); + + this.m_Frustum[5][0] = (this.clip[3] + this.clip[2]); + this.m_Frustum[5][1] = (this.clip[7] + this.clip[6]); + this.m_Frustum[5][2] = (this.clip[11] + this.clip[10]); + this.m_Frustum[5][3] = (this.clip[15] + this.clip[14]); + + normalizePlane(this.m_Frustum, 5); + } + + public boolean pointInFrustum(float x, float y, float z) { + for (int i = 0; i < 6; i++) { + if (this.m_Frustum[i][0] * x + this.m_Frustum[i][1] * y + this.m_Frustum[i][2] * z + this.m_Frustum[i][3] <= 0.0F) { + return false; + } + } + + return true; + } + + public boolean sphereInFrustum(float x, float y, float z, float radius) { + for (int i = 0; i < 6; i++) { + if (this.m_Frustum[i][0] * x + this.m_Frustum[i][1] * y + this.m_Frustum[i][2] * z + this.m_Frustum[i][3] <= -radius) { + return false; + } + } + + return true; + } + + public boolean cubeFullyInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) { + for (int i = 0; i < 6; i++) { + if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) + return false; + if (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) + return false; + } + + return true; + } + + public boolean cubeInFrustum(float x1, float y1, float z1, float x2, float y2, float z2) { + return true; +// for (int i = 0; i < 6; i++) { +// if ((this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z1 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y1 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x1 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F) && (this.m_Frustum[i][0] * x2 + this.m_Frustum[i][1] * y2 + this.m_Frustum[i][2] * z2 + this.m_Frustum[i][3] <= 0.0F)) { +// return false; +// } +// } +// return true; + } +} \ No newline at end of file diff --git a/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java b/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java new file mode 100755 index 0000000..ce5bae6 --- /dev/null +++ b/src/main/java/net/tylermurphy/Minecraft/Render/Util/ShaderProgram.java @@ -0,0 +1,126 @@ +package net.tylermurphy.Minecraft.Render.Util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.nio.FloatBuffer; + +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL20; +import org.joml.Matrix4f; +import org.joml.Vector2f; +import org.joml.Vector3f; +import org.joml.Vector4f; + +import net.tylermurphy.Minecraft.Util.Constants; + +public abstract class ShaderProgram { + + private int programID; + private int vertexShaderID; + private int fragmentShaderID; + + private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16); + + public ShaderProgram(String vertexFile,String fragmentFile){ + vertexShaderID = loadShader(vertexFile,GL20.GL_VERTEX_SHADER); + fragmentShaderID = loadShader(fragmentFile,GL20.GL_FRAGMENT_SHADER); + programID = GL20.glCreateProgram(); + GL20.glAttachShader(programID, vertexShaderID); + GL20.glAttachShader(programID, fragmentShaderID); + bindAttributes(); + GL20.glLinkProgram(programID); + GL20.glValidateProgram(programID); + getAllUniformLocations(); + } + + protected abstract void getAllUniformLocations(); + + protected int getUniformLocation(String uniformName){ + return GL20.glGetUniformLocation(programID,uniformName); + } + + public void start(){ + GL20.glUseProgram(programID); + } + + public void stop(){ + GL20.glUseProgram(0); + } + + public void cleanUp(){ + stop(); + GL20.glDetachShader(programID, vertexShaderID); + GL20.glDetachShader(programID, fragmentShaderID); + GL20.glDeleteShader(vertexShaderID); + GL20.glDeleteShader(fragmentShaderID); + GL20.glDeleteProgram(programID); + } + + protected abstract void bindAttributes(); + + protected void bindAttribute(int attribute, String variableName){ + GL20.glBindAttribLocation(programID, attribute, variableName); + } + + protected void loadFloat(int location, float value){ + GL20.glUniform1f(location, value); + } + + protected void loadInt(int location, int value){ + GL20.glUniform1i(location, value); + } + + protected void loadVector(int location, Vector3f vector){ + GL20.glUniform3f(location,vector.x,vector.y,vector.z); + } + + protected void loadVector(int location, Vector4f vector){ + GL20.glUniform4f(location,vector.x,vector.y,vector.z, vector.w); + } + + protected void load2DVector(int location, Vector2f vector){ + GL20.glUniform2f(location,vector.x,vector.y); + } + + protected void loadBoolean(int location, boolean value){ + float toLoad = 0; + if(value){ + toLoad = 1; + } + GL20.glUniform1f(location, toLoad); + } + + protected void loadMatrix(int location, Matrix4f matrix){ + matrix.get(matrixBuffer); + GL20.glUniformMatrix4fv(location, false, matrixBuffer); + } + + private static int loadShader(String file, int type){ + StringBuilder shaderSource = new StringBuilder(); + try{ + FileReader fr = new FileReader(new File(Constants.SHADER_LOCATION + file)); + BufferedReader reader = new BufferedReader(fr); + String line; + while((line = reader.readLine())!=null){ + shaderSource.append(line).append("//\n"); + } + reader.close(); + }catch(IOException e){ + e.printStackTrace(); + System.exit(-1); + } + int shaderID = GL20.glCreateShader(type); + GL20.glShaderSource(shaderID, shaderSource); + GL20.glCompileShader(shaderID); + if(GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS )== GL11.GL_FALSE){ + System.out.println(GL20.glGetShaderInfoLog(shaderID, 500)); + System.err.println("Could not compile shader!"); + System.exit(-1); + } + return shaderID; + } + +} -- cgit v1.2.3-freya