From e32fa9e0955a90f05dc1d0ab6e0d6a370b549cdd Mon Sep 17 00:00:00 2001 From: DaniTheSkunk <> Date: Tue, 13 Dec 2022 02:23:21 +0000 Subject: [PATCH] reimplemented scalers --- com/danitheskunk/skunkworks/Test3D.java | 3 +- .../skunkworks/backends/gl/Filter.java | 37 +- .../skunkworks/backends/gl/FilterFXAA.java | 318 ------------------ .../skunkworks/backends/gl/RenderContext.java | 25 +- .../backends/gl/RenderContext3D.java | 43 ++- .../skunkworks/backends/gl/Scaler.java | 8 +- .../skunkworks/backends/gl/ScalerAspect.java | 62 ++++ .../skunkworks/backends/gl/ScalerInteger.java | 64 ++++ .../skunkworks/backends/gl/ScalerStretch.java | 7 + .../skunkworks/backends/gl/Window.java | 13 +- .../skunkworks/gfx/IRenderContext.java | 2 + .../gfx/threedee/IRenderContext3D.java | 6 +- 12 files changed, 231 insertions(+), 357 deletions(-) delete mode 100644 com/danitheskunk/skunkworks/backends/gl/FilterFXAA.java create mode 100644 com/danitheskunk/skunkworks/backends/gl/ScalerAspect.java create mode 100644 com/danitheskunk/skunkworks/backends/gl/ScalerInteger.java create mode 100644 com/danitheskunk/skunkworks/backends/gl/ScalerStretch.java diff --git a/com/danitheskunk/skunkworks/Test3D.java b/com/danitheskunk/skunkworks/Test3D.java index f11015d..251ef66 100644 --- a/com/danitheskunk/skunkworks/Test3D.java +++ b/com/danitheskunk/skunkworks/Test3D.java @@ -17,7 +17,7 @@ public class Test3D extends BaseGame { Model model; public Test3D() { - super(new Vec2i(1920, 1080), "Skunkworks 3d test"); + super(new Vec2i(1920/4, 1080/4), "Skunkworks 3d test"); System.out.printf("assimp version: %d.%d.%d\n", Assimp.aiGetVersionMajor(), Assimp.aiGetVersionMinor(), @@ -47,6 +47,7 @@ public class Test3D extends BaseGame { @Override protected void render3D(IRenderContext3D rc) { + rc.clear(Color.GRAY); rc.renderModel(model); } diff --git a/com/danitheskunk/skunkworks/backends/gl/Filter.java b/com/danitheskunk/skunkworks/backends/gl/Filter.java index 9ee369d..5087f11 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Filter.java +++ b/com/danitheskunk/skunkworks/backends/gl/Filter.java @@ -1,35 +1,59 @@ package com.danitheskunk.skunkworks.backends.gl; +import com.danitheskunk.skunkworks.Vec2f; import com.danitheskunk.skunkworks.Vec2i; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.glEnd; +import static org.lwjgl.opengl.GL20.glVertexAttrib2f; + public abstract class Filter { private final boolean resizing; protected Framebuffer input; protected Framebuffer output; + protected Program program; + protected Vec2f sizeRatio; - public Filter(Framebuffer input, boolean resizing) { + public Filter(Framebuffer input, Program program, boolean resizing) { this.resizing = resizing; this.input = input; + this.program = program; output = new Framebuffer(input.getSize()); + calcSizeRatio(); } public void apply() { output.bind(); input.bindTexture(); - process(); + program.use(); + preRender(); + glViewport(0, 0, output.getSize().getX(), output.getSize().getY()); + glBegin(GL_TRIANGLES); + //counterclockwise triangles + glVertex2i(-1, 1); + glVertex2i( 1, -1); + glVertex2i(-1, -1); + + glVertex2i( 1, -1); + glVertex2i(-1, 1); + glVertex2i( 1, 1); + glEnd(); } public Framebuffer getOutput() { return output; } - protected abstract void process(); + protected void preRender() { + + } public void setInput(Framebuffer input) { this.input = input; - if(resizing) { + if(!resizing) { output.setSize(input.getSize()); } + calcSizeRatio(); } public void setOutputSize(Vec2i size) { @@ -37,5 +61,10 @@ public abstract class Filter { throw new RuntimeException("this filter doesn't allow output resizing"); } output.setSize(size); + calcSizeRatio(); + } + + private void calcSizeRatio() { + sizeRatio = Vec2f.div(output.getSize(), input.getSize()); } } diff --git a/com/danitheskunk/skunkworks/backends/gl/FilterFXAA.java b/com/danitheskunk/skunkworks/backends/gl/FilterFXAA.java deleted file mode 100644 index b56453e..0000000 --- a/com/danitheskunk/skunkworks/backends/gl/FilterFXAA.java +++ /dev/null @@ -1,318 +0,0 @@ -package com.danitheskunk.skunkworks.backends.gl; - -import com.danitheskunk.skunkworks.backends.gl.Filter; -import com.danitheskunk.skunkworks.backends.gl.Framebuffer; -import com.danitheskunk.skunkworks.backends.gl.Program; -import com.danitheskunk.skunkworks.backends.gl.ProgramCopy; - -import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL20.glUniform2f; - -public class FilterFXAA extends Filter { - private static String vertexSource = """ - layout(location = 0) in vec2 pos; - layout(location = 1) out vec2 out_texCoord; - void main() { - gl_Position = vec4(pos, 0.0f, 1.0f); - out_texCoord = vec2(pos.x * 0.5 + 0.5, pos.y * 0.5 + 0.5); - } - """; - private static String fragmentSource = """ - #if __VERSION__ >= 130 - #define COMPAT_VARYING in - #define COMPAT_TEXTURE texture - out vec4 FragColor; - #else - #define COMPAT_VARYING varying - #define COMPAT_TEXTURE texture2D - #define FragColor gl_FragColor - #endif - - #ifdef GL_ES - #ifdef GL_FRAGMENT_PRECISION_HIGH - precision highp float; - #else - precision mediump float; - #endif - #define COMPAT_PRECISION mediump - #else - #define COMPAT_PRECISION - #endif - - uniform COMPAT_PRECISION int FrameDirection; - uniform COMPAT_PRECISION int FrameCount; - uniform COMPAT_PRECISION vec2 OutputSize; - uniform COMPAT_PRECISION vec2 TextureSize; - uniform COMPAT_PRECISION vec2 InputSize; - layout(binding = 0) uniform sampler2D Texture; - layout(location = 1) COMPAT_VARYING vec2 TEX0; - - // compatibility #defines - #define Source Texture - #define vTexCoord TEX0 - #define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize - #define outsize vec4(OutputSize, 1.0 / OutputSize) - - - - /* - FXAA_PRESET - Choose compile-in knob preset 0-5. - ------------------------------------------------------------------------------ - FXAA_EDGE_THRESHOLD - The minimum amount of local contrast required - to apply algorithm. - 1.0/3.0 - too little - 1.0/4.0 - good start - 1.0/8.0 - applies to more edges - 1.0/16.0 - overkill - ------------------------------------------------------------------------------ - FXAA_EDGE_THRESHOLD_MIN - Trims the algorithm from processing darks. - Perf optimization. - 1.0/32.0 - visible limit (smaller isn't visible) - 1.0/16.0 - good compromise - 1.0/12.0 - upper limit (seeing artifacts) - ------------------------------------------------------------------------------ - FXAA_SEARCH_STEPS - Maximum number of search steps for end of span. - ------------------------------------------------------------------------------ - FXAA_SEARCH_THRESHOLD - Controls when to stop searching. - 1.0/4.0 - seems to be the best quality wise - ------------------------------------------------------------------------------ - FXAA_SUBPIX_TRIM - Controls sub-pixel aliasing removal. - 1.0/2.0 - low removal - 1.0/3.0 - medium removal - 1.0/4.0 - default removal - 1.0/8.0 - high removal - 0.0 - complete removal - ------------------------------------------------------------------------------ - FXAA_SUBPIX_CAP - Insures fine detail is not completely removed. - This is important for the transition of sub-pixel detail, - like fences and wires. - 3.0/4.0 - default (medium amount of filtering) - 7.0/8.0 - high amount of filtering - 1.0 - no capping of sub-pixel aliasing removal - */ - - #ifndef FXAA_PRESET - #define FXAA_PRESET 5 - #endif - #if (FXAA_PRESET == 3) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/16.0) - #define FXAA_SEARCH_STEPS 16 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) - #endif - #if (FXAA_PRESET == 4) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0) - #define FXAA_SEARCH_STEPS 24 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) - #endif - #if (FXAA_PRESET == 5) - #define FXAA_EDGE_THRESHOLD (1.0/8.0) - #define FXAA_EDGE_THRESHOLD_MIN (1.0/24.0) - #define FXAA_SEARCH_STEPS 32 - #define FXAA_SEARCH_THRESHOLD (1.0/4.0) - #define FXAA_SUBPIX_CAP (3.0/4.0) - #define FXAA_SUBPIX_TRIM (1.0/4.0) - #endif - - #define FXAA_SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_SUBPIX_TRIM)) - - // Return the luma, the estimation of luminance from rgb inputs. - // This approximates luma using one FMA instruction, - // skipping normalization and tossing out blue. - // FxaaLuma() will range 0.0 to 2.963210702. - COMPAT_PRECISION float FxaaLuma(vec3 rgb) { - return rgb.y * (0.587/0.299) + rgb.x; - } - - vec3 FxaaLerp3(vec3 a, vec3 b, float amountOfA) { - return (vec3(-amountOfA) * b) + ((a * vec3(amountOfA)) + b); - } - - vec4 FxaaTexOff(sampler2D tex, vec2 pos, ivec2 off, vec2 rcpFrame) { - float x = pos.x + float(off.x) * rcpFrame.x; - float y = pos.y + float(off.y) * rcpFrame.y; - return COMPAT_TEXTURE(tex, vec2(x, y)); - } - - // pos is the output of FxaaVertexShader interpolated across screen. - // xy -> actual texture position {0.0 to 1.0} - // rcpFrame should be a uniform equal to {1.0/frameWidth, 1.0/frameHeight} - vec3 FxaaPixelShader(vec2 pos, sampler2D tex, vec2 rcpFrame) - { - vec3 rgbN = FxaaTexOff(tex, pos.xy, ivec2( 0,-1), rcpFrame).xyz; - vec3 rgbW = FxaaTexOff(tex, pos.xy, ivec2(-1, 0), rcpFrame).xyz; - vec3 rgbM = FxaaTexOff(tex, pos.xy, ivec2( 0, 0), rcpFrame).xyz; - vec3 rgbE = FxaaTexOff(tex, pos.xy, ivec2( 1, 0), rcpFrame).xyz; - vec3 rgbS = FxaaTexOff(tex, pos.xy, ivec2( 0, 1), rcpFrame).xyz; - - float lumaN = FxaaLuma(rgbN); - float lumaW = FxaaLuma(rgbW); - float lumaM = FxaaLuma(rgbM); - float lumaE = FxaaLuma(rgbE); - float lumaS = FxaaLuma(rgbS); - float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE))); - float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE))); - - float range = rangeMax - rangeMin; - if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD)) - { - return rgbM; - } - - vec3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS; - - float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25; - float rangeL = abs(lumaL - lumaM); - float blendL = max(0.0, (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE; - blendL = min(FXAA_SUBPIX_CAP, blendL); - - vec3 rgbNW = FxaaTexOff(tex, pos.xy, ivec2(-1,-1), rcpFrame).xyz; - vec3 rgbNE = FxaaTexOff(tex, pos.xy, ivec2( 1,-1), rcpFrame).xyz; - vec3 rgbSW = FxaaTexOff(tex, pos.xy, ivec2(-1, 1), rcpFrame).xyz; - vec3 rgbSE = FxaaTexOff(tex, pos.xy, ivec2( 1, 1), rcpFrame).xyz; - rgbL += (rgbNW + rgbNE + rgbSW + rgbSE); - rgbL *= vec3(1.0/9.0); - - float lumaNW = FxaaLuma(rgbNW); - float lumaNE = FxaaLuma(rgbNE); - float lumaSW = FxaaLuma(rgbSW); - float lumaSE = FxaaLuma(rgbSE); - - float edgeVert = - abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) + - abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) + - abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE)); - float edgeHorz = - abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) + - abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) + - abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE)); - - bool horzSpan = edgeHorz >= edgeVert; - float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x; - - if(!horzSpan) - { - lumaN = lumaW; - lumaS = lumaE; - } - - float gradientN = abs(lumaN - lumaM); - float gradientS = abs(lumaS - lumaM); - lumaN = (lumaN + lumaM) * 0.5; - lumaS = (lumaS + lumaM) * 0.5; - - if (gradientN < gradientS) - { - lumaN = lumaS; - lumaN = lumaS; - gradientN = gradientS; - lengthSign *= -1.0; - } - - vec2 posN; - posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5); - posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0); - - gradientN *= FXAA_SEARCH_THRESHOLD; - - vec2 posP = posN; - vec2 offNP = horzSpan ? vec2(rcpFrame.x, 0.0) : vec2(0.0, rcpFrame.y); - float lumaEndN = lumaN; - float lumaEndP = lumaN; - bool doneN = false; - bool doneP = false; - posN += offNP * vec2(-1.0, -1.0); - posP += offNP * vec2( 1.0, 1.0); - - for(int i = 0; i < FXAA_SEARCH_STEPS; i++) { - if(!doneN) - { - lumaEndN = FxaaLuma(COMPAT_TEXTURE(tex, posN.xy).xyz); - } - if(!doneP) - { - lumaEndP = FxaaLuma(COMPAT_TEXTURE(tex, posP.xy).xyz); - } - - doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN); - doneP = doneP || (abs(lumaEndP - lumaN) >= gradientN); - - if(doneN && doneP) - { - break; - } - if(!doneN) - { - posN -= offNP; - } - if(!doneP) - { - posP += offNP; - } - } - - float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y; - float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y; - bool directionN = dstN < dstP; - lumaEndN = directionN ? lumaEndN : lumaEndP; - - if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0)) - { - lengthSign = 0.0; - } - - - float spanLength = (dstP + dstN); - dstN = directionN ? dstN : dstP; - float subPixelOffset = (0.5 + (dstN * (-1.0/spanLength))) * lengthSign; - vec3 rgbF = COMPAT_TEXTURE(tex, vec2( - pos.x + (horzSpan ? 0.0 : subPixelOffset), - pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz; - return FxaaLerp3(rgbL, rgbF, blendL); - } - - void main() - { - FragColor = vec4(FxaaPixelShader(vTexCoord, Source, vec2(SourceSize.z, SourceSize.w)), 1.0) * 1.0; - } - """; - - private Program program; - - public FilterFXAA(Framebuffer input) { - super(input, false); - program = new Program(vertexSource, fragmentSource); - } - - @Override - protected void process() { - program.use(); - //ProgramCopy.getInstance().use(); - - var size = input.getSize(); - glUniform2f(program.getUniformLocation("OutputSize"), size.getX(), size.getY()); - glUniform2f(program.getUniformLocation("TextureSize"), size.getX(), size.getY()); - glUniform2f(program.getUniformLocation("InputSize"), size.getX(), size.getY()); - - - glClearColor(0.0f, 0.0f, 0.0f, 1.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/RenderContext.java b/com/danitheskunk/skunkworks/backends/gl/RenderContext.java index bd7f8b6..a615215 100644 --- a/com/danitheskunk/skunkworks/backends/gl/RenderContext.java +++ b/com/danitheskunk/skunkworks/backends/gl/RenderContext.java @@ -22,6 +22,17 @@ class RenderContext extends BaseRenderContext implements IRenderContext { windowSizeIndex = program.getUniformLocation("windowSize"); } + @Override + public void clear(Color color) { + float inv = 1.0f / 255.0f; + glClearColor(color.getR() * inv, + color.getG() * inv, + color.getB() * inv, + color.getA() * inv + ); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + @Override public void drawNineSlice(NineSlice slice, Recti rect) { var centerWidth = Math.max(0, @@ -37,17 +48,15 @@ class RenderContext extends BaseRenderContext implements IRenderContext { var pos = rect.getPos(); drawTexture(pos, slice.getTopLeft()); - drawTexture(new Vec2i(pos.getX() + - slice.getLeft().getWidth() + - centerWidth, - pos.getY() - ), slice.getTopRight()); drawTexture( - new Vec2i(pos.getX(), - pos.getY() + slice.getTop().getHeight() + centerHeight + new Vec2i(pos.getX() + slice.getLeft().getWidth() + centerWidth, + pos.getY() ), - slice.getBottomLeft() + slice.getTopRight() ); + drawTexture(new Vec2i(pos.getX(), + pos.getY() + slice.getTop().getHeight() + centerHeight + ), slice.getBottomLeft()); drawTexture(Vec2i.add(pos, slice.getTopLeft().getSize(), new Vec2i(centerWidth, centerHeight) diff --git a/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java index 0c94a66..9249edd 100644 --- a/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java +++ b/com/danitheskunk/skunkworks/backends/gl/RenderContext3D.java @@ -11,22 +11,43 @@ import com.danitheskunk.skunkworks.gfx.threedee.Model; import static org.lwjgl.opengl.GL46.*; public class RenderContext3D extends BaseRenderContext3D { + public static final Class INTERFACE = IRenderContext3D.class; private final int texCoordIndex; private final int tintIndex; private TextureAtlas textureAtlas; - public static final Class INTERFACE = IRenderContext3D.class; - public RenderContext3D(Program program) { texCoordIndex = program.getAttribLocation("texCoord"); tintIndex = program.getUniformLocation("tint"); } + @Override + public void clear(Color color) { + float inv = 1.0f / 255.0f; + glClearColor( + color.getR() * inv, + color.getG() * inv, + color.getB() * inv, + color.getA() * inv + ); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + @Override public void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); } + @Override + public void preFrame() { + + } + + @Override + public void renderMesh(Mesh mesh) { + renderMesh(mesh, Color.WHITE); + } + @Override public void renderMesh(Mesh mesh, Color tint) { var tex = (Texture) mesh.getTexture(); @@ -76,8 +97,10 @@ public class RenderContext3D extends BaseRenderContext3D { } @Override - public void renderMesh(Mesh mesh) { - renderMesh(mesh, Color.WHITE); + public void renderModel(Model model, Color tint) { + for(var i = 0; i < model.getMeshCount(); ++i) { + renderMesh(model.getMesh(i), tint); + } } @Override @@ -85,13 +108,6 @@ public class RenderContext3D extends BaseRenderContext3D { renderModel(model, Color.WHITE); } - @Override - public void renderModel(Model model, Color tint) { - for(var i = 0; i < model.getMeshCount(); ++i) { - renderMesh(model.getMesh(i), tint); - } - } - @Override public void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3) { glBegin(GL_TRIANGLES); @@ -103,11 +119,6 @@ public class RenderContext3D extends BaseRenderContext3D { glEnd(); } - @Override - public void preFrame() { - - } - public void setTextureAtlas(TextureAtlas textureAtlas) { this.textureAtlas = textureAtlas; } diff --git a/com/danitheskunk/skunkworks/backends/gl/Scaler.java b/com/danitheskunk/skunkworks/backends/gl/Scaler.java index 7ab4f2d..e93c08e 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Scaler.java +++ b/com/danitheskunk/skunkworks/backends/gl/Scaler.java @@ -6,7 +6,9 @@ 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 { +//todo: remove +public class Scaler { + /* private static final String fragmentSource = """ #version 450 layout(location = 1) in vec2 texCoord; @@ -44,7 +46,7 @@ public class Scaler extends Filter { } @Override - protected void process() { + protected void preRender() { var outputSize = output.getSize(); var inputSize = input.getSize(); glViewport(0, 0, outputSize.getX(), outputSize.getY()); @@ -129,4 +131,6 @@ public class Scaler extends Filter { public void setStretchMode(WindowStretchMode stretchMode) { this.stretchMode = stretchMode; } + + */ } diff --git a/com/danitheskunk/skunkworks/backends/gl/ScalerAspect.java b/com/danitheskunk/skunkworks/backends/gl/ScalerAspect.java new file mode 100644 index 0000000..6374b5d --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/ScalerAspect.java @@ -0,0 +1,62 @@ +package com.danitheskunk.skunkworks.backends.gl; + +import static org.lwjgl.opengl.GL46.glUniform1f; +import static org.lwjgl.opengl.GL46.glUniform2f; + +public class ScalerAspect extends Filter { + private static final String fragmentSource = """ + #version 450 + layout(location = 1) in vec2 texCoord; + layout(binding = 0) uniform sampler2D tex; + layout(location = 2) uniform float scale; + layout(location = 3) uniform vec2 offset; + layout(location = 4) uniform vec2 sizeRatio; + out vec4 color; + void main() { + vec2 tc = (texCoord-offset)*sizeRatio/scale; + vec4 col = vec4(0,0,0,0); + if(tc.x <= 1.0 && tc.y <= 1.0 && tc.x >= 0.0 && tc.y >= 0.0) { + col = texture(tex, tc); + } + if(col.a > 0.0) { + color = col; + } + } + """; + private static final String vertexSource = """ + #version 450 + layout(location = 0) in vec2 pos; + layout(location = 1) out vec2 out_texCoord; + void main() { + gl_Position = vec4(pos, 0.0f, 1.0f); + out_texCoord = vec2(pos.x * 0.5 + 0.5, pos.y * 0.5 + 0.5); + } + """; + + public ScalerAspect(Framebuffer input) { + super(input, new Program(vertexSource, fragmentSource), true); + } + + @Override + protected void preRender() { + float scalex = (float) output.getSize().getX() / + (float) input.getSize().getX(); + float scaley = (float) output.getSize().getY() / + (float) input.getSize().getY(); + float scale = Math.min(scalex, scaley); + + float xoff = ( + output.getSize().getX() - input.getSize().getX() * scale + ) / 2 / output.getSize().getX(); + float yoff = ( + output.getSize().getY() - input.getSize().getY() * scale + ) / 2 / output.getSize().getY(); + glUniform1f(program.getUniformLocation("scale"), scale); + glUniform2f(program.getUniformLocation("offset"), xoff, yoff); + glUniform2f( + program.getUniformLocation("sizeRatio"), + (float)sizeRatio.getX(), + (float)sizeRatio.getY() + ); + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/ScalerInteger.java b/com/danitheskunk/skunkworks/backends/gl/ScalerInteger.java new file mode 100644 index 0000000..b67a0ae --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/ScalerInteger.java @@ -0,0 +1,64 @@ +package com.danitheskunk.skunkworks.backends.gl; + +import static org.lwjgl.opengl.GL46.glUniform1f; +import static org.lwjgl.opengl.GL46.glUniform2f; + +public class ScalerInteger extends Filter { + private static final String fragmentSource = """ + #version 450 + layout(location = 1) in vec2 texCoord; + layout(binding = 0) uniform sampler2D tex; + layout(location = 2) uniform float scale; + layout(location = 3) uniform vec2 offset; + layout(location = 4) uniform vec2 sizeRatio; + out vec4 color; + void main() { + vec2 tc = (texCoord-offset)*sizeRatio/scale; + vec4 col = vec4(0,0,0,0); + if(tc.x <= 1.0 && tc.y <= 1.0 && tc.x >= 0.0 && tc.y >= 0.0) { + col = texture(tex, tc); + } + if(col.a > 0.0) { + color = col; + } + } + """; + private static final String vertexSource = """ + #version 450 + layout(location = 0) in vec2 pos; + layout(location = 1) out vec2 out_texCoord; + void main() { + gl_Position = vec4(pos, 0.0f, 1.0f); + out_texCoord = vec2(pos.x * 0.5 + 0.5, pos.y * 0.5 + 0.5); + } + """; + + public ScalerInteger(Framebuffer input) { + super(input, new Program(vertexSource, fragmentSource), true); + } + + @Override + protected void preRender() { + float scalex = (float) output.getSize().getX() / + (float) input.getSize().getX(); + float scaley = (float) output.getSize().getY() / + (float) input.getSize().getY(); + float scale = Math.min(scalex, scaley); + //scale = 1.0f / (int)(1.0f / scale); + scale = Math.max(1.0f, (int)scale); + + float xoff = ( + output.getSize().getX() - input.getSize().getX() * scale + ) / 2 / output.getSize().getX(); + float yoff = ( + output.getSize().getY() - input.getSize().getY() * scale + ) / 2 / output.getSize().getY(); + glUniform1f(program.getUniformLocation("scale"), scale); + glUniform2f(program.getUniformLocation("offset"), xoff, yoff); + glUniform2f( + program.getUniformLocation("sizeRatio"), + (float)sizeRatio.getX(), + (float)sizeRatio.getY() + ); + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/ScalerStretch.java b/com/danitheskunk/skunkworks/backends/gl/ScalerStretch.java new file mode 100644 index 0000000..73ce106 --- /dev/null +++ b/com/danitheskunk/skunkworks/backends/gl/ScalerStretch.java @@ -0,0 +1,7 @@ +package com.danitheskunk.skunkworks.backends.gl; + +public class ScalerStretch extends Filter { + public ScalerStretch(Framebuffer input) { + super(input, ProgramCopy.getInstance(), true); + } +} diff --git a/com/danitheskunk/skunkworks/backends/gl/Window.java b/com/danitheskunk/skunkworks/backends/gl/Window.java index d6dfe14..4c2411c 100644 --- a/com/danitheskunk/skunkworks/backends/gl/Window.java +++ b/com/danitheskunk/skunkworks/backends/gl/Window.java @@ -28,8 +28,8 @@ public class Window extends BaseWindow { private Vec2i windowSize; private final Pipeline2D pipeline2D; private final Pipeline3D pipeline3D; - private final Scaler scaler; - private final FilterFXAA fxaa; + private final Filter scaler; + //private final FilterFXAA fxaa; public Window(Vec2i size, String title, Engine engine) { super(engine); @@ -69,8 +69,9 @@ public class Window extends BaseWindow { pipeline2D = new Pipeline2D(framebuffer, textureAtlas); pipeline3D = new Pipeline3D(framebuffer, textureAtlas); - fxaa = new FilterFXAA(framebuffer); - scaler = new Scaler(fxaa.getOutput()); + //fxaa = new FilterFXAA(framebuffer); + //scaler = new Scaler(framebuffer); + scaler = new ScalerInteger(framebuffer); shouldClose = false; @@ -200,8 +201,8 @@ public class Window extends BaseWindow { @Override public void runScaler() { - fxaa.apply(); - scaler.setStretchMode(stretchMode); + //fxaa.apply(); + //scaler.setStretchMode(stretchMode); scaler.apply(); scaler.getOutput().copyToScreen(); } diff --git a/com/danitheskunk/skunkworks/gfx/IRenderContext.java b/com/danitheskunk/skunkworks/gfx/IRenderContext.java index 3d31d76..607dec7 100644 --- a/com/danitheskunk/skunkworks/gfx/IRenderContext.java +++ b/com/danitheskunk/skunkworks/gfx/IRenderContext.java @@ -28,6 +28,8 @@ public interface IRenderContext { Recti rect, ITexture texture, Color color, boolean repeat ); + void clear(Color color); + void preFrame(); //todo: drawTextureRectangleRepeat } diff --git a/com/danitheskunk/skunkworks/gfx/threedee/IRenderContext3D.java b/com/danitheskunk/skunkworks/gfx/threedee/IRenderContext3D.java index dfe3989..5eda59c 100644 --- a/com/danitheskunk/skunkworks/gfx/threedee/IRenderContext3D.java +++ b/com/danitheskunk/skunkworks/gfx/threedee/IRenderContext3D.java @@ -4,8 +4,12 @@ import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.gfx.Color; public interface IRenderContext3D { + void clear(Color color); + void clearDepth(); + void preFrame(); + void renderMesh(Mesh mesh, Color tint); void renderMesh(Mesh mesh); @@ -15,6 +19,4 @@ public interface IRenderContext3D { void renderModel(Model model); void renderTriangle(Vec3f p1, Vec3f p2, Vec3f p3); - - void preFrame(); }