diff --git a/.gitignore b/.gitignore
index 1318d0a..3919f5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,4 +33,6 @@ build/
.vscode/
### Mac OS ###
-.DS_Store
\ No newline at end of file
+.DS_Store
+
+logs
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 86e58e0..26b5258 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,16 +6,53 @@
me.slinky
Tony
- 0.0.1
+ 0.0.2
- 22
- 22
- UTF-8
-
3.4.1
- natives-windows
+ 1.10.8
+ 1.10.0
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 15
+ 15
+
+
+
+
+
+
+
+ lwjgl-natives-linux-amd64
+
+
+ unix
+ linux
+ amd64
+
+
+
+ natives-linux
+
+
+
+ lwjgl-natives-windows-amd64
+
+
+ windows
+ amd64
+
+
+
+ natives-windows
+
+
+
@@ -38,170 +75,30 @@
org.lwjgl
lwjgl-assimp
-
- org.lwjgl
- lwjgl-bgfx
-
-
- org.lwjgl
- lwjgl-egl
-
-
- org.lwjgl
- lwjgl-fmod
-
-
- org.lwjgl
- lwjgl-freetype
-
org.lwjgl
lwjgl-glfw
-
- org.lwjgl
- lwjgl-harfbuzz
-
-
- org.lwjgl
- lwjgl-hwloc
-
-
- org.lwjgl
- lwjgl-jawt
-
-
- org.lwjgl
- lwjgl-jemalloc
-
-
- org.lwjgl
- lwjgl-ktx
-
-
- org.lwjgl
- lwjgl-llvm
-
-
- org.lwjgl
- lwjgl-lmdb
-
-
- org.lwjgl
- lwjgl-lz4
-
-
- org.lwjgl
- lwjgl-meshoptimizer
-
-
- org.lwjgl
- lwjgl-msdfgen
-
-
- org.lwjgl
- lwjgl-nanovg
-
-
- org.lwjgl
- lwjgl-nfd
-
-
- org.lwjgl
- lwjgl-nuklear
-
-
- org.lwjgl
- lwjgl-odbc
-
org.lwjgl
lwjgl-openal
-
- org.lwjgl
- lwjgl-opencl
-
org.lwjgl
lwjgl-opengl
-
- org.lwjgl
- lwjgl-opengles
-
-
- org.lwjgl
- lwjgl-openxr
-
-
- org.lwjgl
- lwjgl-opus
-
-
- org.lwjgl
- lwjgl-par
-
-
- org.lwjgl
- lwjgl-remotery
-
-
- org.lwjgl
- lwjgl-renderdoc
-
-
- org.lwjgl
- lwjgl-rpmalloc
-
-
- org.lwjgl
- lwjgl-sdl
-
-
- org.lwjgl
- lwjgl-shaderc
-
org.lwjgl
lwjgl-spng
-
- org.lwjgl
- lwjgl-spvc
-
org.lwjgl
lwjgl-stb
-
- org.lwjgl
- lwjgl-tinyexr
-
org.lwjgl
lwjgl-tinyfd
-
- org.lwjgl
- lwjgl-vma
-
-
- org.lwjgl
- lwjgl-vulkan
-
-
- org.lwjgl
- lwjgl-xxhash
-
-
- org.lwjgl
- lwjgl-yoga
-
-
- org.lwjgl
- lwjgl-zstd
-
org.lwjgl
lwjgl
@@ -212,81 +109,11 @@
lwjgl-assimp
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-bgfx
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-freetype
- ${lwjgl.natives}
-
org.lwjgl
lwjgl-glfw
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-harfbuzz
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-hwloc
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-jemalloc
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-ktx
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-llvm
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-lmdb
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-lz4
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-meshoptimizer
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-msdfgen
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-nanovg
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-nfd
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-nuklear
- ${lwjgl.natives}
-
org.lwjgl
lwjgl-openal
@@ -297,95 +124,40 @@
lwjgl-opengl
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-opengles
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-openxr
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-opus
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-par
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-remotery
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-rpmalloc
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-sdl
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-shaderc
- ${lwjgl.natives}
-
org.lwjgl
lwjgl-spng
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-spvc
- ${lwjgl.natives}
-
org.lwjgl
lwjgl-stb
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-tinyexr
- ${lwjgl.natives}
-
org.lwjgl
lwjgl-tinyfd
${lwjgl.natives}
-
- org.lwjgl
- lwjgl-vma
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-xxhash
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-yoga
- ${lwjgl.natives}
-
-
- org.lwjgl
- lwjgl-zstd
- ${lwjgl.natives}
-
org.joml
joml
- 1.10.8
+ ${joml.version}
+
+
+ org.joml
+ joml-primitives
+ ${joml-primitives.version}
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.25.3
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.25.3
diff --git a/src/main/java/DirectionalLight.java b/src/main/java/DirectionalLight.java
new file mode 100644
index 0000000..048cb53
--- /dev/null
+++ b/src/main/java/DirectionalLight.java
@@ -0,0 +1,16 @@
+import org.joml.Vector3f;
+
+public class DirectionalLight {
+ public Vector3f direction;
+ public Vector3f color;
+ public float intensity;
+
+ public DirectionalLight (
+ Vector3f direction,
+ Vector3f color,
+ float intensity) {
+ this.direction = direction;
+ this.color = color;
+ this.intensity = intensity;
+ }
+}
diff --git a/src/main/java/Mesh.java b/src/main/java/Mesh.java
index 8b6dee5..adf7027 100644
--- a/src/main/java/Mesh.java
+++ b/src/main/java/Mesh.java
@@ -15,35 +15,46 @@ public class Mesh {
private int _vbo;
private int _ebo;
- public void setup(float[] positions, float[] uv, float[] normals, int[] indices) {
+ private int vertexCount;
+
+ public Mesh(float[] p, float[] u, float[] n, int[] indices) {
+ vertexCount = indices.length;
+ sendToGPU(Vertex.interleaveVertexData(p, u, n), indices);
+ }
+
+ public void render() {
+ glBindVertexArray(_vao);
+ glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_INT, 0);
+ glBindVertexArray(0);
+ }
+
+ public void cleanup() {
+ glDeleteBuffers(_vbo);
+ glDeleteBuffers(_ebo);
+ glDeleteVertexArrays(_vao);
+ }
+
+ private void sendToGPU(float[] vertices, int[] indices) {
try (MemoryStack stack = MemoryStack.stackPush()) {
_vao = glGenVertexArrays();
glBindVertexArray(_vao);
// pos
_vbo = glGenBuffers();
- FloatBuffer posBuffer = stack.mallocFloat(positions.length);
- posBuffer.put(positions).flip();
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
- glBufferData(GL_ARRAY_BUFFER, posBuffer, GL_STATIC_DRAW);
- glEnableVertexAttribArray(0);
- glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
+ glBufferData(GL_ARRAY_BUFFER, stack.floats(vertices), GL_STATIC_DRAW);
- // uv
- int uvVbo = glGenBuffers();
- FloatBuffer uvBuffer = stack.mallocFloat(uv.length);
- uvBuffer.put(uv).flip();
- glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
- glBufferData(GL_ARRAY_BUFFER, uvBuffer, GL_STATIC_DRAW);
- glEnableVertexAttribArray(1);
- glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
-
- // indices
_ebo = glGenBuffers();
- IntBuffer indexBuffer = stack.mallocInt(indices.length);
- indexBuffer.put(indices).flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, stack.ints(indices), GL_STATIC_DRAW);
+
+ // set vao positions
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(0, 3, GL_FLOAT, false, STRIDE, 0);
+ glEnableVertexAttribArray(1);
+ glVertexAttribPointer(1, 2, GL_FLOAT, false, STRIDE, 3 * Float.BYTES);
+ glEnableVertexAttribArray(2);
+ glVertexAttribPointer(2, 3, GL_FLOAT, false, STRIDE, 5 * Float.BYTES);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
diff --git a/src/main/java/OrthoCamera.java b/src/main/java/OrthoCamera.java
new file mode 100644
index 0000000..d619edb
--- /dev/null
+++ b/src/main/java/OrthoCamera.java
@@ -0,0 +1,35 @@
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+
+public class OrthoCamera {
+ private Matrix4f projection;
+ private Matrix4f view;
+
+ private float size = 10.f;
+ private Vector3f position = new Vector3f(size, size, size);
+
+ public OrthoCamera(float aspectRatio) {
+ projection = new Matrix4f().ortho(
+ -size * aspectRatio, // Left
+ size * aspectRatio, // Right
+ -size, // Bottom
+ size, // Top
+ 0.01f, // Near
+ 100.0f // Far
+ );
+
+ Vector3f camPos = new Vector3f(10, 10, 10);
+ Vector3f target = new Vector3f(0, 0, 0);
+ Vector3f up = new Vector3f(0, 1, 0);
+
+ view = new Matrix4f().lookAt(camPos, target, up);
+ }
+
+ public Matrix4f getProjection() {
+ return projection;
+ }
+
+ public Matrix4f getView() {
+ return view;
+ }
+}
diff --git a/src/main/java/PrimitiveGenerator.java b/src/main/java/PrimitiveGenerator.java
index bc40297..9e136af 100644
--- a/src/main/java/PrimitiveGenerator.java
+++ b/src/main/java/PrimitiveGenerator.java
@@ -3,11 +3,57 @@ import org.joml.Vector3f;
public class PrimitiveGenerator {
public static Mesh getCube() {
- var mesh = new Mesh();
+ float s = 0.5f;
- Vertex[] vertices = new Vertex[8];
+ // Positions: 24 vertices (6 faces * 4 vertices)
+ float[] p = {
+ // Front face (z = s)
+ -s, s, s, -s, -s, s, s, -s, s, s, s, s,
+ // Back face (z = -s)
+ -s, s, -s, s, s, -s, s, -s, -s, -s, -s, -s,
+ // Top face (y = s)
+ -s, s, -s, -s, s, s, s, s, s, s, s, -s,
+ // Bottom face (y = -s)
+ -s, -s, -s, s, -s, -s, s, -s, s, -s, -s, s,
+ // Right face (x = s)
+ s, s, s, s, -s, s, s, -s, -s, s, s, -s,
+ // Left face (x = -s)
+ -s, s, -s, -s, -s, -s, -s, -s, s, -s, s, s
+ };
+ // UV Coordinates (Standard 0,0 to 1,1 for every face)
+ float[] u = {
+ 0,1, 0,0, 1,0, 1,1, // Front
+ 1,1, 0,1, 0,0, 1,0, // Back
+ 0,1, 0,0, 1,0, 1,1, // Top
+ 0,0, 1,0, 1,1, 0,1, // Bottom
+ 0,1, 0,0, 1,0, 1,1, // Right
+ 0,1, 0,0, 1,0, 1,1 // Left
+ };
+
+ // Normals (Pointing straight out from each face)
+ float[] n = {
+ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // Front
+ 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, // Back
+ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // Top
+ 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // Bottom
+ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // Right
+ -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0 // Left
+ };
+
+ // Indices (Two triangles per face)
int[] indices = new int[36];
- return mesh;
+ for (int i = 0; i < 6; i++) {
+ int offset = i * 4;
+ int idx = i * 6;
+ indices[idx + 0] = offset + 0;
+ indices[idx + 1] = offset + 1;
+ indices[idx + 2] = offset + 2;
+ indices[idx + 3] = offset + 2;
+ indices[idx + 4] = offset + 3;
+ indices[idx + 5] = offset + 0;
+ }
+
+ return new Mesh(p, u, n, indices);
}
}
diff --git a/src/main/java/Shader.java b/src/main/java/Shader.java
index 0e7096f..84b2c95 100644
--- a/src/main/java/Shader.java
+++ b/src/main/java/Shader.java
@@ -1,8 +1,23 @@
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+import org.lwjgl.system.MemoryStack;
+
+import java.nio.FloatBuffer;
+import java.util.HashMap;
+import java.util.Vector;
+
import static org.lwjgl.opengl.GL40.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
public class Shader {
+ private static final Logger logger = LogManager.getLogger(Shader.class);
+
private final int id;
+ private final HashMap uniforms = new HashMap<>();
+
public Shader(String vertexPath, String fragmentPath) {
id = glCreateProgram();
@@ -34,6 +49,56 @@ public class Shader {
public void unbind() {
glUseProgram(0);
}
+
+ public void setUniform(String uniformName, Matrix4f data) {
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer fb = stack.mallocFloat(16);
+ data.get(fb);
+ int location = getUniformLocation(uniformName);
+ if (location < 0) {
+ var msg = "Failed to find location for uniform name %s".formatted(uniformName);
+ logger.error(msg);
+ return;
+ }
+ glUniformMatrix4fv(location, false, fb);
+ }
+ }
+
+ public void setUniform(String uniformName, Vector3f data) {
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer fb = stack.mallocFloat(3);
+ data.get(fb);
+ int location = getUniformLocation(uniformName);
+ if (location < 0) {
+ var msg = "Failed to find location for uniform name %s".formatted(uniformName);
+ logger.error(msg);
+ return;
+ }
+ glUniform3fv(location, fb.array());
+ }
+ }
+
+ public void setUniform(String uniformName, float data) {
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer fb = stack.mallocFloat(1);
+ fb.put(data);
+ int location = getUniformLocation(uniformName);
+ if (location < 0) {
+ var msg = "Failed to find location for uniform name %s".formatted(uniformName);
+ logger.error(msg);
+ return;
+ }
+ glUniform1f(location, fb.get(0));
+ }
+ }
+
+ private int getUniformLocation(String uniformName) {
+ if (!uniforms.containsKey(uniformName)) {
+ int location = glGetUniformLocation(id, uniformName);
+ uniforms.put(uniformName, location);
+ }
+ return uniforms.get(uniformName);
+ }
}
diff --git a/src/main/java/Tony.java b/src/main/java/Tony.java
index fde520b..66c1ac6 100644
--- a/src/main/java/Tony.java
+++ b/src/main/java/Tony.java
@@ -1,11 +1,11 @@
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
import org.lwjgl.*;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import org.lwjgl.system.*;
import java.nio.*;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
@@ -13,20 +13,35 @@ import static org.lwjgl.opengl.GL40.*;
import static org.lwjgl.system.MemoryStack.*;
import static org.lwjgl.system.MemoryUtil.*;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
public class Tony {
private long window;
private Shader shader;
+ private Mesh cube;
+ private OrthoCamera camera;
+ private DirectionalLight sun;
- private static final Logger LOGGER = Logger.getLogger( Tony.class.getName() );
+ private static final Logger logger = LogManager.getLogger(Tony.class);
public void run() {
- LOGGER.log(Level.INFO, "Tony version: %s".formatted(Version.getVersionString()));
- LOGGER.log(Level.INFO, "LWJGL version: %s".formatted(org.lwjgl.Version.getVersion()));
+ logger.info("Tony version: %s".formatted(Version.getVersionString()));
+ logger.info("LWJGL version: %s".formatted(org.lwjgl.Version.getVersion()));
init();
// setup game objects
shader = new Shader("/shaders/basic.vert", "/shaders/basic.frag");
+ cube = PrimitiveGenerator.getCube();
+
+ camera = new OrthoCamera(1024.f / 720);
+
+ sun = new DirectionalLight(
+ new Vector3f(-1.0f, -1.0f, -0.5f), // Pointing Down, Left, and slightly Back
+ new Vector3f(1.0f, 1.0f, 0.9f), // Warm yellowish sun
+ 1.2f // Brightness
+ );
loop();
@@ -75,19 +90,37 @@ public class Tony {
} // the stack frame is popped automatically
glfwMakeContextCurrent(window);
+ GL.createCapabilities();
+
+ glViewport(0, 0, 1024, 720);
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() {
- GL.createCapabilities();
+ glClearColor(0.33f, 0.48f, 0.48f, 1.0f);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ Matrix4f modelMatrix = new Matrix4f();
while ( !glfwWindowShouldClose(window) ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ shader.bind();
+
+ modelMatrix.rotateXYZ(0, 0.01f, 0);
+
+ shader.setUniform("projection", camera.getProjection());
+ shader.setUniform("view", camera.getView());
+ shader.setUniform("model", modelMatrix);
+ shader.setUniform("lightDirection", sun.direction);
+ shader.setUniform("lightColor", sun.color);
+ shader.setUniform("lightIntensity", sun.intensity);
+
+ cube.render();
+
+ shader.unbind();
+
glfwSwapBuffers(window);
glfwPollEvents();
diff --git a/src/main/java/Version.java b/src/main/java/Version.java
index 914270d..847e8bb 100644
--- a/src/main/java/Version.java
+++ b/src/main/java/Version.java
@@ -10,5 +10,5 @@ public class Version {
public static final int VERSION_MAJ = 0;
public static final int VERSION_MIN = 0;
- public static final int VERSION_PATCH = 1;
+ public static final int VERSION_PATCH = 2;
}
\ No newline at end of file
diff --git a/src/main/java/Vertex.java b/src/main/java/Vertex.java
index 09b901c..352b82c 100644
--- a/src/main/java/Vertex.java
+++ b/src/main/java/Vertex.java
@@ -5,4 +5,26 @@ public class Vertex {
public Vector3f position;
public Vector2f uv;
public Vector3f norm;
+
+ public static float[] interleaveVertexData(float[] positions, float[] uvs, float[] norms) {
+ int vertexCount = positions.length / 3;
+ float[] result = new float[vertexCount * 8];
+
+ for (int i = 0; i < vertexCount; i++) {
+ result[i * 8] = positions[i * 3];
+ result[i * 8 + 1] = positions[i * 3 + 1];
+ result[i * 8 + 2] = positions[i * 3 + 2];
+
+ // UVs (2 floats)
+ result[i * 8 + 3] = uvs[i * 2];
+ result[i * 8 + 4] = uvs[i * 2 + 1];
+
+ // Normals (3 floats)
+ result[i * 8 + 5] = norms[i * 3];
+ result[i * 8 + 6] = norms[i * 3 + 1];
+ result[i * 8 + 7] = norms[i * 3 + 2];
+ }
+
+ return result;
+ }
}
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..cf7d604
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/shaders/basic.frag b/src/main/resources/shaders/basic.frag
index 2371ee4..01068c2 100644
--- a/src/main/resources/shaders/basic.frag
+++ b/src/main/resources/shaders/basic.frag
@@ -2,6 +2,24 @@
out vec4 color;
+in vec2 texCoord;
+in vec3 normal;
+
+uniform sampler2D texture_diffuse;
+uniform vec3 lightDirection;
+uniform vec3 lightColor;
+uniform float lightIntensity;
+
void main() {
- color = vec4(1.0, 0.0, 0.0, 1.0);
+ vec3 normal = normalize(outNormal);
+ vec3 lightDir = normalize(-lightDirection);
+
+ float diff = max(dot(normal, lightDir), 0.0);
+
+ float ambient = 0.2;
+
+ vec3 diffuse = diff * lightColor * lightIntensity;
+ vec4 texColor = texture(texture_diffuse, texCoord);
+
+ color = vec4(ambient + diffuse, 1.0) * texColor;
}
\ No newline at end of file
diff --git a/src/main/resources/shaders/basic.vert b/src/main/resources/shaders/basic.vert
index 0c0f21a..23410ca 100644
--- a/src/main/resources/shaders/basic.vert
+++ b/src/main/resources/shaders/basic.vert
@@ -1,6 +1,8 @@
#version 400 core
layout (location = 0) in vec3 position;
+layout (location = 1) in vec2 uv;
+layout (location = 2) in vec3
uniform mat4 model;
uniform mat4 view;