diff --git a/Test.java b/Test.java index 68f4ee2..d1557fd 100644 --- a/Test.java +++ b/Test.java @@ -6,14 +6,19 @@ public class Test { var window = engine.openWindow(1280, 720, "Skunkworks"); var img = engine.loadImage("C:\\Users\\dani\\Videos\\Screenshot 2022-06-25 17-00-59.png"); //var img = engine.loadImage("C:\\art\\kyoko.png"); + var tex = window.loadTexture("C:\\Users\\dani\\Videos\\Screenshot 2022-06-25 17-00-59.png"); System.out.println(img.getPixel(new Vec2i(60, 60))); while(!window.shouldClose()) { window.tick(); var renderContext = window.renderStart(); - renderContext.drawRectangle( + //renderContext.drawRectangle( + // new Recti(100, 100, 100, 100), + // new Color(150, 200, 250) + //); + renderContext.drawTextureRectangle( new Recti(100, 100, 100, 100), - new Color(150, 200, 250) + tex ); window.renderFinish(renderContext); } diff --git a/com/danitheskunk/skunkworks/Color.java b/com/danitheskunk/skunkworks/Color.java index 10abc8a..bc895d8 100644 --- a/com/danitheskunk/skunkworks/Color.java +++ b/com/danitheskunk/skunkworks/Color.java @@ -2,6 +2,7 @@ package com.danitheskunk.skunkworks; public final class Color { final int r, g, b, a; + public final static Color WHITE = new Color(255, 255, 255); public Color(int r, int g, int b) { this.r = r; diff --git a/com/danitheskunk/skunkworks/Engine.java b/com/danitheskunk/skunkworks/Engine.java index ed0c3ac..4be01b5 100644 --- a/com/danitheskunk/skunkworks/Engine.java +++ b/com/danitheskunk/skunkworks/Engine.java @@ -40,7 +40,7 @@ public class Engine { public IWindow openWindow(int width, int height, String title) { return switch(graphicsBackend) { - case OPENGL -> new GLWindow(width, height, title); + case OPENGL -> new GLWindow(width, height, title, this); }; } } diff --git a/com/danitheskunk/skunkworks/GLRenderContext.java b/com/danitheskunk/skunkworks/GLRenderContext.java index 15e1371..cb37d76 100644 --- a/com/danitheskunk/skunkworks/GLRenderContext.java +++ b/com/danitheskunk/skunkworks/GLRenderContext.java @@ -10,6 +10,8 @@ public class GLRenderContext implements IRenderContext{ var bl = rect.getBottomLeft(); var br = rect.getBottomRight(); + //todo: make work with enabled textures + glColor4f( color.getR() / 255.0f, color.getG() / 255.0f, @@ -26,4 +28,39 @@ public class GLRenderContext implements IRenderContext{ glVertex2i(bl.getX(), bl.getY()); glVertex2i(br.getX(), bl.getY()); } + + @Override + public void drawTextureRectangle(Recti rect, ITexture texture) { + drawTextureRectangle(rect, texture, Color.WHITE); + } + + @Override + public void drawTextureRectangle(Recti rect, ITexture texture, Color color) { + var tl = rect.getTopLeft(); + var tr = rect.getTopRight(); + var bl = rect.getBottomLeft(); + var br = rect.getBottomRight(); + + glColor4f( + color.getR() / 255.0f, + color.getG() / 255.0f, + color.getB() / 255.0f, + color.getA() / 255.0f + ); + + //counter clockwise triangles + glTexCoord2f(0.0f, 1.0f); + glVertex2i(bl.getX(), bl.getY()); + glTexCoord2f(1.0f, 0.0f); + glVertex2i(tr.getX(), tr.getY()); + glTexCoord2f(0.0f, 0.0f); + glVertex2i(tl.getX(), tl.getY()); + + glTexCoord2f(1.0f, 0.0f); + glVertex2i(tr.getX(), tr.getY()); + glTexCoord2f(0.0f, 1.0f); + glVertex2i(bl.getX(), bl.getY()); + glTexCoord2f(1.0f, 1.0f); + glVertex2i(br.getX(), bl.getY()); + } } diff --git a/com/danitheskunk/skunkworks/GLTexture.java b/com/danitheskunk/skunkworks/GLTexture.java new file mode 100644 index 0000000..c25a573 --- /dev/null +++ b/com/danitheskunk/skunkworks/GLTexture.java @@ -0,0 +1,14 @@ +package com.danitheskunk.skunkworks; + +public class GLTexture implements ITexture { + private Recti texArea; + + GLTexture(Recti texArea) { + this.texArea = texArea; + } + + //setters + void setTexArea(Recti texArea) { + this.texArea = texArea; + } +} diff --git a/com/danitheskunk/skunkworks/GLTextureAtlas.java b/com/danitheskunk/skunkworks/GLTextureAtlas.java new file mode 100644 index 0000000..fa4c7fd --- /dev/null +++ b/com/danitheskunk/skunkworks/GLTextureAtlas.java @@ -0,0 +1,53 @@ +package com.danitheskunk.skunkworks; + +import org.lwjgl.BufferUtils; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.opengl.GL11.*; + +class GLTextureAtlas { + private Image img; + private int textureID; + private List textures; + + GLTextureAtlas() { + img = new Image(new Vec2i(32, 32)); + textureID = glGenTextures(); + textures = new ArrayList<>(); + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + } + + ITexture addTexture(Image img) { + //todo: do the actual texture stuff + this.img = img; + update(); + var texture = new GLTexture(new Recti(new Vec2i(0, 0), img.getSize())); + textures.add(texture); + return texture; + } + + void update() { + var buf = BufferUtils.createByteBuffer(img.getData().length); + buf.put(img.getData()); + buf.flip(); + + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA, + img.getWidth(), + img.getHeight(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + buf + ); + } +} diff --git a/com/danitheskunk/skunkworks/GLWindow.java b/com/danitheskunk/skunkworks/GLWindow.java index 80d4720..dca76ab 100644 --- a/com/danitheskunk/skunkworks/GLWindow.java +++ b/com/danitheskunk/skunkworks/GLWindow.java @@ -10,16 +10,20 @@ import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.system.MemoryUtil.NULL; public class GLWindow implements IWindow { + private Engine engine; private GLRenderContext renderContext; private boolean shouldClose; + private GLTextureAtlas textureAtlas; private long window; - public GLWindow(int width, int height, String title) { + public GLWindow(int width, int height, String title, Engine engine) { GLFWErrorCallback.createPrint(System.err).set(); if(!glfwInit()) throw new IllegalStateException("Unable to initialize GLFW"); glfwDefaultWindowHints(); + this.engine = engine; + window = glfwCreateWindow(width, height, title, NULL, NULL); if(window == NULL) throw new RuntimeException("Failed to create GLFW window"); @@ -32,8 +36,10 @@ public class GLWindow implements IWindow { glLoadIdentity(); glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f); glEnable(GL_COLOR); + glEnable(GL_TEXTURE_2D); renderContext = new GLRenderContext(); + textureAtlas = new GLTextureAtlas(); shouldClose = false; @@ -42,6 +48,12 @@ public class GLWindow implements IWindow { System.out.println(GL11.glGetInteger(GL_MAX_TEXTURE_SIZE)); } + @Override + public ITexture loadTexture(String path) { + var img = engine.loadImage(path); + return textureAtlas.addTexture(img); + } + @Override public void renderFinish(IRenderContext context) { glEnd(); diff --git a/com/danitheskunk/skunkworks/IRenderContext.java b/com/danitheskunk/skunkworks/IRenderContext.java index 2499edc..3aede41 100644 --- a/com/danitheskunk/skunkworks/IRenderContext.java +++ b/com/danitheskunk/skunkworks/IRenderContext.java @@ -2,4 +2,6 @@ package com.danitheskunk.skunkworks; public interface IRenderContext { void drawRectangle(Recti rect, Color color); + void drawTextureRectangle(Recti rect, ITexture texture); + void drawTextureRectangle(Recti rect, ITexture texture, Color color); } diff --git a/com/danitheskunk/skunkworks/ITexture.java b/com/danitheskunk/skunkworks/ITexture.java new file mode 100644 index 0000000..b4c83c0 --- /dev/null +++ b/com/danitheskunk/skunkworks/ITexture.java @@ -0,0 +1,5 @@ +package com.danitheskunk.skunkworks; + +public interface ITexture { + +} diff --git a/com/danitheskunk/skunkworks/IWindow.java b/com/danitheskunk/skunkworks/IWindow.java index 3cec2bb..2b17635 100644 --- a/com/danitheskunk/skunkworks/IWindow.java +++ b/com/danitheskunk/skunkworks/IWindow.java @@ -1,6 +1,7 @@ package com.danitheskunk.skunkworks; public interface IWindow { + ITexture loadTexture(String path); void renderFinish(IRenderContext context); IRenderContext renderStart(); boolean shouldClose(); diff --git a/com/danitheskunk/skunkworks/Image.java b/com/danitheskunk/skunkworks/Image.java index 154955d..f3f32b4 100644 --- a/com/danitheskunk/skunkworks/Image.java +++ b/com/danitheskunk/skunkworks/Image.java @@ -28,8 +28,20 @@ public class Image { return data; } + public Vec2i getSize() { + return size; + } + + public int getWidth() { + return size.getX(); + } + + public int getHeight() { + return size.getY(); + } + public Color getPixel(Vec2i pos) { - int i = pos.getX() * 4 + pos.getY() * 4 * width; + int i = pos.getX() * 4 + pos.getY() * 4 * size.getX(); return new Color( ((int)data[i + 0]) & 0xFF, ((int)data[i + 1]) & 0xFF, @@ -39,7 +51,7 @@ public class Image { } public void setPixel(Vec2i pos, Color col) { - int i = pos.getX() * 4 + pos.getY() * 4 * width; + int i = pos.getX() * 4 + pos.getY() * 4 * size.getX(); data[i + 0] = (byte)(col.r & 0xFF); data[i + 1] = (byte)(col.g & 0xFF); data[i + 2] = (byte)(col.b & 0xFF);