mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 08:36:07 +09:00
option for screen filtering mode
This commit is contained in:
@@ -32,7 +32,9 @@
|
|||||||
"MENU_OPTIONS_PARTICLES": "Particles",
|
"MENU_OPTIONS_PARTICLES": "Particles",
|
||||||
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
"MENU_OPTIONS_PERFORMANCE": "Performance",
|
||||||
"MENU_OPTIONS_STREAMERS_LAYOUT": "Chat Overlay",
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "Chat Overlay",
|
||||||
|
"MENU_OPTIONS_NONE" : "None",
|
||||||
|
|
||||||
"MENU_CREDIT_GPL_DNT" : "GPL",
|
"MENU_CREDIT_GPL_DNT" : "GPL",
|
||||||
"MENU_LABEL_JVM_DNT" : "JVM"
|
"MENU_LABEL_JVM_DNT" : "JVM",
|
||||||
|
"MENU_OPTIONS_FILTERING_HQ2X_DNT" : "Hq2x"
|
||||||
}
|
}
|
||||||
@@ -31,5 +31,6 @@
|
|||||||
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
"MENU_OPTIONS_NOTIFICATION_DISPLAY_DURATION": "알림 표시 시간",
|
||||||
"MENU_OPTIONS_PARTICLES": "입자 수",
|
"MENU_OPTIONS_PARTICLES": "입자 수",
|
||||||
"MENU_OPTIONS_PERFORMANCE": "성능",
|
"MENU_OPTIONS_PERFORMANCE": "성능",
|
||||||
"MENU_OPTIONS_STREAMERS_LAYOUT": "채팅창 오버레이"
|
"MENU_OPTIONS_STREAMERS_LAYOUT": "채팅창 오버레이",
|
||||||
|
"MENU_OPTIONS_NONE" : "없음"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import net.torvald.terrarum.langpack.Lang;
|
|||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
import net.torvald.terrarum.modulebasegame.IngameRenderer;
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame;
|
||||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory;
|
||||||
import net.torvald.terrarum.savegame.DiskSkimmer;
|
|
||||||
import net.torvald.terrarum.serialise.WriteConfig;
|
import net.torvald.terrarum.serialise.WriteConfig;
|
||||||
import net.torvald.terrarum.ui.Toolkit;
|
import net.torvald.terrarum.ui.Toolkit;
|
||||||
import net.torvald.terrarum.utils.JsonFetcher;
|
import net.torvald.terrarum.utils.JsonFetcher;
|
||||||
@@ -240,8 +239,12 @@ public class App implements ApplicationListener {
|
|||||||
public static ShaderProgram shaderColLUT;
|
public static ShaderProgram shaderColLUT;
|
||||||
public static ShaderProgram shaderReflect;
|
public static ShaderProgram shaderReflect;
|
||||||
public static ShaderProgram shaderGhastlyWhite;
|
public static ShaderProgram shaderGhastlyWhite;
|
||||||
|
public static ShaderProgram shaderHQ2x;
|
||||||
|
|
||||||
|
private static Texture hq2xLut;
|
||||||
|
|
||||||
public static Mesh fullscreenQuad;
|
public static Mesh fullscreenQuad;
|
||||||
|
public static Mesh fullscreenQuad2x;
|
||||||
private static OrthographicCamera camera;
|
private static OrthographicCamera camera;
|
||||||
private static FlippingSpriteBatch logoBatch;
|
private static FlippingSpriteBatch logoBatch;
|
||||||
public static TextureRegion logo;
|
public static TextureRegion logo;
|
||||||
@@ -392,6 +395,7 @@ public class App implements ApplicationListener {
|
|||||||
appConfig.useVsync(getConfigBoolean("usevsync"));
|
appConfig.useVsync(getConfigBoolean("usevsync"));
|
||||||
appConfig.setResizable(false);
|
appConfig.setResizable(false);
|
||||||
appConfig.setWindowedMode(width, height);
|
appConfig.setWindowedMode(width, height);
|
||||||
|
appConfig.setTransparentFramebuffer(false);
|
||||||
int fpsActive = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
|
int fpsActive = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
|
||||||
if (fpsActive <= 0) fpsActive = GLOBAL_FRAMERATE_LIMIT;
|
if (fpsActive <= 0) fpsActive = GLOBAL_FRAMERATE_LIMIT;
|
||||||
int fpsBack = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfpsidle"));
|
int fpsBack = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfpsidle"));
|
||||||
@@ -473,6 +477,9 @@ public class App implements ApplicationListener {
|
|||||||
);
|
);
|
||||||
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
shaderPassthruRGBA = loadShaderFromClasspath("shaders/gl32spritebatch.vert", "shaders/gl32spritebatch.frag");
|
||||||
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
shaderReflect = loadShaderFromClasspath("shaders/default.vert", "shaders/reflect.frag");
|
||||||
|
shaderHQ2x = loadShaderFromClasspath("shaders/hq2x.vert", "shaders/hq2x.frag");
|
||||||
|
|
||||||
|
hq2xLut = new Texture(Gdx.files.classpath("shaders/hq2x.tga"));
|
||||||
|
|
||||||
fullscreenQuad = new Mesh(
|
fullscreenQuad = new Mesh(
|
||||||
true, 4, 6,
|
true, 4, 6,
|
||||||
@@ -480,7 +487,14 @@ public class App implements ApplicationListener {
|
|||||||
VertexAttribute.ColorUnpacked(),
|
VertexAttribute.ColorUnpacked(),
|
||||||
VertexAttribute.TexCoords(0)
|
VertexAttribute.TexCoords(0)
|
||||||
);
|
);
|
||||||
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
fullscreenQuad2x = new Mesh(
|
||||||
|
true, 4, 6,
|
||||||
|
VertexAttribute.Position(),
|
||||||
|
VertexAttribute.ColorUnpacked(),
|
||||||
|
VertexAttribute.TexCoords(0)
|
||||||
|
);
|
||||||
|
updateFullscreenQuad(fullscreenQuad, scr.getWidth(), scr.getHeight());
|
||||||
|
updateFullscreenQuad(fullscreenQuad2x, scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
// set up renderer info variables
|
// set up renderer info variables
|
||||||
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
renderer = Gdx.graphics.getGLVersion().getRendererString();
|
||||||
@@ -571,11 +585,39 @@ public class App implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shaderPassthruRGBA.bind();
|
if (getConfigString("screenmagnifyingfilter").equals("hq2x")) {
|
||||||
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
int canvasWidth = scr.getWidth() * 2;
|
||||||
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
int canvasHeight = scr.getHeight() * 2;
|
||||||
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
|
||||||
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
shaderHQ2x.bind();
|
||||||
|
shaderHQ2x.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderHQ2x.setUniformi("u_lut", 1);
|
||||||
|
shaderHQ2x.setUniformi("u_texture", 0);
|
||||||
|
shaderHQ2x.setUniformf("u_textureSize", canvasWidth / 2f, canvasHeight / 2f);
|
||||||
|
hq2xLut.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||||
|
hq2xLut.bind(1);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad2x.render(shaderHQ2x, GL20.GL_TRIANGLES);
|
||||||
|
}
|
||||||
|
else if (getConfigDouble("screenmagnifying") < 1.01 || getConfigString("screenmagnifyingfilter").equals("none")) {
|
||||||
|
shaderPassthruRGBA.bind();
|
||||||
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
||||||
|
}
|
||||||
|
else if (getConfigString("screenmagnifyingfilter").equals("bilinear")) {
|
||||||
|
shaderPassthruRGBA.bind();
|
||||||
|
shaderPassthruRGBA.setUniformMatrix("u_projTrans", camera.combined);
|
||||||
|
shaderPassthruRGBA.setUniformi("u_texture", 0);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||||
|
postProcessorOutFBO.getColorBufferTexture().bind(0);
|
||||||
|
fullscreenQuad.render(shaderPassthruRGBA, GL20.GL_TRIANGLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// process resize request
|
// process resize request
|
||||||
if (resizeRequested) {
|
if (resizeRequested) {
|
||||||
@@ -708,7 +750,8 @@ public class App implements ApplicationListener {
|
|||||||
|
|
||||||
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
if (currentScreen != null) currentScreen.resize(scr.getWidth(), scr.getHeight());
|
||||||
TerrarumPostProcessor.INSTANCE.resize(scr.getWidth(), scr.getHeight());
|
TerrarumPostProcessor.INSTANCE.resize(scr.getWidth(), scr.getHeight());
|
||||||
updateFullscreenQuad(scr.getWidth(), scr.getHeight());
|
updateFullscreenQuad(fullscreenQuad, scr.getWidth(), scr.getHeight());
|
||||||
|
updateFullscreenQuad(fullscreenQuad2x, scr.getWidth(), scr.getHeight());
|
||||||
|
|
||||||
|
|
||||||
if (renderFBO == null ||
|
if (renderFBO == null ||
|
||||||
@@ -772,9 +815,13 @@ public class App implements ApplicationListener {
|
|||||||
shaderColLUT.dispose();
|
shaderColLUT.dispose();
|
||||||
shaderReflect.dispose();
|
shaderReflect.dispose();
|
||||||
shaderGhastlyWhite.dispose();
|
shaderGhastlyWhite.dispose();
|
||||||
|
shaderHQ2x.dispose();
|
||||||
|
|
||||||
|
hq2xLut.dispose();
|
||||||
|
|
||||||
CommonResourcePool.INSTANCE.dispose();
|
CommonResourcePool.INSTANCE.dispose();
|
||||||
fullscreenQuad.dispose();
|
fullscreenQuad.dispose();
|
||||||
|
fullscreenQuad2x.dispose();
|
||||||
logoBatch.dispose();
|
logoBatch.dispose();
|
||||||
batch.dispose();
|
batch.dispose();
|
||||||
// shapeRender.dispose();
|
// shapeRender.dispose();
|
||||||
@@ -882,7 +929,6 @@ public class App implements ApplicationListener {
|
|||||||
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/passthrurgb.frag");
|
shaderColLUT = loadShaderFromClasspath("shaders/default.vert", "shaders/passthrurgb.frag");
|
||||||
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
shaderGhastlyWhite = loadShaderFromClasspath("shaders/default.vert", "shaders/ghastlywhite.frag");
|
||||||
|
|
||||||
|
|
||||||
// make gamepad(s)
|
// make gamepad(s)
|
||||||
if (App.getConfigBoolean("usexinput")) {
|
if (App.getConfigBoolean("usexinput")) {
|
||||||
try {
|
try {
|
||||||
@@ -1036,14 +1082,14 @@ public class App implements ApplicationListener {
|
|||||||
logoBatch.setProjectionMatrix(camera.combined);
|
logoBatch.setProjectionMatrix(camera.combined);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFullscreenQuad(int WIDTH, int HEIGHT) { // NOT y-flipped quads!
|
private void updateFullscreenQuad(Mesh mesh, int WIDTH, int HEIGHT) { // NOT y-flipped quads!
|
||||||
fullscreenQuad.setVertices(new float[]{
|
mesh.setVertices(new float[]{
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||||
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
WIDTH, 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||||
WIDTH, HEIGHT, 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
WIDTH, HEIGHT, 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
||||||
0f, HEIGHT, 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
0f, HEIGHT, 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
||||||
});
|
});
|
||||||
fullscreenQuad.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
mesh.setIndices(new short[]{0, 1, 2, 2, 3, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setGamepadButtonLabels() {
|
public static void setGamepadButtonLabels() {
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ object DefaultConfig {
|
|||||||
"inputmethod" to "none",
|
"inputmethod" to "none",
|
||||||
|
|
||||||
"screenmagnifying" to 1.0,
|
"screenmagnifying" to 1.0,
|
||||||
|
"screenmagnifyingfilter" to "none", // "none", "bilinear", "hq2x"
|
||||||
|
|
||||||
"fx_newlight" to false,
|
"fx_newlight" to false,
|
||||||
|
|
||||||
|
|||||||
@@ -196,35 +196,35 @@ object TerrarumPostProcessor : Disposable {
|
|||||||
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Double.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
private fun Float.format(digits: Int) = "%.${digits}f".format(this)
|
||||||
|
|
||||||
private val swizzler = intArrayOf(
|
private val swizzler = floatArrayOf(
|
||||||
1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1,
|
1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f,
|
||||||
1,0,0,0, 0,1,0,0, 0,0,0,1, 0,0,1,0,
|
1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f,
|
||||||
1,0,0,0, 0,0,1,0, 0,1,0,0, 0,0,0,1,
|
1f,0f,0f,0f, 0f,0f,1f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f,
|
||||||
1,0,0,0, 0,0,1,0, 0,0,0,1, 0,1,0,0,
|
1f,0f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f,
|
||||||
1,0,0,0, 0,0,0,1, 0,1,0,0, 0,0,1,0,
|
1f,0f,0f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f, 0f,0f,1f,0f,
|
||||||
1,0,0,0, 0,0,0,1, 0,0,1,0, 0,1,0,0,
|
1f,0f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f, 0f,1f,0f,0f,
|
||||||
|
|
||||||
0,1,0,0, 1,0,0,0, 0,0,1,0, 0,0,0,1,
|
0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f,
|
||||||
0,1,0,0, 1,0,0,0, 0,0,0,1, 0,0,1,0,
|
0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f,
|
||||||
0,1,0,0, 0,0,1,0, 1,0,0,0, 0,0,0,1,
|
0f,1f,0f,0f, 0f,0f,1f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,1,0,0, 0,0,1,0, 0,0,0,1, 1,0,0,0,
|
0f,1f,0f,0f, 0f,0f,1f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f,
|
||||||
0,1,0,0, 0,0,0,1, 1,0,0,0, 0,0,1,0,
|
0f,1f,0f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,1,0,0, 0,0,0,1, 0,0,1,0, 1,0,0,0,
|
0f,1f,0f,0f, 0f,0f,0f,1f, 0f,0f,1f,0f, 1f,0f,0f,0f,
|
||||||
|
|
||||||
0,0,1,0, 1,0,0,0, 0,1,0,0, 0,0,0,1,
|
0f,0f,1f,0f, 1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,0,1,0, 1,0,0,0, 0,0,0,1, 0,1,0,0,
|
0f,0f,1f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f,
|
||||||
0,0,1,0, 0,1,0,0, 1,0,0,0, 0,0,0,1,
|
0f,0f,1f,0f, 0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,0f,1f,
|
||||||
0,0,1,0, 0,1,0,0, 0,0,0,1, 1,0,0,0,
|
0f,0f,1f,0f, 0f,1f,0f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f,
|
||||||
0,0,1,0, 0,0,0,1, 1,0,0,0, 0,1,0,0,
|
0f,0f,1f,0f, 0f,0f,0f,1f, 1f,0f,0f,0f, 0f,1f,0f,0f,
|
||||||
0,0,1,0, 0,0,0,1, 0,1,0,0, 1,0,0,0,
|
0f,0f,1f,0f, 0f,0f,0f,1f, 0f,1f,0f,0f, 1f,0f,0f,0f,
|
||||||
|
|
||||||
0,0,0,1, 1,0,0,0, 0,1,0,0, 0,0,1,0,
|
0f,0f,0f,1f, 1f,0f,0f,0f, 0f,1f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,0,0,1, 1,0,0,0, 0,0,1,0, 0,1,0,0,
|
0f,0f,0f,1f, 1f,0f,0f,0f, 0f,0f,1f,0f, 0f,1f,0f,0f,
|
||||||
0,0,0,1, 0,1,0,0, 1,0,0,0, 0,0,1,0,
|
0f,0f,0f,1f, 0f,1f,0f,0f, 1f,0f,0f,0f, 0f,0f,1f,0f,
|
||||||
0,0,0,1, 0,1,0,0, 0,0,1,0, 1,0,0,0,
|
0f,0f,0f,1f, 0f,1f,0f,0f, 0f,0f,1f,0f, 1f,0f,0f,0f,
|
||||||
0,0,0,1, 0,0,1,0, 1,0,0,0, 0,1,0,0,
|
0f,0f,0f,1f, 0f,0f,1f,0f, 1f,0f,0f,0f, 0f,1f,0f,0f,
|
||||||
0,0,0,1, 0,0,1,0, 0,1,0,0, 1,0,0,0,
|
0f,0f,0f,1f, 0f,0f,1f,0f, 0f,1f,0f,0f, 1f,0f,0f,0f,
|
||||||
).map { it.toFloat() }.toFloatArray()
|
)
|
||||||
|
|
||||||
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
|
private fun postShader(projMat: Matrix4, fbo: FrameBuffer) {
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
import net.torvald.terrarum.CommonResourcePool
|
import net.torvald.terrarum.CommonResourcePool
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.ui.*
|
import net.torvald.terrarum.ui.*
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
|
||||||
@@ -26,9 +27,14 @@ object ControlPanelCommon {
|
|||||||
var CONFIG_SPINNER_WIDTH = 140
|
var CONFIG_SPINNER_WIDTH = 140
|
||||||
var CONFIG_TYPEIN_WIDTH = 240
|
var CONFIG_TYPEIN_WIDTH = 240
|
||||||
var CONFIG_SLIDER_WIDTH = 240
|
var CONFIG_SLIDER_WIDTH = 240
|
||||||
|
var CONFIG_TEXTSEL_WIDTH = 240
|
||||||
|
|
||||||
// @return Pair of <UIItem, Init job for the item>
|
// @return Pair of <UIItem, Init job for the item>
|
||||||
fun makeButton(parent: UICanvas, args: String, x: Int, y: Int, optionName: String): Pair<UIItem, (UIItem, String) -> Unit> {
|
fun makeButton(parent: UICanvas, args: String, x: Int, y: Int, optionNames0: String): Pair<UIItem, (UIItem, String) -> Unit> {
|
||||||
|
val optionNames = optionNames0.split(",")
|
||||||
|
val optionName = optionNames.first()
|
||||||
|
val arg = args.split(',')
|
||||||
|
|
||||||
return if (args.equals("h1") || args.equals("p")) {
|
return if (args.equals("h1") || args.equals("p")) {
|
||||||
(object : UIItem(parent, x, y) {
|
(object : UIItem(parent, x, y) {
|
||||||
override val width = 1
|
override val width = 1
|
||||||
@@ -44,8 +50,26 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (args.startsWith("textsel,")) {
|
||||||
|
val labelFuns = arg.subList(1, arg.size).map { { Lang[it.substringAfter("=")] } }
|
||||||
|
val optionsList = arg.subList(1, arg.size).map { it.substringBefore("=") }
|
||||||
|
|
||||||
|
val initialSel = optionsList.indexOf(App.getConfigString(optionName))
|
||||||
|
|
||||||
|
println("labelFuns = ${labelFuns.map { it.invoke() }}")
|
||||||
|
println("optionsList = $optionsList")
|
||||||
|
println("optionName = $optionName; value = ${App.getConfigString(optionName)}")
|
||||||
|
println("initialSel = $initialSel")
|
||||||
|
|
||||||
|
if (initialSel < 0) throw IllegalArgumentException("config value '${App.getConfigString(optionName)}' for option '$optionName' is not found on the options list")
|
||||||
|
|
||||||
|
UIItemTextSelector(parent, x, y, labelFuns, initialSel, CONFIG_TEXTSEL_WIDTH, clickToShowPalette = false) to { it: UIItem, optionStr: String ->
|
||||||
|
(it as UIItemTextSelector).selectionChangeListener = {
|
||||||
|
App.setConfig(optionStr, optionsList[it])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (args.startsWith("spinner,")) {
|
else if (args.startsWith("spinner,")) {
|
||||||
val arg = args.split(',')
|
|
||||||
UIItemSpinner(parent, x, y, App.getConfigInt(optionName), arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
UIItemSpinner(parent, x, y, App.getConfigInt(optionName), arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
||||||
(it as UIItemSpinner).selectionChangeListener = {
|
(it as UIItemSpinner).selectionChangeListener = {
|
||||||
App.setConfig(optionStr, it)
|
App.setConfig(optionStr, it)
|
||||||
@@ -53,7 +77,6 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (args.startsWith("spinnerd,")) {
|
else if (args.startsWith("spinnerd,")) {
|
||||||
val arg = args.split(',')
|
|
||||||
UIItemSpinner(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), arg[3].toDouble(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${((it as Double)*100).toInt()}%" }) to { it: UIItem, optionStr: String ->
|
UIItemSpinner(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), arg[3].toDouble(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${((it as Double)*100).toInt()}%" }) to { it: UIItem, optionStr: String ->
|
||||||
(it as UIItemSpinner).selectionChangeListener = {
|
(it as UIItemSpinner).selectionChangeListener = {
|
||||||
App.setConfig(optionStr, it)
|
App.setConfig(optionStr, it)
|
||||||
@@ -61,7 +84,6 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (args.startsWith("sliderd,")) {
|
else if (args.startsWith("sliderd,")) {
|
||||||
val arg = args.split(',')
|
|
||||||
UIItemHorzSlider(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), CONFIG_SLIDER_WIDTH) to { it: UIItem, optionStr: String ->
|
UIItemHorzSlider(parent, x, y, App.getConfigDouble(optionName), arg[1].toDouble(), arg[2].toDouble(), CONFIG_SLIDER_WIDTH) to { it: UIItem, optionStr: String ->
|
||||||
(it as UIItemHorzSlider).selectionChangeListener = {
|
(it as UIItemHorzSlider).selectionChangeListener = {
|
||||||
App.setConfig(optionStr, it)
|
App.setConfig(optionStr, it)
|
||||||
@@ -69,7 +91,6 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (args.startsWith("spinnerimul,")) {
|
else if (args.startsWith("spinnerimul,")) {
|
||||||
val arg = args.split(',')
|
|
||||||
val mult = arg[4].toInt()
|
val mult = arg[4].toInt()
|
||||||
UIItemSpinner(parent, x, y, App.getConfigInt(optionName) / mult, arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
UIItemSpinner(parent, x, y, App.getConfigInt(optionName) / mult, arg[1].toInt(), arg[2].toInt(), arg[3].toInt(), CONFIG_SPINNER_WIDTH, numberToTextFunction = { "${it.toLong()}" }) to { it: UIItem, optionStr: String ->
|
||||||
(it as UIItemSpinner).selectionChangeListener = {
|
(it as UIItemSpinner).selectionChangeListener = {
|
||||||
@@ -90,8 +111,8 @@ object ControlPanelCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (args.startsWith("typeinres")) {
|
else if (args.startsWith("typeinres")) {
|
||||||
val keyWidth = optionName.substringBefore(',')
|
val keyWidth = optionNames[0]
|
||||||
val keyHeight = optionName.substringAfter(',')
|
val keyHeight = optionNames[1]
|
||||||
UIItemTextLineInput(parent, x, y, CONFIG_SPINNER_WIDTH,
|
UIItemTextLineInput(parent, x, y, CONFIG_SPINNER_WIDTH,
|
||||||
defaultValue = { "${App.getConfigInt(keyWidth)}x${App.getConfigInt(keyHeight)}" },
|
defaultValue = { "${App.getConfigInt(keyWidth)}x${App.getConfigInt(keyHeight)}" },
|
||||||
maxLen = InputLenCap(9, InputLenCap.CharLenUnit.CODEPOINTS),
|
maxLen = InputLenCap(9, InputLenCap.CharLenUnit.CODEPOINTS),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class UIGraphicsControlPanel(remoCon: UIRemoCon?) : UICanvas() {
|
|||||||
arrayOf("", { Lang["MENU_OPTIONS_DISPLAY"] }, "h1"),
|
arrayOf("", { Lang["MENU_OPTIONS_DISPLAY"] }, "h1"),
|
||||||
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
arrayOf("screenwidth,screenheight", { Lang["MENU_OPTIONS_RESOLUTION"] }, "typeinres"),
|
||||||
arrayOf("screenmagnifying", { Lang["GAME_ACTION_ZOOM"] }, "spinnerd,1.0,2.0,0.05"),
|
arrayOf("screenmagnifying", { Lang["GAME_ACTION_ZOOM"] }, "spinnerd,1.0,2.0,0.05"),
|
||||||
|
arrayOf("screenmagnifyingfilter", { Lang["MENU_OPTIONS_FILTERING_MODE"] }, "textsel,none=MENU_OPTIONS_NONE,bilinear=MENU_OPTIONS_FILTERING_BILINEAR,hq2x=MENU_OPTIONS_FILTERING_HQ2X_DNT"),
|
||||||
arrayOf("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
arrayOf("displayfps", { Lang["MENU_LABEL_FRAMESPERSEC"] }, "spinner,0,300,2"),
|
||||||
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
arrayOf("usevsync", { Lang["MENU_OPTIONS_VSYNC"] }, "toggle"),
|
||||||
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
arrayOf("", { "(${Lang["MENU_LABEL_RESTART_REQUIRED"]})" }, "p"),
|
||||||
|
|||||||
87
src/shaders/hq2x.frag
Normal file
87
src/shaders/hq2x.frag
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// This float value should be defined from the compiling code.
|
||||||
|
// #define SCALE [2, 3, 4].0
|
||||||
|
|
||||||
|
#version 150
|
||||||
|
#ifdef GL_ES
|
||||||
|
#define PRECISION mediump
|
||||||
|
precision PRECISION float;
|
||||||
|
precision PRECISION int;
|
||||||
|
#else
|
||||||
|
#define PRECISION
|
||||||
|
#endif
|
||||||
|
#define SCALE 2.0
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform sampler2D u_lut;
|
||||||
|
uniform vec2 u_textureSize;
|
||||||
|
|
||||||
|
in vec4 v_texCoord[4];
|
||||||
|
|
||||||
|
const mat3 YUV_MATRIX = mat3(0.299, 0.587, 0.114, -0.169, -0.331, 0.5, 0.5, -0.419, -0.081);
|
||||||
|
const vec3 YUV_THRESHOLD = vec3(48.0/255.0, 7.0/255.0, 6.0/255.0);
|
||||||
|
const vec3 YUV_OFFSET = vec3(0, 0.5, 0.5);
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
bool diff(vec3 yuv1, vec3 yuv2) {
|
||||||
|
return any(greaterThan(abs((yuv1 + YUV_OFFSET) - (yuv2 + YUV_OFFSET)), YUV_THRESHOLD));
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 transpose(mat3 val) {
|
||||||
|
mat3 result;
|
||||||
|
result[0][1] = val[1][0];
|
||||||
|
result[0][2] = val[2][0];
|
||||||
|
result[1][0] = val[0][1];
|
||||||
|
result[1][2] = val[2][1];
|
||||||
|
result[2][0] = val[0][2];
|
||||||
|
result[2][1] = val[1][2];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 fp = fract(v_texCoord[0].xy * u_textureSize);
|
||||||
|
vec2 quad = sign(-0.5 + fp);
|
||||||
|
mat3 yuv = transpose(YUV_MATRIX);
|
||||||
|
|
||||||
|
float dx = v_texCoord[0].z;
|
||||||
|
float dy = v_texCoord[0].w;
|
||||||
|
vec3 p1 = texture(u_texture, v_texCoord[0].xy).rgb;
|
||||||
|
vec3 p2 = texture(u_texture, v_texCoord[0].xy + vec2(dx, dy) * quad).rgb;
|
||||||
|
vec3 p3 = texture(u_texture, v_texCoord[0].xy + vec2(dx, 0) * quad).rgb;
|
||||||
|
vec3 p4 = texture(u_texture, v_texCoord[0].xy + vec2(0, dy) * quad).rgb;
|
||||||
|
// Use mat4 instead of mat4x3 here to support GLES.
|
||||||
|
mat4 pixels = mat4(vec4(p1, 0.0), vec4(p2, 0.0), vec4(p3, 0.0), vec4(p4, 0.0));
|
||||||
|
|
||||||
|
vec3 w1 = yuv * texture(u_texture, v_texCoord[1].xw).rgb;
|
||||||
|
vec3 w2 = yuv * texture(u_texture, v_texCoord[1].yw).rgb;
|
||||||
|
vec3 w3 = yuv * texture(u_texture, v_texCoord[1].zw).rgb;
|
||||||
|
|
||||||
|
vec3 w4 = yuv * texture(u_texture, v_texCoord[2].xw).rgb;
|
||||||
|
vec3 w5 = yuv * p1;
|
||||||
|
vec3 w6 = yuv * texture(u_texture, v_texCoord[2].zw).rgb;
|
||||||
|
|
||||||
|
vec3 w7 = yuv * texture(u_texture, v_texCoord[3].xw).rgb;
|
||||||
|
vec3 w8 = yuv * texture(u_texture, v_texCoord[3].yw).rgb;
|
||||||
|
vec3 w9 = yuv * texture(u_texture, v_texCoord[3].zw).rgb;
|
||||||
|
|
||||||
|
bvec3 pattern[3];
|
||||||
|
pattern[0] = bvec3(diff(w5, w1), diff(w5, w2), diff(w5, w3));
|
||||||
|
pattern[1] = bvec3(diff(w5, w4), false , diff(w5, w6));
|
||||||
|
pattern[2] = bvec3(diff(w5, w7), diff(w5, w8), diff(w5, w9));
|
||||||
|
bvec4 cross = bvec4(diff(w4, w2), diff(w2, w6), diff(w8, w4), diff(w6, w8));
|
||||||
|
|
||||||
|
vec2 index;
|
||||||
|
index.x = dot(vec3(pattern[0]), vec3(1, 2, 4)) +
|
||||||
|
dot(vec3(pattern[1]), vec3(8, 0, 16)) +
|
||||||
|
dot(vec3(pattern[2]), vec3(32, 64, 128));
|
||||||
|
index.y = dot(vec4(cross), vec4(1, 2, 4, 8)) * (SCALE * SCALE) +
|
||||||
|
dot(floor(fp * SCALE), vec2(1.0, SCALE));
|
||||||
|
|
||||||
|
vec2 step = vec2(1.0) / vec2(256.0, 16.0 * (SCALE * SCALE));
|
||||||
|
vec2 offset = step / vec2(2.0);
|
||||||
|
vec4 weights = texture(u_lut, index * step + offset);
|
||||||
|
float sum = dot(weights, vec4(1));
|
||||||
|
vec3 res = (pixels * (weights / sum)).rgb;
|
||||||
|
|
||||||
|
fragColor.rgb = res;
|
||||||
|
}
|
||||||
BIN
src/shaders/hq2x.tga
LFS
Normal file
BIN
src/shaders/hq2x.tga
LFS
Normal file
Binary file not shown.
41
src/shaders/hq2x.vert
Normal file
41
src/shaders/hq2x.vert
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#version 150
|
||||||
|
#ifdef GL_ES
|
||||||
|
#define PRECISION mediump
|
||||||
|
precision PRECISION float;
|
||||||
|
precision PRECISION int;
|
||||||
|
#else
|
||||||
|
#define PRECISION
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in vec4 a_position;
|
||||||
|
in vec2 a_texCoord0;
|
||||||
|
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
|
||||||
|
out vec2 u_textureSize;
|
||||||
|
out vec4 v_texCoord[4];
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = u_projTrans * a_position;
|
||||||
|
|
||||||
|
vec2 ps = 1.0/u_textureSize;
|
||||||
|
float dx = ps.x;
|
||||||
|
float dy = ps.y;
|
||||||
|
|
||||||
|
// +----+----+----+
|
||||||
|
// | | | |
|
||||||
|
// | w1 | w2 | w3 |
|
||||||
|
// +----+----+----+
|
||||||
|
// | | | |
|
||||||
|
// | w4 | w5 | w6 |
|
||||||
|
// +----+----+----+
|
||||||
|
// | | | |
|
||||||
|
// | w7 | w8 | w9 |
|
||||||
|
// +----+----+----+
|
||||||
|
|
||||||
|
v_texCoord[0].zw = ps;
|
||||||
|
v_texCoord[0].xy = a_texCoord0.xy;
|
||||||
|
v_texCoord[1] = a_texCoord0.xxxy + vec4(-dx, 0, dx, -dy); // w1 | w2 | w3
|
||||||
|
v_texCoord[2] = a_texCoord0.xxxy + vec4(-dx, 0, dx, 0); // w4 | w5 | w6
|
||||||
|
v_texCoord[3] = a_texCoord0.xxxy + vec4(-dx, 0, dx, dy); // w7 | w8 | w9
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user