From 0f320d00ae26a4d1dbdc075c71a75f8960f79efb Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Mon, 12 Dec 2022 09:54:00 +0000 Subject: [PATCH] created filter system and ported scaler to it --- .../skunkworks/backends/gl/Filter.java | 41 +++++ .../skunkworks/backends/gl/Framebuffer.java | 26 ++- .../skunkworks/backends/gl/Scaler.java | 132 +++++++++++++++ .../skunkworks/backends/gl/Window.java | 152 +----------------- 4 files changed, 200 insertions(+), 151 deletions(-) create mode 100644 com/danitheskunk/skunkworks/backends/gl/Filter.java create mode 100644 com/danitheskunk/skunkworks/backends/gl/Scaler.java diff --git a/com/danitheskunk/skunkworks/backends/gl/Filter.java b/com/danitheskunk/skunkworks/backends/gl/Filter.java new file mode 100644 index 0000000..9ee369d --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/Filter.java @@ -0,0 +1,41 @@ +package com.danitheskunk.skunkworks.backends.gl; + +import com.danitheskunk.skunkworks.Vec2i; + +public abstract class Filter { + private final boolean resizing; + protected Framebuffer input; + protected Framebuffer output; + + public Filter(Framebuffer input, boolean resizing) { + this.resizing = resizing; + this.input = input; + output = new Framebuffer(input.getSize()); + } + + public void apply() { + output.bind(); + input.bindTexture(); + process(); + } + + public Framebuffer getOutput() { + return output; + } + + protected abstract void process(); + + public void setInput(Framebuffer input) { + this.input = input; + if(resizing) { + output.setSize(input.getSize()); + } + } + + public void setOutputSize(Vec2i size) { + if(!resizing) { + throw new RuntimeException("this filter doesn't allow output resizing"); + } + output.setSize(size); + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/Framebuffer.java b/com/danitheskunk/skunkworks/backends/gl/Framebuffer.java index 44f55fc..6e26e5d 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Framebuffer.java +++ b/com/danitheskunk/skunkworks/backends/gl/Framebuffer.java @@ -36,12 +36,7 @@ public class Framebuffer { public void setSize(Vec2i size) { this.size = size; - if(framebuffer != 0) { - glDeleteFramebuffers(framebuffer); - } - if(framebufferTex != 0) { - glDeleteTextures(framebufferTex); - } + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); glBindTexture(GL_TEXTURE_2D, framebufferTex); glTexImage2D(GL_TEXTURE_2D, @@ -82,4 +77,23 @@ public class Framebuffer { 0 ); } + + public void copyToScreen() { + unbind(); + ProgramCopy.getInstance().use(); + bindTexture(); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBegin(GL_TRIANGLES); + //counterclockwise triangles + glVertex2i(-1, 1); + glVertex2i( 1, -1); + glVertex2i(-1, -1); + + glVertex2i( 1, -1); + glVertex2i(-1, 1); + glVertex2i( 1, 1); + glEnd(); + } } diff --git a/com/danitheskunk/skunkworks/backends/gl/Scaler.java b/com/danitheskunk/skunkworks/backends/gl/Scaler.java new file mode 100644 index 0000000..7ab4f2d --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/Scaler.java @@ -0,0 +1,132 @@ +package com.danitheskunk.skunkworks.backends.gl; + +import com.danitheskunk.skunkworks.WindowStretchMode; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL20.glVertexAttrib2f; +import static org.lwjgl.opengl.GL41.glProgramUniform2f; + +public class Scaler extends Filter { + private static final String fragmentSource = """ + #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); + vec4 col = texture(tex, texCoord); + if(col.a > 0.0) { + color = col; + } + //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 static final String vertexSource = """ + #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 final Program program; + private WindowStretchMode stretchMode; + + public Scaler(Framebuffer input) { + super(input, true); + program = new Program(vertexSource, fragmentSource); + } + + @Override + protected void process() { + var outputSize = output.getSize(); + var inputSize = input.getSize(); + glViewport(0, 0, outputSize.getX(), outputSize.getY()); + + program.use(); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glProgramUniform2f( + program.getProgram(), + program.getUniformLocation("windowSize"), + outputSize.getX(), + outputSize.getY() + ); + + int tlx1 = 0; + int tly1 = 0; + int tlx2 = 0; + int tly2 = 0; + + switch(stretchMode) { + case STRETCH -> { + tlx2 = outputSize.getX(); + tly2 = outputSize.getY(); + } + case ASPECT -> { + float scalex = (float) outputSize.getX() / + (float) inputSize.getX(); + float scaley = (float) outputSize.getY() / + (float) inputSize.getY(); + float scale = Math.min(scalex, scaley); + + int xoff = (int) ( + (outputSize.getX() - inputSize.getX() * scale) / 2 + ); + int yoff = (int) ( + (outputSize.getY() - inputSize.getY() * scale) / 2 + ); + + tlx1 = xoff; + tly1 = yoff; + tlx2 = (int) (xoff + inputSize.getX() * scale); + tly2 = (int) (yoff + inputSize.getY() * scale); + } + case INTEGER -> { + int scalex = outputSize.getX() / inputSize.getX(); + int scaley = outputSize.getY() / inputSize.getY(); + int scale = Math.max(1, Math.min(scalex, scaley)); + + int xoff = (outputSize.getX() - inputSize.getX() * scale) / 2; + int yoff = (outputSize.getY() - inputSize.getY() * scale) / 2; + + tlx1 = xoff; + tly1 = yoff; + tlx2 = xoff + inputSize.getX() * scale; + tly2 = yoff + inputSize.getY() * scale; + } + } + + + var texCoordIndex = program.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(); + + } + + public void setStretchMode(WindowStretchMode stretchMode) { + this.stretchMode = stretchMode; + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/Window.java b/com/danitheskunk/skunkworks/backends/gl/Window.java index de8d00f..fc300a7 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Window.java +++ b/com/danitheskunk/skunkworks/backends/gl/Window.java @@ -19,36 +19,8 @@ import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.system.MemoryUtil.NULL; public class Window extends BaseWindow { - private static final 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); - vec4 col = texture(tex, texCoord); - if(col.a > 0.0) { - color = col; - } - //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 static final 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 final Framebuffer framebuffer; - private final Framebuffer framebuffer2; - private final Program programScaler; private final Vec2i size; private final boolean[] stateMouseClicked; private final boolean[] stateMouseDown; @@ -58,6 +30,7 @@ public class Window extends BaseWindow { private Vec2i windowSize; private final Pipeline2D pipeline2D; private final Pipeline3D pipeline3D; + private final Scaler scaler; public Window(Vec2i size, String title, Engine engine) { super(engine); @@ -93,19 +66,11 @@ public class Window extends BaseWindow { glfwSetMouseButtonCallback(window, this::mouseButtonCallback); framebuffer = new Framebuffer(size); - framebuffer2 = new Framebuffer(size); textureAtlas = new TextureAtlas(); - programScaler = new Program(vertexSourceScaler, fragmentSourceScaler); pipeline2D = new Pipeline2D(framebuffer, textureAtlas); pipeline3D = new Pipeline3D(framebuffer, textureAtlas); - - - glProgramUniform2f(programScaler.getProgram(), - programScaler.getUniformLocation("windowSize"), - size.getX(), - size.getY() - ); + scaler = new Scaler(framebuffer); shouldClose = false; @@ -235,113 +200,9 @@ public class Window extends BaseWindow { @Override public void runScaler() { - //glEnd(); - - - //Framebuffer.unbind(); - framebuffer2.bind(); - glViewport(0, 0, windowSize.getX(), windowSize.getY()); - - programScaler.use(); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - framebuffer.bindTexture(); - glProgramUniform2f(programScaler.getProgram(), - programScaler.getUniformLocation("windowSize"), - windowSize.getX(), - windowSize.getY() - ); - - int tlx1 = 0; - int tly1 = 0; - int tlx2 = 0; - int tly2 = 0; - - switch(stretchMode) { - case STRETCH -> { - tlx2 = windowSize.getX(); - tly2 = windowSize.getY(); - } - case ASPECT -> { - float scalex = (float) windowSize.getX() / (float) size.getX(); - float scaley = (float) windowSize.getY() / (float) size.getY(); - float scale = Math.min(scalex, scaley); - - int xoff = (int) ( - (windowSize.getX() - size.getX() * scale) / 2 - ); - int yoff = (int) ( - (windowSize.getY() - size.getY() * scale) / 2 - ); - - tlx1 = xoff; - tly1 = yoff; - tlx2 = (int) (xoff + size.getX() * scale); - tly2 = (int) (yoff + size.getY() * scale); - } - case INTEGER -> { - 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; - - tlx1 = xoff; - tly1 = yoff; - tlx2 = xoff + size.getX() * scale; - 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(); - - Framebuffer.unbind(); - framebuffer2.bindTexture(); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - tlx1 = 0; - tly1 = 0; - tlx2 = windowSize.getX(); - tly2 = windowSize.getY(); - 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(); - - + scaler.setStretchMode(stretchMode); + scaler.apply(); + scaler.getOutput().copyToScreen(); } @Override @@ -379,5 +240,6 @@ public class Window extends BaseWindow { System.out.printf("new window size %d x %d\n", width, height); windowSize = new Vec2i(width, height); glViewport(0, 0, width, height); + scaler.setOutputSize(windowSize); } }