From 87c6bd90e9c8a00fe31fb13165fe3f804c9be112 Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Sat, 5 Nov 2022 23:30:49 +0000 Subject: [PATCH] added integer scaling window --- com/danitheskunk/skunkworks/Test.java | 4 +- .../skunkworks/backends/gl/TextureAtlas.java | 9 +- .../skunkworks/backends/gl/Window.java | 126 +++++++++++++++++- 3 files changed, 128 insertions(+), 11 deletions(-) diff --git a/com/danitheskunk/skunkworks/Test.java b/com/danitheskunk/skunkworks/Test.java index c1beac2..0b68b26 100644 --- a/com/danitheskunk/skunkworks/Test.java +++ b/com/danitheskunk/skunkworks/Test.java @@ -8,7 +8,7 @@ public class Test extends BaseGame { private Terminal term; public Test() { - super(new Vec2i(1280, 720), "Skunkworks"); + super(new Vec2i(1280/2, 720/2), "Skunkworks"); } public static void main(String[] args) { @@ -19,7 +19,7 @@ public class Test extends BaseGame { protected void init() { var fontThin = window.loadFontTileset("fonts\\thin-6x12.png"); var fontThin2 = window.loadFontTileset("fonts\\thin-12x12.png"); - term = new Terminal(new Vec2i(80, 45), fontThin2, fontThin); + term = new Terminal(new Vec2i(80/2, 45/2), fontThin2, fontThin); var c1 = Color.GREEN; var c2 = new Color(0, 128, 0); diff --git a/com/danitheskunk/skunkworks/backends/gl/TextureAtlas.java b/com/danitheskunk/skunkworks/backends/gl/TextureAtlas.java index b54cc63..6a2597e 100644 --- a/com/danitheskunk/skunkworks/backends/gl/TextureAtlas.java +++ b/com/danitheskunk/skunkworks/backends/gl/TextureAtlas.java @@ -17,14 +17,15 @@ class TextureAtlas { private Texture atlasTexture; //for debugging private Image img; private boolean shouldUpdate; + final private int textureID; TextureAtlas() { img = new Image(new Vec2i(32, 32)); - int textureID = glGenTextures(); + textureID = glGenTextures(); textures = new ArrayList<>(); shouldUpdate = true; - glBindTexture(GL_TEXTURE_2D, textureID); + bind(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -32,6 +33,10 @@ class TextureAtlas { } + public void bind() { + glBindTexture(GL_TEXTURE_2D, textureID); + } + ITexture addTexture(Image img) { //todo: do the actual texture stuff //this.img = img; diff --git a/com/danitheskunk/skunkworks/backends/gl/Window.java b/com/danitheskunk/skunkworks/backends/gl/Window.java index 4c7c3e1..e7132f6 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Window.java +++ b/com/danitheskunk/skunkworks/backends/gl/Window.java @@ -8,6 +8,7 @@ import com.danitheskunk.skunkworks.gfx.IRenderContext; import com.danitheskunk.skunkworks.gfx.ITexture; import com.danitheskunk.skunkworks.gfx.Image; import org.lwjgl.glfw.GLFWErrorCallback; +import org.lwjgl.glfw.GLFWWindowCloseCallbackI; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GL11; @@ -44,13 +45,42 @@ public class Window extends BaseWindow { color = texelFetch(tex, ivec2(mod(texCoord, texSize)) + texOffset, 0) * vec4(tint, 1.0f); } """; + + private static String vertexSourceScaler = """ + #version 450 + layout(location = 0) in vec2 pos; + layout(location = 1) in vec2 texCoord; + layout(location = 2) uniform vec2 windowSize; + layout(location = 1) out vec2 out_texCoord; + void main() { + gl_Position = vec4(pos / windowSize * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f); + out_texCoord = texCoord; + } + """; + private static String fragmentSourceScaler = """ + #version 450 + layout(location = 1) in vec2 texCoord; + layout(binding = 0) uniform sampler2D tex; + out vec4 color; + void main() { + //color = vec4(vec2(texCoord).x/1000.f, 0.2f, 0.7f, 1.0f); + color = texture(tex, texCoord); + //color = texelFetch(tex, ivec2(texCoord), 0); + //color = vec4(1.0, 1.0, 1.0, 1.0); + //color = vec4(texCoord.xy, 0.0, 1.0); + } + """; private final Program program; + private final Program programScaler; private final RenderContext renderContext; private final Vec2i size; + private Vec2i windowSize; private final TextureAtlas textureAtlas; private final long window; private boolean debug; private boolean shouldClose; + private final int framebuffer; + private final int framebufferTex; public Window(Vec2i size, String title, Engine engine) { super(engine); @@ -61,6 +91,7 @@ public class Window extends BaseWindow { glfwDefaultWindowHints(); this.debug = false; this.size = size; + this.windowSize = size; window = glfwCreateWindow(size.getX(), size.getY(), title, NULL, NULL); if(window == NULL) throw new RuntimeException( @@ -79,9 +110,36 @@ public class Window extends BaseWindow { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); + glfwSetWindowSizeCallback(window, this::windowSizeCallback); + + + framebuffer = glGenFramebuffers(); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + framebufferTex = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, framebufferTex); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGB, + size.getX(), + size.getY(), + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + 0 + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glFramebufferTexture(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + framebufferTex, + 0 + ); + glDrawBuffers(GL_COLOR_ATTACHMENT0); + textureAtlas = new TextureAtlas(); program = new Program(vertexSource, fragmentSource); - program.use(); + programScaler = new Program(vertexSourceScaler, fragmentSourceScaler); + renderContext = new RenderContext(size, textureAtlas, program.getAttribLocation("texCoord"), @@ -89,8 +147,7 @@ public class Window extends BaseWindow { program.getUniformLocation("texSize"), program.getUniformLocation("tint") ); - glProgramUniform2f( - program.program, + glProgramUniform2f(program.program, program.getUniformLocation("windowSize"), size.getX(), size.getY() @@ -103,6 +160,14 @@ public class Window extends BaseWindow { System.out.println(GL11.glGetInteger(GL_MAX_TEXTURE_SIZE)); } + private void windowSizeCallback(long window, int width, int height) { + System.out.printf("new window size %d x %d\n", width, height); + windowSize = new Vec2i(width, height); + glViewport(0, 0, width, height); + //glLoadIdentity(); + //glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f); + } + @Override public ITexture loadTexture(Image image) { return textureAtlas.addTexture(image); @@ -121,8 +186,7 @@ public class Window extends BaseWindow { for(int y = 0; y < tileCount.getY(); ++y) { for(int x = 0; x < tileCount.getX(); ++x) { - var rect = new Recti( - Vec2i.mul(new Vec2i(x, y), tileSize), + var rect = new Recti(Vec2i.mul(new Vec2i(x, y), tileSize), tileSize ); var img = image.getSubImage(rect); @@ -142,18 +206,66 @@ public class Window extends BaseWindow { @Override public void renderFinish(IRenderContext context) { if(debug) { - context.drawTextureRectangle( - new Recti(Vec2i.ZERO, size), + context.drawTextureRectangle(new Recti(Vec2i.ZERO, size), textureAtlas.getAtlasTexture(), true ); } //glEnd(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, windowSize.getX(), windowSize.getY()); + programScaler.use(); + glClearColor(0.0f, 1.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glBindTexture(GL_TEXTURE_2D, framebufferTex); + glProgramUniform2f(programScaler.program, + programScaler.getUniformLocation("windowSize"), + windowSize.getX(), + windowSize.getY() + ); + + int scalex = windowSize.getX() / size.getX(); + int scaley = windowSize.getY() / size.getY(); + int scale = Math.max(1, Math.min(scalex, scaley)); + + int xoff = (windowSize.getX() - size.getX() * scale) / 2; + int yoff = (windowSize.getY() - size.getY() * scale) / 2; + + int tlx1 = xoff; + int tly1 = yoff; + int tlx2 = xoff + size.getX() * scale; + int tly2 = yoff + size.getY() * scale; + + + var texCoordIndex = programScaler.getAttribLocation("texCoord"); + glBegin(GL_TRIANGLES); + //counterclockwise triangles + glVertexAttrib2f(texCoordIndex, 0, 1); + glVertex2i(tlx1, tly2); + glVertexAttrib2f(texCoordIndex, 1, 0); + glVertex2i(tlx2, tly1); + glVertexAttrib2f(texCoordIndex, 0, 0); + glVertex2i(tlx1, tly1); + + glVertexAttrib2f(texCoordIndex, 1, 0); + glVertex2i(tlx2, tly1); + glVertexAttrib2f(texCoordIndex, 0, 1); + glVertex2i(tlx1, tly2); + glVertexAttrib2f(texCoordIndex, 1, 1); + glVertex2i(tlx2, tly2); + + glEnd(); + glfwSwapBuffers(window); } @Override public IRenderContext renderStart() { + program.use(); + textureAtlas.bind(); + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + glViewport(0, 0, size.getX(), size.getY()); textureAtlas.update(); glClearColor(0.f, 0.f, 0.f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);