From faa92d09de7dd8b93123931c36ab84c115d9c7f0 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Wed, 19 Mar 2025 15:20:03 +0100 Subject: [PATCH] plateau qui tourne --- app/build.gradle | 17 ++- app/src/main/java/chess/App.java | 4 +- app/src/main/java/chess/render/Camera.java | 128 ++++++++++++++++ .../main/java/chess/render/ElementBuffer.java | 33 +++++ app/src/main/java/chess/render/Renderer.java | 123 ++++++++++++++++ .../main/java/chess/render/VertexArray.java | 47 ++++++ .../chess/render/VertexAttribPointer.java | 13 ++ .../main/java/chess/render/VertexBuffer.java | 50 +++++++ app/src/main/java/chess/render/Window.java | 138 ++++++++++++++++++ .../java/chess/render/shader/BoardShader.java | 53 +++++++ .../chess/render/shader/ShaderProgram.java | 94 ++++++++++++ 11 files changed, 696 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/chess/render/Camera.java create mode 100644 app/src/main/java/chess/render/ElementBuffer.java create mode 100644 app/src/main/java/chess/render/Renderer.java create mode 100644 app/src/main/java/chess/render/VertexArray.java create mode 100644 app/src/main/java/chess/render/VertexAttribPointer.java create mode 100644 app/src/main/java/chess/render/VertexBuffer.java create mode 100644 app/src/main/java/chess/render/Window.java create mode 100644 app/src/main/java/chess/render/shader/BoardShader.java create mode 100644 app/src/main/java/chess/render/shader/ShaderProgram.java diff --git a/app/build.gradle b/app/build.gradle index 75305d2..7641c68 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ plugins { // Apply the application plugin to add support for building a CLI application in Java. - id 'application' + id "application" } repositories { @@ -16,15 +16,26 @@ repositories { mavenCentral() } +def lwjgl_version = "3.3.6" +def lwjgl_natives = "natives-linux" + dependencies { // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' + testImplementation "org.junit.jupiter:junit-jupiter:5.9.1" + implementation "org.lwjgl:lwjgl:$lwjgl_version" + implementation "org.lwjgl:lwjgl-opengl:$lwjgl_version" + implementation "org.lwjgl:lwjgl-glfw:$lwjgl_version" + implementation "org.joml:joml:1.10.8" + + implementation "org.lwjgl:lwjgl::$lwjgl_natives" + implementation "org.lwjgl:lwjgl-opengl::$lwjgl_natives" + implementation "org.lwjgl:lwjgl-glfw::$lwjgl_natives" } application { // Define the main class for the application. - mainClass = 'chess.App' + mainClass = "chess.App" } tasks.named('test') { diff --git a/app/src/main/java/chess/App.java b/app/src/main/java/chess/App.java index ce3c0b3..716a717 100644 --- a/app/src/main/java/chess/App.java +++ b/app/src/main/java/chess/App.java @@ -3,12 +3,14 @@ */ package chess; +import chess.render.*; + public class App { public String getGreeting() { return "Hello World!"; } public static void main(String[] args) { - System.out.println(new App().getGreeting()); + new Window().run(); } } diff --git a/app/src/main/java/chess/render/Camera.java b/app/src/main/java/chess/render/Camera.java new file mode 100644 index 0000000..fe72244 --- /dev/null +++ b/app/src/main/java/chess/render/Camera.java @@ -0,0 +1,128 @@ +package chess.render; + +import org.joml.Matrix4f; +import org.joml.Vector3f; + +public class Camera { + public static final float fov = 70.0f; + // should be changed to match screen + public static final float aspect = 1.0f; + public static final float zNear = 0.01f; + public static final float zFar = 100.0f; + + private Vector3f pos; + + private float yaw = 0.0f; + private float pitch = 0.0f; + + public Camera() { + this.pos = new Vector3f(0, 2.0f, 0); + setRotation(0.0f, -3.14150f / 2.0f); + } + + public void move(float x, float y) { + this.pos.x += x; + this.pos.y += y; + } + + public void rotate(float yaw, float pitch) { + this.yaw += yaw; + this.pitch += pitch; + } + + public Vector3f getPos() { + return pos; + } + + public float getYaw() { + return yaw; + } + + public float getPitch() { + return pitch; + } + + public float getFov() { + return fov; + } + + public void setX(float x) { + this.pos.x = x; + } + + public void setY(float y) { + this.pos.y = y; + } + + public void setZ(float z) { + this.pos.z = z; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public void reset() { + resetPosition(); + resetRotation(); + } + + public void resetPosition() { + pos = new Vector3f(0.0f, 0.0f, 0.0f); + } + + public void resetRotation() { + yaw = 0.0f; + pitch = 0.0f; + } + + public void moveForward(float distance) { + pos.x += distance * (float) Math.cos(yaw); + pos.y += distance * (float) Math.sin(yaw); + } + + public void moveRight(float distance) { + pos.x += distance * (float) Math.cos(yaw); + pos.y += distance * (float) Math.sin(yaw); + } + + public void moveUp(float distance) { + pos.z += distance; + } + + public void moveDown(float distance) { + pos.z -= distance; + } + + public void addYaw(float angle) { + yaw += angle; + } + + public void addPitch(float angle) { + pitch += angle; + } + + public void setPosition(Vector3f pos) { + this.pos = pos; + } + + public void setRotation(float yaw, float pitch) { + this.yaw = yaw; + this.pitch = pitch; + } + + public Matrix4f getMatrix() { + Vector3f forward = new Vector3f( + (float) (Math.cos(yaw) * Math.cos(pitch)), + (float) (Math.sin(pitch)), + (float) (Math.sin(yaw) * Math.cos(pitch))); + + return new Matrix4f() + .perspective((float) (Math.toRadians(fov)), aspect, zNear, zFar) + .lookAt(pos, forward, new Vector3f(0.0f, 1.0f, 0.0f)); + } +} diff --git a/app/src/main/java/chess/render/ElementBuffer.java b/app/src/main/java/chess/render/ElementBuffer.java new file mode 100644 index 0000000..c7a7bd0 --- /dev/null +++ b/app/src/main/java/chess/render/ElementBuffer.java @@ -0,0 +1,33 @@ +package chess.render; + +import org.lwjgl.opengl.GL30; + +public class ElementBuffer { + private int id; + private int indiciesCount; + + public ElementBuffer(int[] indicies) { + this.indiciesCount = indicies.length; + this.id = GL30.glGenBuffers(); + Bind(); + GL30.glBufferData(GL30.GL_ELEMENT_ARRAY_BUFFER, indicies.length * 4, GL30.GL_STATIC_DRAW); + GL30.glBufferSubData(GL30.GL_ELEMENT_ARRAY_BUFFER, 0, indicies); + Unbind(); + } + + public void Destroy() { + GL30.glDeleteBuffers(this.id); + } + + public void Bind() { + GL30.glBindBuffer(GL30.GL_ELEMENT_ARRAY_BUFFER, this.id); + } + + public void Unbind() { + GL30.glBindBuffer(GL30.GL_ELEMENT_ARRAY_BUFFER, 0); + } + + public int GetIndiciesCount() { + return this.indiciesCount; + } +} diff --git a/app/src/main/java/chess/render/Renderer.java b/app/src/main/java/chess/render/Renderer.java new file mode 100644 index 0000000..4e579af --- /dev/null +++ b/app/src/main/java/chess/render/Renderer.java @@ -0,0 +1,123 @@ +package chess.render; + +import org.joml.Vector3f; +import org.lwjgl.opengl.*; + +import static org.lwjgl.opengl.GL30.*; +import chess.render.shader.BoardShader; + +public class Renderer { + private BoardShader shader; + private VertexArray vao; + + private static int BOARD_WIDTH = 8; + private static int BOARD_HEIGHT = 8; + private static int BOARD_SIZE = BOARD_WIDTH * BOARD_HEIGHT; + private static int SQUARE_VERTEX_COUNT = 4; + + public Renderer() { + this.shader = new BoardShader(); + } + + public void Init() { + shader.LoadShader(); + InitBoard(); + } + + private float[] GetBoardPositions() { + float[] positions = new float[BOARD_SIZE * SQUARE_VERTEX_COUNT * 3]; + for (int i = 0; i < BOARD_WIDTH; i++) { + for (int j = 0; j < BOARD_HEIGHT; j++) { + float x = i / (float) BOARD_WIDTH; + float dx = (i + 1) / (float) BOARD_WIDTH; + float z = j / (float) BOARD_HEIGHT; + float dz = (j + 1) / (float) BOARD_HEIGHT; + + float trueX = 2 * x - 1; + float trueZ = 2 * z - 1; + float trueDX = 2 * dx - 1; + float trueDZ = 2 * dz - 1; + + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3] = trueX; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 1] = 0.0f; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 2] = trueZ; + + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 3] = trueDX; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 4] = 0.0f; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 5] = trueZ; + + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 6] = trueX; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 7] = 0.0f; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 8] = trueDZ; + + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 9] = trueDX; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 10] = 0.0f; + positions[(BOARD_WIDTH * i + j) * SQUARE_VERTEX_COUNT * 3 + 11] = trueDZ; + } + } + return positions; + } + + private float[] GetBoardColors() { + float[] colors = new float[BOARD_SIZE * SQUARE_VERTEX_COUNT * 3]; + for (int i = 0; i < BOARD_WIDTH; i++) { + for (int j = 0; j < BOARD_HEIGHT; j++) { + Vector3f color; + if ((i + j) % 2 != 0) { + color = new Vector3f(1.0f, 1.0f, 1.0f); + } else { + color = new Vector3f(0.0f, 0.0f, 0.0f); + } + int squareIndex = i * BOARD_WIDTH + j; + for (int k = 0; k < SQUARE_VERTEX_COUNT; k++) { + colors[squareIndex * SQUARE_VERTEX_COUNT * 3 + k * 3] = color.x; + colors[squareIndex * SQUARE_VERTEX_COUNT * 3 + k * 3 + 1] = color.y; + colors[squareIndex * SQUARE_VERTEX_COUNT * 3 + k * 3 + 2] = color.z; + } + } + } + return colors; + } + + private int[] GetBoardIndicies() { + int[] indices = new int[BOARD_SIZE * 6]; + for (int i = 0; i < BOARD_SIZE; i++) { + indices[i * 6] = i * 4; + indices[i * 6 + 1] = i * 4 + 1; + indices[i * 6 + 2] = i * 4 + 2; + indices[i * 6 + 3] = i * 4 + 1; + indices[i * 6 + 4] = i * 4 + 2; + indices[i * 6 + 5] = i * 4 + 3; + } + return indices; + } + + private void InitBoard() { + ElementBuffer eBuffer = new ElementBuffer(GetBoardIndicies()); + this.vao = new VertexArray(eBuffer); + + VertexBuffer positionBuffer = new VertexBuffer(GetBoardPositions(), 3); + positionBuffer.AddVertexAttribPointer(0, 3, 0); + + VertexBuffer colorBuffer = new VertexBuffer(GetBoardColors(), 3); + colorBuffer.AddVertexAttribPointer(1, 3, 0); + + this.vao.Bind(); + this.vao.BindVertexBuffer(positionBuffer); + this.vao.BindVertexBuffer(colorBuffer); + this.vao.Unbind(); + } + + public void Render(Camera cam) { + this.shader.Start(); + this.shader.SetCamMatrix(cam.getMatrix()); + RenderVao(vao); + } + + public void RenderVao(VertexArray vertexArray) { + this.shader.Start(); + vertexArray.Bind(); + GL30.glDrawElements(GL30.GL_TRIANGLES, vertexArray.GetVertexCount(), GL_UNSIGNED_INT, 0); + vertexArray.Unbind(); + } +} diff --git a/app/src/main/java/chess/render/VertexArray.java b/app/src/main/java/chess/render/VertexArray.java new file mode 100644 index 0000000..8f966fa --- /dev/null +++ b/app/src/main/java/chess/render/VertexArray.java @@ -0,0 +1,47 @@ +package chess.render; + +import java.util.ArrayList; +import java.util.List; + +import org.lwjgl.opengl.GL30; + +public class VertexArray { + private int id; + private ElementBuffer elementBuffer; + private List vertexBuffers; + + public VertexArray(ElementBuffer elementBuffer) { + this.id = GL30.glGenVertexArrays(); + this.elementBuffer = elementBuffer; + this.vertexBuffers = new ArrayList(); + Bind(); + BindElementArrayBuffer(); + Unbind(); + } + + public void Destroy() { + GL30.glDeleteBuffers(this.id); + } + + public int GetVertexCount() { + return this.elementBuffer.GetIndiciesCount(); + } + + public void BindVertexBuffer(VertexBuffer buffer) { + buffer.Bind(); + buffer.BindVertexAttribs(); + this.vertexBuffers.add(buffer); + } + + public void Bind() { + GL30.glBindVertexArray(this.id); + } + + public void Unbind() { + GL30.glBindVertexArray(0); + } + + private void BindElementArrayBuffer() { + this.elementBuffer.Bind(); + } +} diff --git a/app/src/main/java/chess/render/VertexAttribPointer.java b/app/src/main/java/chess/render/VertexAttribPointer.java new file mode 100644 index 0000000..cb01074 --- /dev/null +++ b/app/src/main/java/chess/render/VertexAttribPointer.java @@ -0,0 +1,13 @@ +package chess.render; + +public class VertexAttribPointer { + public int index; + public int size; + public int offset; + + public VertexAttribPointer(int index, int size, int offset) { + this.index = index; + this.size = size; + this.offset = offset; + } +} diff --git a/app/src/main/java/chess/render/VertexBuffer.java b/app/src/main/java/chess/render/VertexBuffer.java new file mode 100644 index 0000000..5dd757f --- /dev/null +++ b/app/src/main/java/chess/render/VertexBuffer.java @@ -0,0 +1,50 @@ +package chess.render; + +import static org.lwjgl.opengl.GL11.GL_FLOAT; + +import java.nio.FloatBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.lwjgl.opengl.GL30; + +public class VertexBuffer { + private int id; + private int dataStride; + List vertexAttribs; + + public VertexBuffer(float[] data, int stride) { + this.id = GL30.glGenBuffers(); + this.dataStride = stride; + this.vertexAttribs = new ArrayList(); + Bind(); + GL30.glBufferData(GL30.GL_ARRAY_BUFFER, data.length * 4, GL30.GL_STATIC_DRAW); + GL30.glBufferSubData(GL30.GL_ARRAY_BUFFER, 0, data); + Unbind(); + } + + public void Destroy() { + GL30.glDeleteBuffers(id); + } + + public void Bind() { + GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, this.id); + } + + public void Unbind() { + GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0); + } + + public void AddVertexAttribPointer(int index, int coordinateSize, int offset) { + VertexAttribPointer pointer = new VertexAttribPointer(index, coordinateSize, offset); + this.vertexAttribs.add(pointer); + } + + public void BindVertexAttribs() { + for (VertexAttribPointer vertexAttribPointer : vertexAttribs) { + GL30.glEnableVertexAttribArray(vertexAttribPointer.index); + GL30.glVertexAttribPointer(vertexAttribPointer.index, vertexAttribPointer.size, GL_FLOAT, false, + this.dataStride * 4, vertexAttribPointer.offset); + } + } +} diff --git a/app/src/main/java/chess/render/Window.java b/app/src/main/java/chess/render/Window.java new file mode 100644 index 0000000..d3502b1 --- /dev/null +++ b/app/src/main/java/chess/render/Window.java @@ -0,0 +1,138 @@ +package chess.render; + +import org.lwjgl.*; +import org.lwjgl.glfw.*; +import org.lwjgl.opengl.*; +import org.lwjgl.system.*; + +import chess.render.Camera; +import chess.render.Renderer; + +import java.nio.*; + +import static org.lwjgl.glfw.Callbacks.*; +import static org.lwjgl.glfw.GLFW.*; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.system.MemoryStack.*; +import static org.lwjgl.system.MemoryUtil.*; + +public class Window { + + // The window handle + private long window; + + private Renderer renderer; + private Camera cam; + + public Window() { + this.renderer = new Renderer(); + this.cam = new Camera(); + } + + public void run() { + System.out.println("LWJGL " + Version.getVersion() + "!"); + + init(); + loop(); + + // Free the window callbacks and destroy the window + glfwFreeCallbacks(window); + glfwDestroyWindow(window); + + // Terminate GLFW and free the error callback + glfwTerminate(); + glfwSetErrorCallback(null).free(); + } + + private void init() { + // Setup an error callback. The default implementation + // will print the error message in System.err. + GLFWErrorCallback.createPrint(System.err).set(); + + // Initialize GLFW. Most GLFW functions will not work before doing this. + if (!glfwInit()) + throw new IllegalStateException("Unable to initialize GLFW"); + + // Configure GLFW + glfwDefaultWindowHints(); // optional, the current window hints are already the default + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable + + // Create the window + window = glfwCreateWindow(1000, 1000, "Chess4J", NULL, NULL); + if (window == NULL) + throw new RuntimeException("Failed to create the GLFW window"); + + // Get the thread stack and push a new frame + try (MemoryStack stack = stackPush()) { + IntBuffer pWidth = stack.mallocInt(1); // int* + IntBuffer pHeight = stack.mallocInt(1); // int* + + // Get the window size passed to glfwCreateWindow + glfwGetWindowSize(window, pWidth, pHeight); + + // Get the resolution of the primary monitor + GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + + // Center the window + glfwSetWindowPos( + window, + (vidmode.width() - pWidth.get(0)) / 2, + (vidmode.height() - pHeight.get(0)) / 2); + } // the stack frame is popped automatically + + // Make the OpenGL context current + glfwMakeContextCurrent(window); + // Enable v-sync + glfwSwapInterval(1); + + // Make the window visible + glfwShowWindow(window); + } + + private void render() { + cam.rotate(0.01f, 0.01f); + renderer.Render(cam); + } + + private void loop() { + // This line is critical for LWJGL's interoperation with GLFW's + // OpenGL context, or any context that is managed externally. + // LWJGL detects the context that is current in the current thread, + // creates the GLCapabilities instance and makes the OpenGL + // bindings available for use. + GL.createCapabilities(); + + renderer.Init(); + + // Set the clear color + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glColor4f(1.0f, 0.0f, 0.0f, 1.0f); + + // Run the rendering loop until the user has attempted to close + // the window or has pressed the ESCAPE key. + while (!glfwWindowShouldClose(window)) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer + + render(); + + glfwSwapBuffers(window); // swap the color buffers + + // Poll for window events. The key callback above will only be + // invoked during this call. + glfwPollEvents(); + + try (MemoryStack stack = stackPush()) { + IntBuffer pWidth = stack.mallocInt(1); // int* + IntBuffer pHeight = stack.mallocInt(1); // int* + + // Get the window size passed to glfwCreateWindow + glfwGetWindowSize(window, pWidth, pHeight); + + glViewport(0, 0, pWidth.get(), pHeight.get()); + } // the stack frame is popped automatically + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/chess/render/shader/BoardShader.java b/app/src/main/java/chess/render/shader/BoardShader.java new file mode 100644 index 0000000..15c6c10 --- /dev/null +++ b/app/src/main/java/chess/render/shader/BoardShader.java @@ -0,0 +1,53 @@ +package chess.render.shader; + +import org.joml.Matrix4f; + +public class BoardShader extends ShaderProgram { + + private static String vertexShader = """ + #version 330 + + layout(location = 0) in vec3 position; + layout(location = 1) in vec3 color; + + uniform mat4 camMatrix; + + out vec3 pass_color; + + void main(void){ + gl_Position = camMatrix * vec4(position, 1.0); + pass_color = color; + } + """; + + private static String fragmentShader = """ + #version 330 + + in vec3 pass_color; + + out vec4 out_color; + + void main(void){ + out_color = vec4(pass_color, 1.0); + } + """; + + private int location_CamMatrix = 0; + + public BoardShader() { + + } + + public void LoadShader() { + super.LoadProgram(vertexShader, fragmentShader); + } + + @Override + protected void GetAllUniformLocation() { + location_CamMatrix = GetUniformLocation("camMatrix"); + } + + public void SetCamMatrix(Matrix4f mat) { + LoadMat4(location_CamMatrix, mat); + } +} diff --git a/app/src/main/java/chess/render/shader/ShaderProgram.java b/app/src/main/java/chess/render/shader/ShaderProgram.java new file mode 100644 index 0000000..e2d8430 --- /dev/null +++ b/app/src/main/java/chess/render/shader/ShaderProgram.java @@ -0,0 +1,94 @@ +package chess.render.shader; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; + +import org.joml.Matrix4f; +import org.joml.Vector3f; +import org.lwjgl.BufferUtils; +import org.lwjgl.opengl.GL30; +import org.lwjgl.system.MemoryStack; + +public abstract class ShaderProgram { + private int programId; + private int vertexShaderId; + private int fragmentShaderId; + + public ShaderProgram() { + this.programId = 0; + this.vertexShaderId = 0; + this.fragmentShaderId = 0; + } + + public void Start() { + GL30.glUseProgram(this.programId); + } + + public void Stop() { + GL30.glUseProgram(0); + } + + public void LoadProgram(String vertexSource, String fragmentSource) { + this.vertexShaderId = LoadShader(vertexSource, GL30.GL_VERTEX_SHADER); + this.fragmentShaderId = LoadShader(fragmentSource, GL30.GL_FRAGMENT_SHADER); + + this.programId = GL30.glCreateProgram(); + GL30.glAttachShader(this.programId, vertexShaderId); + GL30.glAttachShader(this.programId, this.fragmentShaderId); + GL30.glLinkProgram(this.programId); + GL30.glValidateProgram(this.programId); + + if (GL30.glGetProgrami(programId, GL30.GL_VALIDATE_STATUS) == 0) { + System.err.println("Warning validating Shader code: " + GL30.glGetProgramInfoLog(programId, 1024)); + } + + GetAllUniformLocation(); + } + + private int LoadShader(String source, int type) { + int shaderId = GL30.glCreateShader(type); + + GL30.glShaderSource(shaderId, source); + GL30.glCompileShader(shaderId); + + IntBuffer compileSuccesful = BufferUtils.createIntBuffer(1); + GL30.glGetShaderiv(shaderId, GL30.GL_COMPILE_STATUS, compileSuccesful); + + if (compileSuccesful.get() != 1) { + System.out.println("Shader did not compile !"); + return -1; + + } + + return shaderId; + } + + protected abstract void GetAllUniformLocation(); + + protected int GetUniformLocation(String uniformName) { + int location = GL30.glGetUniformLocation(programId, uniformName); + if (location == -1) { + System.out.println("Uniform value not found !"); + } + return location; + } + + public void LoadFloat(int location, float value) { + GL30.glUniform1f(location, value); + } + + public void LoadInt(int location, int value) { + GL30.glUniform1i(location, value); + } + + public void LoadVector(int location, Vector3f vector) { + GL30.glUniform3f(location, vector.x, vector.y, vector.z); + } + + public void LoadMat4(int location, Matrix4f mat) { + try (MemoryStack stack = MemoryStack.stackPush()) { + FloatBuffer buffer = mat.get(stack.mallocFloat(16)); + GL30.glUniformMatrix4fv(location, false, buffer); + } + } +}