commit 38a5aa5a47f1fdaeed03ca14670a65056806bca3 Author: slinky55 Date: Fri Apr 10 01:45:16 2026 -0500 intial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1318d0a --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..86e58e0 --- /dev/null +++ b/pom.xml @@ -0,0 +1,392 @@ + + + 4.0.0 + + me.slinky + Tony + 0.0.1 + + + 22 + 22 + UTF-8 + + 3.4.1 + natives-windows + + + + + + org.lwjgl + lwjgl-bom + ${lwjgl.version} + import + pom + + + + + + + org.lwjgl + lwjgl + + + 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 + ${lwjgl.natives} + + + org.lwjgl + 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 + ${lwjgl.natives} + + + org.lwjgl + 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 + + + + \ No newline at end of file diff --git a/src/main/java/Mesh.java b/src/main/java/Mesh.java new file mode 100644 index 0000000..8b6dee5 --- /dev/null +++ b/src/main/java/Mesh.java @@ -0,0 +1,52 @@ +import org.lwjgl.system.MemoryStack; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.Arrays; +import java.util.List; + +import static org.lwjgl.opengl.GL40.*; + +public class Mesh { + public static final int FLOATS_PER_VERTEX = 8; + public static final int STRIDE = FLOATS_PER_VERTEX * Float.BYTES; + + private int _vao; + private int _vbo; + private int _ebo; + + public void setup(float[] positions, float[] uv, float[] normals, 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); + + // 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); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + } +} diff --git a/src/main/java/PrimitiveGenerator.java b/src/main/java/PrimitiveGenerator.java new file mode 100644 index 0000000..bc40297 --- /dev/null +++ b/src/main/java/PrimitiveGenerator.java @@ -0,0 +1,13 @@ +import org.joml.Vector2f; +import org.joml.Vector3f; + +public class PrimitiveGenerator { + public static Mesh getCube() { + var mesh = new Mesh(); + + Vertex[] vertices = new Vertex[8]; + + int[] indices = new int[36]; + return mesh; + } +} diff --git a/src/main/java/Scene.java b/src/main/java/Scene.java new file mode 100644 index 0000000..05e71df --- /dev/null +++ b/src/main/java/Scene.java @@ -0,0 +1,5 @@ +import java.util.HashMap; + +public class Scene { + private HashMap meshes; +} diff --git a/src/main/java/Shader.java b/src/main/java/Shader.java new file mode 100644 index 0000000..0e7096f --- /dev/null +++ b/src/main/java/Shader.java @@ -0,0 +1,39 @@ +import static org.lwjgl.opengl.GL40.*; + +public class Shader { + private final int id; + + public Shader(String vertexPath, String fragmentPath) { + id = glCreateProgram(); + + if (id == 0) { + throw new RuntimeException("Could not create Shader"); + } + + int vertex = ShaderUtils.createShader(vertexPath, GL_VERTEX_SHADER); + glAttachShader(id, vertex); + int fragment = ShaderUtils.createShader(fragmentPath, GL_FRAGMENT_SHADER); + glAttachShader(id, fragment); + + glLinkProgram(id); + if (glGetProgrami(id, GL_LINK_STATUS) == 0) { + throw new RuntimeException("Error linking shader code: %s".formatted(glGetProgramInfoLog(id))); + } + + glDetachShader(id, vertex); + glDetachShader(id, fragment); + + glDeleteShader(vertex); + glDeleteShader(fragment); + } + + public void bind() { + glUseProgram(id); + } + + public void unbind() { + glUseProgram(0); + } +} + + diff --git a/src/main/java/ShaderUtils.java b/src/main/java/ShaderUtils.java new file mode 100644 index 0000000..9da0c18 --- /dev/null +++ b/src/main/java/ShaderUtils.java @@ -0,0 +1,37 @@ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.stream.Collectors; + +import static org.lwjgl.opengl.GL40.*; + +public class ShaderUtils { + public static String loadShaderSource(String path) { + try (InputStream in = ShaderUtils.class.getResourceAsStream(path)) { + if (in == null) { + throw new RuntimeException("Resource not found %s".formatted(path)); + } + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + return reader.lines().collect(Collectors.joining("\n")); + } catch (IOException e) { + throw new RuntimeException("Failed to load resource: %s".formatted(path), e); + } + } + + public static int createShader(String path, int type) { + String source = ShaderUtils.loadShaderSource(path); + + int shader = glCreateShader(type); + + glShaderSource(shader, source); + glCompileShader(shader); + + if (glGetShaderi(shader, GL_COMPILE_STATUS) == GL_FALSE) { + throw new RuntimeException("Error compiling shader %s: %s".formatted(path, glGetShaderInfoLog(shader))); + } + + return shader; + } +} diff --git a/src/main/java/Tony.java b/src/main/java/Tony.java new file mode 100644 index 0000000..fde520b --- /dev/null +++ b/src/main/java/Tony.java @@ -0,0 +1,107 @@ +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.*; +import static org.lwjgl.opengl.GL40.*; +import static org.lwjgl.system.MemoryStack.*; +import static org.lwjgl.system.MemoryUtil.*; + +public class Tony { + private long window; + private Shader shader; + + private static final Logger LOGGER = Logger.getLogger( Tony.class.getName() ); + + 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())); + + init(); + + // setup game objects + shader = new Shader("/shaders/basic.vert", "/shaders/basic.frag"); + + 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() { + GLFWErrorCallback.createPrint(System.err).set(); + + if ( !glfwInit() ) + throw new IllegalStateException("Unable to initialize 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 + + window = glfwCreateWindow(1024, 720, "Tony %s".formatted(Version.getVersionString()), NULL, NULL); + if ( window == NULL ) + throw new RuntimeException("Failed to create the GLFW window"); + + glfwSetKeyCallback(window, this::glfwKeyCallback); + + // 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 videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + + // Center the window + glfwSetWindowPos( + window, + (videoMode.width() - pWidth.get(0)) / 2, + (videoMode.height() - pHeight.get(0)) / 2 + ); + } // the stack frame is popped automatically + + glfwMakeContextCurrent(window); + + glfwSwapInterval(1); + glfwShowWindow(window); + } + + private void loop() { + GL.createCapabilities(); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + while ( !glfwWindowShouldClose(window) ) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glfwSwapBuffers(window); + + glfwPollEvents(); + } + } + + private void glfwKeyCallback(long window, int key, int scancode, int action, int mods) { + if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE ) + glfwSetWindowShouldClose(window, true); + } + + public static void main(String[] args) { + new Tony().run(); + } +} + + diff --git a/src/main/java/Version.java b/src/main/java/Version.java new file mode 100644 index 0000000..914270d --- /dev/null +++ b/src/main/java/Version.java @@ -0,0 +1,14 @@ +public class Version { + private static String VERSION_STRING = null; + public static String getVersionString() { + if (VERSION_STRING == null) { + VERSION_STRING = "v%d.%d.%d".formatted(VERSION_MAJ, VERSION_MIN, VERSION_PATCH); + } + + return VERSION_STRING; + } + + public static final int VERSION_MAJ = 0; + public static final int VERSION_MIN = 0; + public static final int VERSION_PATCH = 1; +} \ No newline at end of file diff --git a/src/main/java/Vertex.java b/src/main/java/Vertex.java new file mode 100644 index 0000000..09b901c --- /dev/null +++ b/src/main/java/Vertex.java @@ -0,0 +1,8 @@ +import org.joml.Vector3f; +import org.joml.Vector2f; + +public class Vertex { + public Vector3f position; + public Vector2f uv; + public Vector3f norm; +} diff --git a/src/main/resources/shaders/basic.frag b/src/main/resources/shaders/basic.frag new file mode 100644 index 0000000..2371ee4 --- /dev/null +++ b/src/main/resources/shaders/basic.frag @@ -0,0 +1,7 @@ +#version 400 core + +out vec4 color; + +void main() { + color = vec4(1.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/src/main/resources/shaders/basic.vert b/src/main/resources/shaders/basic.vert new file mode 100644 index 0000000..0c0f21a --- /dev/null +++ b/src/main/resources/shaders/basic.vert @@ -0,0 +1,11 @@ +#version 400 core + +layout (location = 0) in vec3 position; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +void main() { + gl_Position = projection * view * model * vec4(position, 1.0); +} \ No newline at end of file